Dear team,
This patch makes 'unknown' well-known communities more of a first-class
citizen.
A powerful property of well-known communities is that (often) operators
can implement the feature associated with a given well-known community
through their local routing policy, ahead of time before their vendor
releasing native support in the implementation.
Things that work now:
$ bgpctl show rib community 65535:0
..
$ bgpctl show rib community WELLKNOWN:0
..
$ bgpctl show rib community WELLKNOWN:*
..
$ doas cat /etc/bgpd.conf | grep set
match from any set { community WELLKNOWN:0 community 65535:1 }
Kind regards,
Job
---
usr.sbin/bgpctl/parser.c | 15 +++++++--------
usr.sbin/bgpd/parse.y | 14 ++++++--------
2 files changed, 13 insertions(+), 16 deletions(-)
diff --git a/usr.sbin/bgpctl/parser.c b/usr.sbin/bgpctl/parser.c
index 85300d1cd32..0d1e5d9fb3a 100644
--- a/usr.sbin/bgpctl/parser.c
+++ b/usr.sbin/bgpctl/parser.c
@@ -413,7 +413,7 @@ int parse_addr(const char *, struct
bgpd_addr *);
int parse_asnum(const char *, size_t, u_int32_t *);
int parse_number(const char *, struct parse_result *,
enum token_type);
-int getcommunity(const char *);
+int getcommunity(const char *, int);
int parse_community(const char *, struct parse_result *);
u_int getlargecommunity(const char *);
int parse_largecommunity(const char *, struct parse_result
*);
@@ -927,7 +927,7 @@ parse_number(const char *word, struct parse_result *r, enum
token_type type)
}
int
-getcommunity(const char *s)
+getcommunity(const char *s, int msb)
{
const char *errstr;
u_int16_t uval;
@@ -935,6 +935,9 @@ getcommunity(const char *s)
if (strcmp(s, "*") == 0)
return (COMMUNITY_ANY);
+ if (msb == 1 && strcmp(s, "WELLKNOWN") == 0)
+ return (COMMUNITY_WELLKNOWN);
+
uval = strtonum(s, 0, USHRT_MAX, &errstr);
if (errstr)
errx(1, "Community is %s: %s", errstr, s);
@@ -978,8 +981,8 @@ parse_community(const char *word, struct parse_result *r)
}
*p++ = 0;
- as = getcommunity(word);
- type = getcommunity(p);
+ as = getcommunity(word, 1);
+ type = getcommunity(p, 0);
done:
if (as == 0) {
@@ -994,10 +997,6 @@ done:
case COMMUNITY_BLACKHOLE:
/* valid */
break;
- default:
- /* unknown */
- fprintf(stderr, "Unknown well-known community\n");
- return (0);
}
if ((fs = calloc(1, sizeof(struct filter_set))) == NULL)
diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y
index f0c96051e17..73bdb3a0cb9 100644
--- a/usr.sbin/bgpd/parse.y
+++ b/usr.sbin/bgpd/parse.y
@@ -146,7 +146,7 @@ void copy_filterset(struct filter_set_head
*,
void merge_filter_lists(struct filter_head *, struct filter_head *);
struct filter_rule *get_rule(enum action_types);
-int getcommunity(char *);
+int getcommunity(char *, int);
int parsecommunity(struct filter_community *, char *);
int64_t getlargecommunity(char *);
int parselargecommunity(struct filter_largecommunity *, char *);
@@ -2963,11 +2963,13 @@ symget(const char *nam)
}
int
-getcommunity(char *s)
+getcommunity(char *s, int msb)
{
int val;
const char *errstr;
+ if (msb == 1 && strcmp(s, "WELLKNOWN") == 0)
+ return (COMMUNITY_WELLKNOWN);
if (strcmp(s, "*") == 0)
return (COMMUNITY_ANY);
if (strcmp(s, "neighbor-as") == 0)
@@ -3017,15 +3019,11 @@ parsecommunity(struct filter_community *c, char *s)
}
*p++ = 0;
- if ((i = getcommunity(s)) == COMMUNITY_ERROR)
+ if ((i = getcommunity(s, 1)) == COMMUNITY_ERROR)
return (-1);
- if (i == COMMUNITY_WELLKNOWN) {
- yyerror("Bad community AS number");
- return (-1);
- }
as = i;
- if ((i = getcommunity(p)) == COMMUNITY_ERROR)
+ if ((i = getcommunity(p, 0)) == COMMUNITY_ERROR)
return (-1);
c->as = as;
c->type = i;