Time to fold ext-communities into filter_community so that bgpd can match
multiple ext-communities at the same time as well. Additionally this fixes
parsing some of the ext-community types. Rather large diff again so more
testing and review very welcome. After this more refactoring will be
possible (esp on the attribute matching and altering side).
--
:wq Claudio
PS: diff is agains /usr/src since it includes bgpctl and bgpd diffs.
Index: usr.sbin/bgpctl/bgpctl.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
retrieving revision 1.226
diff -u -p -r1.226 bgpctl.c
--- usr.sbin/bgpctl/bgpctl.c 11 Dec 2018 09:03:36 -0000 1.226
+++ usr.sbin/bgpctl/bgpctl.c 12 Dec 2018 08:29:35 -0000
@@ -281,8 +281,6 @@ main(int argc, char *argv[])
ribreq.as = res->as;
if (res->community.type != COMMUNITY_TYPE_NONE)
ribreq.community = res->community;
- if (res->extcommunity.flags == EXT_COMMUNITY_FLAG_VALID)
- ribreq.extcommunity = res->extcommunity;
ribreq.neighbor = neighbor;
strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib));
ribreq.aid = res->aid;
Index: usr.sbin/bgpctl/parser.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/parser.c,v
retrieving revision 1.87
diff -u -p -r1.87 parser.c
--- usr.sbin/bgpctl/parser.c 28 Nov 2018 08:33:59 -0000 1.87
+++ usr.sbin/bgpctl/parser.c 12 Dec 2018 08:29:35 -0000
@@ -662,8 +662,8 @@ match_token(int *argc, char **argv[], co
case EXTCOM_SUBTYPE:
if (word != NULL && strncmp(word, table[i].keyword,
wordlen) == 0) {
- if (parsesubtype(word, &res.extcommunity.type,
- &res.extcommunity.subtype) == 0)
+ if (parsesubtype(word, &res.community.c.e.type,
+ &res.community.c.e.subtype) == 0)
errx(1, "Bad ext-community unknown "
"type");
match++;
@@ -1084,8 +1084,8 @@ done:
err(1, NULL);
fs->type = ACTION_SET_COMMUNITY;
fs->action.community.type = COMMUNITY_TYPE_BASIC;
- fs->action.community.data1 = as;
- fs->action.community.data2 = type;
+ fs->action.community.c.b.data1 = as;
+ fs->action.community.c.b.data2 = type;
fs->action.community.dflag1 = asflag;
fs->action.community.dflag2 = tflag;
@@ -1160,7 +1160,7 @@ parseextvalue(const char *s, u_int32_t *
s);
return (-1);
}
- *v = ip.s_addr;
+ *v = ntohl(ip.s_addr);
return (EXT_COMMUNITY_TRANS_IPV4);
}
return (-1);
@@ -1177,7 +1177,7 @@ parseextcommunity(const char *word, stru
char *p, *ep;
int type;
- type = r->extcommunity.type;
+ type = r->community.c.e.type;
switch (type) {
case 0xff:
@@ -1208,16 +1208,13 @@ parseextcommunity(const char *word, stru
}
switch (type) {
case EXT_COMMUNITY_TRANS_TWO_AS:
- r->extcommunity.data.ext_as.as = uval;
- r->extcommunity.data.ext_as.val = ullval;
+ r->community.c.e.data1 = uval;
+ r->community.c.e.data2 = ullval;
break;
case EXT_COMMUNITY_TRANS_IPV4:
- r->extcommunity.data.ext_ip.addr.s_addr = uval;
- r->extcommunity.data.ext_ip.val = ullval;
- break;
case EXT_COMMUNITY_TRANS_FOUR_AS:
- r->extcommunity.data.ext_as4.as4 = uval;
- r->extcommunity.data.ext_as4.val = ullval;
+ r->community.c.e.data1 = uval;
+ r->community.c.e.data2 = ullval;
break;
}
break;
@@ -1233,36 +1230,34 @@ parseextcommunity(const char *word, stru
fprintf(stderr, "Bad ext-community: too big\n");
return (0);
}
- r->extcommunity.data.ext_opaq = ullval;
+ r->community.c.e.data2 = ullval;
break;
case EXT_COMMUNITY_NON_TRANS_OPAQUE:
if (strcmp(word, "valid") == 0)
- r->extcommunity.data.ext_opaq = EXT_COMMUNITY_OVS_VALID;
+ r->community.c.e.data2 = EXT_COMMUNITY_OVS_VALID;
else if (strcmp(word, "invalid") == 0)
- r->extcommunity.data.ext_opaq =
- EXT_COMMUNITY_OVS_INVALID;
+ r->community.c.e.data2 = EXT_COMMUNITY_OVS_INVALID;
else if (strcmp(word, "not-found") == 0)
- r->extcommunity.data.ext_opaq =
- EXT_COMMUNITY_OVS_NOTFOUND;
+ r->community.c.e.data2 = EXT_COMMUNITY_OVS_NOTFOUND;
else {
fprintf(stderr, "Bad ext-community value: %s\n", word);
return (0);
}
break;
}
- r->extcommunity.type = type;
+ r->community.c.e.type = type;
/* verify type/subtype combo */
for (cp = iana_ext_comms; cp->subname != NULL; cp++) {
- if (cp->type == r->extcommunity.type &&
- cp->subtype == r->extcommunity.subtype) {
- r->extcommunity.flags |= EXT_COMMUNITY_FLAG_VALID;
+ if (cp->type == r->community.c.e.type &&
+ cp->subtype == r->community.c.e.subtype) {
+ r->community.type = COMMUNITY_TYPE_EXT;;
if ((fs = calloc(1, sizeof(struct filter_set))) == NULL)
err(1, NULL);
- fs->type = ACTION_SET_EXT_COMMUNITY;
- memcpy(&fs->action.ext_community, &r->extcommunity,
- sizeof(struct filter_extcommunity));
+ fs->type = ACTION_SET_COMMUNITY;
+ memcpy(&fs->action.community, &r->community,
+ sizeof(struct filter_community));
TAILQ_INSERT_TAIL(&r->set, fs, entry);
return (1);
@@ -1303,9 +1298,9 @@ parse_largecommunity(const char *word, s
err(1, NULL);
fs->type = ACTION_SET_COMMUNITY;
fs->action.community.type = COMMUNITY_TYPE_LARGE;
- fs->action.community.data1 = as;
- fs->action.community.data2 = ld1;
- fs->action.community.data3 = ld2;
+ fs->action.community.c.l.data1 = as;
+ fs->action.community.c.l.data2 = ld1;
+ fs->action.community.c.l.data3 = ld2;
fs->action.community.dflag1 = asflag;
fs->action.community.dflag2 = ld1flag;
fs->action.community.dflag3 = ld2flag;
Index: usr.sbin/bgpctl/parser.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/parser.h,v
retrieving revision 1.32
diff -u -p -r1.32 parser.h
--- usr.sbin/bgpctl/parser.h 28 Nov 2018 08:33:59 -0000 1.32
+++ usr.sbin/bgpctl/parser.h 12 Dec 2018 08:29:35 -0000
@@ -63,7 +63,6 @@ struct parse_result {
struct filter_as as;
struct filter_set_head set;
struct filter_community community;
- struct filter_extcommunity extcommunity;
char peerdesc[PEER_DESCR_LEN];
char rib[PEER_DESCR_LEN];
char shutcomm[SHUT_COMM_LEN];
Index: usr.sbin/bgpd/bgpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
retrieving revision 1.357
diff -u -p -r1.357 bgpd.h
--- usr.sbin/bgpd/bgpd.h 11 Dec 2018 09:02:14 -0000 1.357
+++ usr.sbin/bgpd/bgpd.h 12 Dec 2018 12:56:51 -0000
@@ -742,30 +742,23 @@ struct filter_community {
u_int8_t dflag1; /* one of set, any, local-as, neighbor-as */
u_int8_t dflag2;
u_int8_t dflag3;
- u_int32_t data1;
- u_int32_t data2;
- u_int32_t data3;
-};
-
-struct filter_extcommunity {
- u_int16_t flags;
- u_int8_t type;
- u_int8_t subtype; /* if extended type */
union {
- struct ext_as {
- u_int16_t as;
- u_int32_t val;
- } ext_as;
- struct ext_as4 {
- u_int32_t as4;
- u_int16_t val;
- } ext_as4;
- struct ext_ip {
- struct in_addr addr;
- u_int16_t val;
- } ext_ip;
- u_int64_t ext_opaq; /* only 48 bits */
- } data;
+ struct basic {
+ u_int32_t data1;
+ u_int32_t data2;
+ } b;
+ struct large {
+ u_int32_t data1;
+ u_int32_t data2;
+ u_int32_t data3;
+ } l;
+ struct ext {
+ u_int32_t data1;
+ u_int64_t data2;
+ u_int8_t type;
+ u_int8_t subtype; /* if extended type */
+ } e;
+ } c;
};
struct ctl_show_rib_request {
@@ -774,7 +767,6 @@ struct ctl_show_rib_request {
struct bgpd_addr prefix;
struct filter_as as;
struct filter_community community;
- struct filter_extcommunity extcommunity;
u_int32_t peerid;
u_int32_t flags;
u_int8_t validation_state;
@@ -929,7 +921,6 @@ struct filter_match {
struct filter_as as;
struct filter_aslen aslen;
struct filter_community community[MAX_COMM_MATCH];
- struct filter_extcommunity ext_community;
struct filter_prefixset prefixset;
struct filter_originset originset;
struct filter_ovs ovs;
@@ -968,8 +959,6 @@ enum action_types {
ACTION_SET_NEXTHOP_SELF,
ACTION_DEL_COMMUNITY,
ACTION_SET_COMMUNITY,
- ACTION_DEL_EXT_COMMUNITY,
- ACTION_SET_EXT_COMMUNITY,
ACTION_PFTABLE,
ACTION_PFTABLE_ID,
ACTION_RTLABEL,
@@ -988,7 +977,6 @@ struct filter_set {
struct bgpd_addr nexthop;
struct nexthop *nh;
struct filter_community community;
- struct filter_extcommunity ext_community;
char pftable[PFTABLE_LEN];
char rtlabel[RTLABEL_LEN];
u_int8_t origin;
Index: usr.sbin/bgpd/parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
retrieving revision 1.365
diff -u -p -r1.365 parse.y
--- usr.sbin/bgpd/parse.y 6 Dec 2018 12:38:01 -0000 1.365
+++ usr.sbin/bgpd/parse.y 12 Dec 2018 12:56:51 -0000
@@ -155,8 +155,7 @@ struct filter_rule *get_rule(enum action
int parsecommunity(struct filter_community *, int, char *);
int parsesubtype(char *, int *, int *);
-int parseextvalue(char *, u_int32_t *);
-int parseextcommunity(struct filter_extcommunity *, char *,
+int parseextcommunity(struct filter_community *, char *,
char *);
static int new_as_set(char *);
static void add_as_set(u_int32_t);
@@ -1078,8 +1077,8 @@ rdomainopts_l : /* empty */
;
rdomainopts : RD STRING {
- struct filter_extcommunity ext;
- u_int64_t rd;
+ struct filter_community ext;
+ u_int64_t rd;
if (parseextcommunity(&ext, "rt", $2) == -1) {
free($2);
@@ -1095,7 +1094,7 @@ rdomainopts : RD STRING {
YYERROR;
}
rd = betoh64(rd) & 0xffffffffffffULL;
- switch (ext.type) {
+ switch (ext.c.e.type) {
case EXT_COMMUNITY_TRANS_TWO_AS:
rd |= (0ULL << 48);
break;
@@ -1117,8 +1116,8 @@ rdomainopts : RD STRING {
if ((set = calloc(1, sizeof(struct filter_set))) ==
NULL)
fatal(NULL);
- set->type = ACTION_SET_EXT_COMMUNITY;
- if (parseextcommunity(&set->action.ext_community,
+ set->type = ACTION_SET_COMMUNITY;
+ if (parseextcommunity(&set->action.community,
$2, $3) == -1) {
free($3);
free($2);
@@ -1135,8 +1134,8 @@ rdomainopts : RD STRING {
if ((set = calloc(1, sizeof(struct filter_set))) ==
NULL)
fatal(NULL);
- set->type = ACTION_SET_EXT_COMMUNITY;
- if (parseextcommunity(&set->action.ext_community,
+ set->type = ACTION_SET_COMMUNITY;
+ if (parseextcommunity(&set->action.community,
$2, $3) == -1) {
free($3);
free($2);
@@ -2160,15 +2159,20 @@ filter_elm : filter_prefix_h {
free($2);
}
| EXTCOMMUNITY STRING STRING {
- if (fmopts.m.ext_community.flags &
- EXT_COMMUNITY_FLAG_VALID) {
- yyerror("\"ext-community\" already specified");
+ int i;
+ for (i = 0; i < MAX_COMM_MATCH; i++) {
+ if (fmopts.m.community[i].type ==
+ COMMUNITY_TYPE_NONE)
+ break;
+ }
+ if (i >= MAX_COMM_MATCH) {
+ yyerror("too many \"community\" filters "
+ "specified");
free($2);
free($3);
YYERROR;
}
-
- if (parseextcommunity(&fmopts.m.ext_community,
+ if (parseextcommunity(&fmopts.m.community[i],
$2, $3) == -1) {
free($2);
free($3);
@@ -2178,14 +2182,19 @@ filter_elm : filter_prefix_h {
free($3);
}
| EXTCOMMUNITY OVS STRING {
- if (fmopts.m.ext_community.flags &
- EXT_COMMUNITY_FLAG_VALID) {
- yyerror("\"ext-community\" already specified");
+ int i;
+ for (i = 0; i < MAX_COMM_MATCH; i++) {
+ if (fmopts.m.community[i].type ==
+ COMMUNITY_TYPE_NONE)
+ break;
+ }
+ if (i >= MAX_COMM_MATCH) {
+ yyerror("too many \"community\" filters "
+ "specified");
free($3);
YYERROR;
}
-
- if (parseextcommunity(&fmopts.m.ext_community,
+ if (parseextcommunity(&fmopts.m.community[i],
"ovs", $3) == -1) {
free($3);
YYERROR;
@@ -2659,11 +2668,11 @@ filter_set_opt : LOCALPREF NUMBER {
if (($$ = calloc(1, sizeof(struct filter_set))) == NULL)
fatal(NULL);
if ($2)
- $$->type = ACTION_DEL_EXT_COMMUNITY;
+ $$->type = ACTION_DEL_COMMUNITY;
else
- $$->type = ACTION_SET_EXT_COMMUNITY;
+ $$->type = ACTION_SET_COMMUNITY;
- if (parseextcommunity(&$$->action.ext_community,
+ if (parseextcommunity(&$$->action.community,
$3, $4) == -1) {
free($3);
free($4);
@@ -2677,11 +2686,11 @@ filter_set_opt : LOCALPREF NUMBER {
if (($$ = calloc(1, sizeof(struct filter_set))) == NULL)
fatal(NULL);
if ($2)
- $$->type = ACTION_DEL_EXT_COMMUNITY;
+ $$->type = ACTION_DEL_COMMUNITY;
else
- $$->type = ACTION_SET_EXT_COMMUNITY;
+ $$->type = ACTION_SET_COMMUNITY;
- if (parseextcommunity(&$$->action.ext_community,
+ if (parseextcommunity(&$$->action.community,
"ovs", $4) == -1) {
free($4);
free($$);
@@ -3479,8 +3488,8 @@ setcommunity(struct filter_community *c,
c->type = COMMUNITY_TYPE_BASIC;
c->dflag1 = asflag;
c->dflag2 = dataflag;
- c->data1 = as;
- c->data2 = data;
+ c->c.b.data1 = as;
+ c->c.b.data2 = data;
}
static int
@@ -3500,9 +3509,9 @@ parselargecommunity(struct filter_commun
}
*q++ = 0;
- if (getcommunity(s, 1, &c->data1, &c->dflag1) == -1 ||
- getcommunity(p, 1, &c->data2, &c->dflag2) == -1 ||
- getcommunity(q, 1, &c->data3, &c->dflag3) == -1)
+ if (getcommunity(s, 1, &c->c.l.data1, &c->dflag1) == -1 ||
+ getcommunity(p, 1, &c->c.l.data2, &c->dflag2) == -1 ||
+ getcommunity(q, 1, &c->c.l.data3, &c->dflag3) == -1)
return (-1);
c->type = COMMUNITY_TYPE_LARGE;
return (0);
@@ -3578,28 +3587,51 @@ parsesubtype(char *name, int *type, int
return (found);
}
-int
-parseextvalue(char *s, u_int32_t *v)
+static int
+parseextvalue(int type, char *s, u_int32_t *v)
{
const char *errstr;
char *p;
struct in_addr ip;
u_int32_t uvalh = 0, uval;
- if ((p = strchr(s, '.')) == NULL) {
+ if (type != -1) {
+ /* nothing */
+ } else if ((p = strchr(s, '.')) == NULL) {
/* AS_PLAIN number (4 or 2 byte) */
- uval = strtonum(s, 0, UINT_MAX, &errstr);
+ strtonum(s, 0, USHRT_MAX, &errstr);
+ if (errstr == NULL)
+ type = EXT_COMMUNITY_TRANS_TWO_AS;
+ else
+ type = EXT_COMMUNITY_TRANS_FOUR_AS;
+ } else if (strchr(p + 1, '.') == NULL) {
+ /* AS_DOT number (4-byte) */
+ type = EXT_COMMUNITY_TRANS_FOUR_AS;
+ } else {
+ /* more than one dot -> IP address */
+ type = EXT_COMMUNITY_TRANS_IPV4;
+ }
+
+ switch (type) {
+ case EXT_COMMUNITY_TRANS_TWO_AS:
+ uval = strtonum(s, 0, USHRT_MAX, &errstr);
if (errstr) {
yyerror("Bad ext-community %s is %s", s, errstr);
return (-1);
}
*v = uval;
- if (uval <= USHRT_MAX)
- return (EXT_COMMUNITY_TRANS_TWO_AS);
- else
- return (EXT_COMMUNITY_TRANS_FOUR_AS);
- } else if (strchr(p + 1, '.') == NULL) {
- /* AS_DOT number (4-byte) */
+ break;
+ case EXT_COMMUNITY_TRANS_FOUR_AS:
+ if ((p = strchr(s, '.')) == NULL) {
+ uval = strtonum(s, 0, UINT_MAX, &errstr);
+ if (errstr) {
+ yyerror("Bad ext-community %s is %s", s,
+ errstr);
+ return (-1);
+ }
+ *v = uval;
+ break;
+ }
*p++ = '\0';
uvalh = strtonum(s, 0, USHRT_MAX, &errstr);
if (errstr) {
@@ -3612,21 +3644,20 @@ parseextvalue(char *s, u_int32_t *v)
return (-1);
}
*v = uval | (uvalh << 16);
- return (EXT_COMMUNITY_TRANS_FOUR_AS);
- } else {
- /* more than one dot -> IP address */
+ break;
+ case EXT_COMMUNITY_TRANS_IPV4:
if (inet_aton(s, &ip) == 0) {
yyerror("Bad ext-community %s not parseable", s);
return (-1);
}
- *v = ip.s_addr;
- return (EXT_COMMUNITY_TRANS_IPV4);
+ *v = ntohl(ip.s_addr);
+ break;
}
- return (-1);
+ return (type);
}
int
-parseextcommunity(struct filter_extcommunity *c, char *t, char *s)
+parseextcommunity(struct filter_community *c, char *t, char *s)
{
const struct ext_comm_pairs *cp;
const char *errstr;
@@ -3641,13 +3672,16 @@ parseextcommunity(struct filter_extcommu
}
switch (type) {
+ case EXT_COMMUNITY_TRANS_TWO_AS:
+ case EXT_COMMUNITY_TRANS_FOUR_AS:
+ case EXT_COMMUNITY_TRANS_IPV4:
case -1:
if ((p = strchr(s, ':')) == NULL) {
yyerror("Bad ext-community %s", s);
return (-1);
}
*p++ = '\0';
- if ((type = parseextvalue(s, &uval)) == -1)
+ if ((type = parseextvalue(type, s, &uval)) == -1)
return (-1);
switch (type) {
case EXT_COMMUNITY_TRANS_TWO_AS:
@@ -3664,20 +3698,8 @@ parseextcommunity(struct filter_extcommu
yyerror("Bad ext-community %s is %s", p, errstr);
return (-1);
}
- switch (type) {
- case EXT_COMMUNITY_TRANS_TWO_AS:
- c->data.ext_as.as = uval;
- c->data.ext_as.val = ullval;
- break;
- case EXT_COMMUNITY_TRANS_IPV4:
- c->data.ext_ip.addr.s_addr = uval;
- c->data.ext_ip.val = ullval;
- break;
- case EXT_COMMUNITY_TRANS_FOUR_AS:
- c->data.ext_as4.as4 = uval;
- c->data.ext_as4.val = ullval;
- break;
- }
+ c->c.e.data1 = uval;
+ c->c.e.data2 = ullval;
break;
case EXT_COMMUNITY_TRANS_OPAQUE:
case EXT_COMMUNITY_TRANS_EVPN:
@@ -3691,28 +3713,28 @@ parseextcommunity(struct filter_extcommu
yyerror("Bad ext-community value too big");
return (-1);
}
- c->data.ext_opaq = ullval;
+ c->c.e.data2 = ullval;
break;
case EXT_COMMUNITY_NON_TRANS_OPAQUE:
if (strcmp(s, "valid") == 0)
- c->data.ext_opaq = EXT_COMMUNITY_OVS_VALID;
+ c->c.e.data2 = EXT_COMMUNITY_OVS_VALID;
else if (strcmp(s, "invalid") == 0)
- c->data.ext_opaq = EXT_COMMUNITY_OVS_INVALID;
+ c->c.e.data2 = EXT_COMMUNITY_OVS_INVALID;
else if (strcmp(s, "not-found") == 0)
- c->data.ext_opaq = EXT_COMMUNITY_OVS_NOTFOUND;
+ c->c.e.data2 = EXT_COMMUNITY_OVS_NOTFOUND;
else {
yyerror("Bad ext-community %s", s);
return (-1);
}
break;
}
- c->type = type;
- c->subtype = subtype;
+ c->c.e.type = type;
+ c->c.e.subtype = subtype;
/* verify type/subtype combo */
for (cp = iana_ext_comms; cp->subname != NULL; cp++) {
if (cp->type == type && cp->subtype == subtype) {
- c->flags |= EXT_COMMUNITY_FLAG_VALID;
+ c->type = COMMUNITY_TYPE_EXT;
return (0);
}
}
@@ -4206,18 +4228,6 @@ filterset_add(struct filter_set_head *sh
sizeof(s->action.community)) == 0)
break;
continue;
- case ACTION_SET_EXT_COMMUNITY:
- case ACTION_DEL_EXT_COMMUNITY:
- if (memcmp(&s->action.ext_community,
- &t->action.ext_community,
- sizeof(s->action.ext_community)) < 0) {
- TAILQ_INSERT_BEFORE(t, s, entry);
- return;
- } else if (memcmp(&s->action.ext_community,
- &t->action.ext_community,
- sizeof(s->action.ext_community)) == 0)
- break;
- continue;
case ACTION_SET_NEXTHOP:
/* only last nexthop per AF matters */
if (s->action.nexthop.aid <
@@ -4288,11 +4298,6 @@ merge_filterset(struct filter_set_head *
yyerror("community is already set");
else if (s->type == ACTION_DEL_COMMUNITY)
yyerror("community will already be deleted");
- else if (s->type == ACTION_SET_EXT_COMMUNITY)
- yyerror("ext-community is already set");
- else if (s->type == ACTION_DEL_EXT_COMMUNITY)
- yyerror(
- "ext-community will already be deleted");
else
yyerror("redefining set parameter %s",
filterset_name(s->type));
Index: usr.sbin/bgpd/printconf.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v
retrieving revision 1.124
diff -u -p -r1.124 printconf.c
--- usr.sbin/bgpd/printconf.c 28 Nov 2018 08:32:27 -0000 1.124
+++ usr.sbin/bgpd/printconf.c 12 Dec 2018 12:56:51 -0000
@@ -32,8 +32,6 @@
void print_prefix(struct filter_prefix *p);
const char *community_type(struct filter_community *c);
void print_community(struct filter_community *c);
-void print_largecommunity(int64_t, int64_t, int64_t);
-void print_extcommunity(struct filter_extcommunity *);
void print_origin(u_int8_t);
void print_set(struct filter_set_head *);
void print_mainconf(struct bgpd_config *);
@@ -113,6 +111,8 @@ community_type(struct filter_community *
return "community";
case COMMUNITY_TYPE_LARGE:
return "large-community";
+ case COMMUNITY_TYPE_EXT:
+ return "ext-community";
default:
return "???";
}
@@ -121,6 +121,8 @@ community_type(struct filter_community *
void
print_community(struct filter_community *c)
{
+ struct in_addr addr;
+
switch (c->type) {
case COMMUNITY_TYPE_BASIC:
switch (c->dflag1) {
@@ -134,7 +136,7 @@ print_community(struct filter_community
printf("local-as:");
break;
default:
- printf("%u:", c->data1);
+ printf("%u:", c->c.b.data1);
break;
}
switch (c->dflag2) {
@@ -148,7 +150,7 @@ print_community(struct filter_community
printf("local-as ");
break;
default:
- printf("%u ", c->data2);
+ printf("%u ", c->c.b.data2);
break;
}
break;
@@ -164,7 +166,7 @@ print_community(struct filter_community
printf("local-as:");
break;
default:
- printf("%u:", c->data1);
+ printf("%u:", c->c.l.data1);
break;
}
switch (c->dflag2) {
@@ -178,7 +180,7 @@ print_community(struct filter_community
printf("local-as:");
break;
default:
- printf("%u:", c->data2);
+ printf("%u:", c->c.l.data2);
break;
}
switch (c->dflag3) {
@@ -192,50 +194,44 @@ print_community(struct filter_community
printf("local-as ");
break;
default:
- printf("%u ", c->data3);
+ printf("%u ", c->c.l.data3);
break;
}
break;
- }
-}
-
-void
-print_extcommunity(struct filter_extcommunity *c)
-{
- printf("%s ", log_ext_subtype(c->type, c->subtype));
-
- switch (c->type) {
- case EXT_COMMUNITY_TRANS_TWO_AS:
- printf("%hu:%u ", c->data.ext_as.as, c->data.ext_as.val);
- break;
- case EXT_COMMUNITY_TRANS_IPV4:
- printf("%s:%u ", inet_ntoa(c->data.ext_ip.addr),
- c->data.ext_ip.val);
- break;
- case EXT_COMMUNITY_TRANS_FOUR_AS:
- printf("%s:%u ", log_as(c->data.ext_as4.as4),
- c->data.ext_as.val);
- break;
- case EXT_COMMUNITY_TRANS_OPAQUE:
- case EXT_COMMUNITY_TRANS_EVPN:
- printf("0x%llx ", c->data.ext_opaq);
- break;
- case EXT_COMMUNITY_NON_TRANS_OPAQUE:
- switch (c->data.ext_opaq) {
- case EXT_COMMUNITY_OVS_VALID:
- printf("valid ");
- break;
- case EXT_COMMUNITY_OVS_NOTFOUND:
- printf("not-found ");
+ case COMMUNITY_TYPE_EXT:
+ printf("%s ", log_ext_subtype(c->c.e.type, c->c.e.subtype));
+ switch (c->c.e.type) {
+ case EXT_COMMUNITY_TRANS_TWO_AS:
+ case EXT_COMMUNITY_TRANS_FOUR_AS:
+ printf("%s:%llu ", log_as(c->c.e.data1),
+ c->c.e.data2);
+ break;
+ case EXT_COMMUNITY_TRANS_IPV4:
+ addr.s_addr = htonl(c->c.e.data1);
+ printf("%s:%llu ", inet_ntoa(addr),
+ c->c.e.data2);
+ break;
+ case EXT_COMMUNITY_TRANS_OPAQUE:
+ case EXT_COMMUNITY_TRANS_EVPN:
+ printf("0x%llx ", c->c.e.data2);
+ break;
+ case EXT_COMMUNITY_NON_TRANS_OPAQUE:
+ switch (c->c.e.data2) {
+ case EXT_COMMUNITY_OVS_VALID:
+ printf("valid ");
+ break;
+ case EXT_COMMUNITY_OVS_NOTFOUND:
+ printf("not-found ");
+ break;
+ case EXT_COMMUNITY_OVS_INVALID:
+ printf("invalid ");
+ break;
+ }
break;
- case EXT_COMMUNITY_OVS_INVALID:
- printf("invalid ");
+ default:
+ printf("0x%llx ", c->c.e.data2);
break;
}
- break;
- default:
- printf("0x%llx ", c->data.ext_opaq);
- break;
}
}
@@ -326,14 +322,6 @@ print_set(struct filter_set_head *set)
/* not possible */
printf("king bula saiz: config broken");
break;
- case ACTION_SET_EXT_COMMUNITY:
- printf("ext-community ");
- print_extcommunity(&s->action.ext_community);
- break;
- case ACTION_DEL_EXT_COMMUNITY:
- printf("ext-community delete ");
- print_extcommunity(&s->action.ext_community);
- break;
}
}
printf("}");
@@ -391,7 +379,7 @@ print_rdomain_targets(struct filter_set_
struct filter_set *s;
TAILQ_FOREACH(s, set, entry) {
printf("\t%s ", tgt);
- print_extcommunity(&s->action.ext_community);
+ print_community(&s->action.community);
printf("\n");
}
}
@@ -847,10 +835,6 @@ print_rule(struct peer *peer_l, struct f
printf("%s ", community_type(c));
print_community(c);
}
- }
- if (r->match.ext_community.flags & EXT_COMMUNITY_FLAG_VALID) {
- printf("ext-community ");
- print_extcommunity(&r->match.ext_community);
}
print_set(&r->set);
Index: usr.sbin/bgpd/rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.452
diff -u -p -r1.452 rde.c
--- usr.sbin/bgpd/rde.c 11 Dec 2018 09:02:14 -0000 1.452
+++ usr.sbin/bgpd/rde.c 12 Dec 2018 12:56:51 -0000
@@ -2229,10 +2229,11 @@ rde_dump_filter(struct prefix *p, struct
if (!community_large_match(asp, &req->community, NULL))
return;
break;
+ case COMMUNITY_TYPE_EXT:
+ if (!community_ext_match(asp, &req->community, 0))
+ return;
+ break;
}
- if (req->extcommunity.flags == EXT_COMMUNITY_FLAG_VALID &&
- !community_ext_match(asp, &req->extcommunity, 0))
- return;
if (!ovs_match(p, req->flags))
return;
rde_dump_rib_as(p, asp, req->pid, req->flags);
@@ -2436,7 +2437,7 @@ rde_rdomain_import(struct rde_aspath *as
struct filter_set *s;
TAILQ_FOREACH(s, &rd->import, entry) {
- if (community_ext_match(asp, &s->action.ext_community, 0))
+ if (community_match(asp, &s->action.community, 0))
return (1);
}
return (0);
Index: usr.sbin/bgpd/rde.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
retrieving revision 1.204
diff -u -p -r1.204 rde.h
--- usr.sbin/bgpd/rde.h 11 Dec 2018 09:02:14 -0000 1.204
+++ usr.sbin/bgpd/rde.h 12 Dec 2018 12:56:51 -0000
@@ -375,12 +375,12 @@ int community_large_set(struct rde_aspa
void community_large_delete(struct rde_aspath *, struct filter_community *,
struct rde_peer *);
int community_ext_match(struct rde_aspath *,
- struct filter_extcommunity *, u_int16_t);
+ struct filter_community *, struct rde_peer *);
int community_ext_set(struct rde_aspath *,
- struct filter_extcommunity *, u_int16_t);
+ struct filter_community *, struct rde_peer *);
void community_ext_delete(struct rde_aspath *,
- struct filter_extcommunity *, u_int16_t);
-int community_ext_conv(struct filter_extcommunity *, u_int16_t,
+ struct filter_community *, struct rde_peer *);
+int community_ext_conv(struct filter_community *, struct rde_peer *,
u_int64_t *);
u_char *community_ext_delete_non_trans(u_char *, u_int16_t, u_int16_t *);
Index: usr.sbin/bgpd/rde_attr.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_attr.c,v
retrieving revision 1.114
diff -u -p -r1.114 rde_attr.c
--- usr.sbin/bgpd/rde_attr.c 11 Dec 2018 09:02:14 -0000 1.114
+++ usr.sbin/bgpd/rde_attr.c 12 Dec 2018 12:56:51 -0000
@@ -1106,8 +1106,6 @@ aspath_lenmatch(struct aspath *a, enum a
* Functions handling communities and extended communities.
*/
-int community_ext_matchone(struct filter_extcommunity *, u_int16_t, u_int64_t);
-
static int
community_extract(struct filter_community *fc, struct rde_peer *peer,
int field, int large, u_int32_t *value)
@@ -1117,15 +1115,21 @@ community_extract(struct filter_communit
switch (field) {
case 1:
flag = fc->dflag1;
- data = fc->data1;
+ if (large)
+ data = fc->c.l.data1;
+ else
+ data = fc->c.b.data1;
break;
case 2:
flag = fc->dflag2;
- data = fc->data2;
+ if (large)
+ data = fc->c.l.data2;
+ else
+ data = fc->c.b.data2;
break;
case 3:
flag = fc->dflag3;
- data = fc->data3;
+ data = fc->c.l.data3;
break;
default:
fatalx("%s: unknown field %d", __func__, field);
@@ -1148,6 +1152,73 @@ community_extract(struct filter_communit
return 0;
}
+static int
+community_ext_matchone(struct filter_community *c, struct rde_peer *peer,
+ u_int64_t community)
+{
+ u_int64_t com, mask;
+
+ community = betoh64(community);
+
+ com = (u_int64_t)c->c.e.type << 56;
+ mask = 0xffULL << 56;
+ if ((com & mask) != (community & mask))
+ return (0);
+
+ switch (c->c.e.type & EXT_COMMUNITY_VALUE) {
+ case EXT_COMMUNITY_TRANS_TWO_AS:
+ case EXT_COMMUNITY_TRANS_IPV4:
+ case EXT_COMMUNITY_TRANS_FOUR_AS:
+ case EXT_COMMUNITY_TRANS_OPAQUE:
+ com = (u_int64_t)c->c.e.subtype << 48;
+ mask = 0xffULL << 48;
+ if ((com & mask) != (community & mask))
+ return (0);
+ break;
+ default:
+ com = c->c.e.data2 & 0xffffffffffffffULL;
+ mask = 0xffffffffffffffULL;
+ if ((com & mask) == (community & mask))
+ return (1);
+ return (0);
+ }
+
+
+ switch (c->c.e.type & EXT_COMMUNITY_VALUE) {
+ case EXT_COMMUNITY_TRANS_TWO_AS:
+ com = (u_int64_t)c->c.e.data1 << 32;
+ mask = 0xffffULL << 32;
+ if ((com & mask) != (community & mask))
+ return (0);
+
+ com = c->c.e.data2;
+ mask = 0xffffffffULL;
+ if ((com & mask) == (community & mask))
+ return (1);
+ break;
+ case EXT_COMMUNITY_TRANS_IPV4:
+ case EXT_COMMUNITY_TRANS_FOUR_AS:
+ com = (u_int64_t)c->c.e.data1 << 16;
+ mask = 0xffffffffULL << 16;
+ if ((com & mask) != (community & mask))
+ return (0);
+
+ com = c->c.e.data2;
+ mask = 0xffff;
+ if ((com & mask) == (community & mask))
+ return (1);
+ break;
+ case EXT_COMMUNITY_TRANS_OPAQUE:
+ com = c->c.e.data2;
+ mask = EXT_COMMUNITY_OPAQUE_MAX;
+ if ((com & mask) == (community & mask))
+ return (1);
+ break;
+ }
+
+ return (0);
+}
+
int
community_match(struct rde_aspath *asp, struct filter_community *fc,
struct rde_peer *peer)
@@ -1308,8 +1379,8 @@ community_delete(struct rde_aspath *asp,
}
int
-community_ext_match(struct rde_aspath *asp, struct filter_extcommunity *c,
- u_int16_t neighas)
+community_ext_match(struct rde_aspath *asp, struct filter_community *c,
+ struct rde_peer *peer)
{
struct attr *attr;
u_int8_t *p;
@@ -1324,7 +1395,7 @@ community_ext_match(struct rde_aspath *a
p = attr->data;
for (len = attr->len / sizeof(ec); len > 0; len--) {
memcpy(&ec, p, sizeof(ec));
- if (community_ext_matchone(c, neighas, ec))
+ if (community_ext_matchone(c, peer, ec))
return (1);
p += sizeof(ec);
}
@@ -1333,8 +1404,8 @@ community_ext_match(struct rde_aspath *a
}
int
-community_ext_set(struct rde_aspath *asp, struct filter_extcommunity *c,
- u_int16_t neighas)
+community_ext_set(struct rde_aspath *asp, struct filter_community *c,
+ struct rde_peer *peer)
{
struct attr *attr;
u_int8_t *p = NULL;
@@ -1342,7 +1413,7 @@ community_ext_set(struct rde_aspath *asp
unsigned int i, ncommunities = 0;
u_int8_t f = ATTR_OPTIONAL|ATTR_TRANSITIVE;
- if (community_ext_conv(c, neighas, &community))
+ if (community_ext_conv(c, peer, &community))
return (0);
attr = attr_optget(asp, ATTR_EXT_COMMUNITIES);
@@ -1381,8 +1452,8 @@ community_ext_set(struct rde_aspath *asp
}
void
-community_ext_delete(struct rde_aspath *asp, struct filter_extcommunity *c,
- u_int16_t neighas)
+community_ext_delete(struct rde_aspath *asp, struct filter_community *c,
+ struct rde_peer *peer)
{
struct attr *attr;
u_int8_t *p, *n;
@@ -1390,7 +1461,7 @@ community_ext_delete(struct rde_aspath *
u_int16_t l, len = 0;
u_int8_t f;
- if (community_ext_conv(c, neighas, &community))
+ if (community_ext_conv(c, peer, &community))
return;
attr = attr_optget(asp, ATTR_EXT_COMMUNITIES);
@@ -1432,119 +1503,34 @@ community_ext_delete(struct rde_aspath *
}
int
-community_ext_conv(struct filter_extcommunity *c, u_int16_t neighas,
+community_ext_conv(struct filter_community *c, struct rde_peer *peer,
u_int64_t *community)
{
u_int64_t com;
- u_int32_t ip;
- com = (u_int64_t)c->type << 56;
- switch (c->type & EXT_COMMUNITY_VALUE) {
+ com = (u_int64_t)c->c.e.type << 56;
+ switch (c->c.e.type & EXT_COMMUNITY_VALUE) {
case EXT_COMMUNITY_TRANS_TWO_AS:
- com |= (u_int64_t)c->subtype << 48;
- com |= (u_int64_t)c->data.ext_as.as << 32;
- com |= c->data.ext_as.val;
+ com |= (u_int64_t)c->c.e.subtype << 48;
+ com |= (u_int64_t)c->c.e.data1 << 32;
+ com |= c->c.e.data2 & 0xffffffff;
break;
case EXT_COMMUNITY_TRANS_IPV4:
- com |= (u_int64_t)c->subtype << 48;
- ip = ntohl(c->data.ext_ip.addr.s_addr);
- com |= (u_int64_t)ip << 16;
- com |= c->data.ext_ip.val;
- break;
case EXT_COMMUNITY_TRANS_FOUR_AS:
- com |= (u_int64_t)c->subtype << 48;
- com |= (u_int64_t)c->data.ext_as4.as4 << 16;
- com |= c->data.ext_as4.val;
+ com |= (u_int64_t)c->c.e.subtype << 48;
+ com |= (u_int64_t)c->c.e.data1 << 16;
+ com |= c->c.e.data2 & 0xffff;
break;
case EXT_COMMUNITY_TRANS_OPAQUE:
- com |= (u_int64_t)c->subtype << 48;
- com |= c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX;
+ com |= (u_int64_t)c->c.e.subtype << 48;
+ com |= c->c.e.data2 & EXT_COMMUNITY_OPAQUE_MAX;
break;
default:
- com |= c->data.ext_opaq & 0xffffffffffffffULL;
+ com |= c->c.e.data2 & 0xffffffffffffffULL;
break;
}
*community = htobe64(com);
-
- return (0);
-}
-
-int
-community_ext_matchone(struct filter_extcommunity *c, u_int16_t neighas,
- u_int64_t community)
-{
- u_int64_t com, mask;
- u_int32_t ip;
-
- community = betoh64(community);
-
- com = (u_int64_t)c->type << 56;
- mask = 0xffULL << 56;
- if ((com & mask) != (community & mask))
- return (0);
-
- switch (c->type & EXT_COMMUNITY_VALUE) {
- case EXT_COMMUNITY_TRANS_TWO_AS:
- case EXT_COMMUNITY_TRANS_IPV4:
- case EXT_COMMUNITY_TRANS_FOUR_AS:
- case EXT_COMMUNITY_TRANS_OPAQUE:
- com = (u_int64_t)c->subtype << 48;
- mask = 0xffULL << 48;
- if ((com & mask) != (community & mask))
- return (0);
- break;
- default:
- com = c->data.ext_opaq & 0xffffffffffffffULL;
- mask = 0xffffffffffffffULL;
- if ((com & mask) == (community & mask))
- return (1);
- return (0);
- }
-
-
- switch (c->type & EXT_COMMUNITY_VALUE) {
- case EXT_COMMUNITY_TRANS_TWO_AS:
- com = (u_int64_t)c->data.ext_as.as << 32;
- mask = 0xffffULL << 32;
- if ((com & mask) != (community & mask))
- return (0);
-
- com = c->data.ext_as.val;
- mask = 0xffffffffULL;
- if ((com & mask) == (community & mask))
- return (1);
- break;
- case EXT_COMMUNITY_TRANS_IPV4:
- ip = ntohl(c->data.ext_ip.addr.s_addr);
- com = (u_int64_t)ip << 16;
- mask = 0xffffffff0000ULL;
- if ((com & mask) != (community & mask))
- return (0);
-
- com = c->data.ext_ip.val;
- mask = 0xffff;
- if ((com & mask) == (community & mask))
- return (1);
- break;
- case EXT_COMMUNITY_TRANS_FOUR_AS:
- com = (u_int64_t)c->data.ext_as4.as4 << 16;
- mask = 0xffffffffULL << 16;
- if ((com & mask) != (community & mask))
- return (0);
-
- com = c->data.ext_as4.val;
- mask = 0xffff;
- if ((com & mask) == (community & mask))
- return (1);
- break;
- case EXT_COMMUNITY_TRANS_OPAQUE:
- com = c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX;
- mask = EXT_COMMUNITY_OPAQUE_MAX;
- if ((com & mask) == (community & mask))
- return (1);
- break;
- }
return (0);
}
Index: usr.sbin/bgpd/rde_filter.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_filter.c,v
retrieving revision 1.115
diff -u -p -r1.115 rde_filter.c
--- usr.sbin/bgpd/rde_filter.c 11 Dec 2018 09:02:14 -0000 1.115
+++ usr.sbin/bgpd/rde_filter.c 12 Dec 2018 12:56:51 -0000
@@ -149,6 +149,10 @@ rde_apply_set(struct filter_set_head *sh
community_large_set(&state->aspath,
&set->action.community, peer);
break;
+ case COMMUNITY_TYPE_EXT:
+ community_ext_set(&state->aspath,
+ &set->action.community, peer);
+ break;
}
break;
case ACTION_DEL_COMMUNITY:
@@ -161,6 +165,9 @@ rde_apply_set(struct filter_set_head *sh
community_large_delete(&state->aspath,
&set->action.community, peer);
break;
+ case COMMUNITY_TYPE_EXT:
+ community_ext_delete(&state->aspath,
+ &set->action.community, peer);
}
break;
case ACTION_PFTABLE:
@@ -184,16 +191,6 @@ rde_apply_set(struct filter_set_head *sh
case ACTION_SET_ORIGIN:
state->aspath.origin = set->action.origin;
break;
- case ACTION_SET_EXT_COMMUNITY:
- community_ext_set(&state->aspath,
- &set->action.ext_community,
- peer->conf.remote_as);
- break;
- case ACTION_DEL_EXT_COMMUNITY:
- community_ext_delete(&state->aspath,
- &set->action.ext_community,
- peer->conf.remote_as);
- break;
}
}
}
@@ -244,13 +241,12 @@ rde_filter_match(struct filter_rule *f,
peer) == 0)
return (0);
break;
+ case COMMUNITY_TYPE_EXT:
+ if (community_ext_match(asp, &f->match.community[i],
+ peer) == 0)
+ return (0);
}
}
- if (asp != NULL &&
- (f->match.ext_community.flags & EXT_COMMUNITY_FLAG_VALID))
- if (community_ext_match(asp, &f->match.ext_community,
- peer->conf.remote_as) == 0)
- return (0);
if (state != NULL && f->match.nexthop.flags != 0) {
struct bgpd_addr *nexthop, *cmpaddr;
@@ -540,12 +536,6 @@ filterset_cmp(struct filter_set *a, stru
sizeof(a->action.community)));
}
- if (a->type == ACTION_SET_EXT_COMMUNITY ||
- a->type == ACTION_DEL_EXT_COMMUNITY) { /* a->type == b->type */
- return (memcmp(&a->action.ext_community,
- &b->action.ext_community, sizeof(a->action.ext_community)));
- }
-
if (a->type == ACTION_SET_NEXTHOP && b->type == ACTION_SET_NEXTHOP) {
/*
* This is the only interesting case, all others are considered
@@ -658,14 +648,6 @@ filterset_equal(struct filter_set_head *
a->action.origin == b->action.origin)
continue;
break;
- case ACTION_SET_EXT_COMMUNITY:
- case ACTION_DEL_EXT_COMMUNITY:
- if (a->type == b->type && memcmp(
- &a->action.ext_community,
- &b->action.ext_community,
- sizeof(a->action.ext_community)) == 0)
- continue;
- break;
}
/* compare failed */
return (0);
@@ -710,10 +692,6 @@ filterset_name(enum action_types type)
return ("rtlabel");
case ACTION_SET_ORIGIN:
return ("origin");
- case ACTION_SET_EXT_COMMUNITY:
- return ("ext-community");
- case ACTION_DEL_EXT_COMMUNITY:
- return ("ext-community delete");
}
fatalx("filterset_name: got lost");
Index: usr.sbin/bgpd/rde_update.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_update.c,v
retrieving revision 1.105
diff -u -p -r1.105 rde_update.c
--- usr.sbin/bgpd/rde_update.c 29 Nov 2018 12:10:51 -0000 1.105
+++ usr.sbin/bgpd/rde_update.c 12 Dec 2018 12:56:51 -0000
@@ -68,18 +68,18 @@ SIPHASH_KEY uptree_key;
static struct filter_community comm_no_advertise = {
.type = COMMUNITY_TYPE_BASIC,
- .data1 = COMMUNITY_WELLKNOWN,
- .data2 = COMMUNITY_NO_ADVERTISE
+ .c.b.data1 = COMMUNITY_WELLKNOWN,
+ .c.b.data2 = COMMUNITY_NO_ADVERTISE
};
static struct filter_community comm_no_export = {
.type = COMMUNITY_TYPE_BASIC,
- .data1 = COMMUNITY_WELLKNOWN,
- .data2 = COMMUNITY_NO_EXPORT
+ .c.b.data1 = COMMUNITY_WELLKNOWN,
+ .c.b.data2 = COMMUNITY_NO_EXPORT
};
static struct filter_community comm_no_expsubconfed = {
.type = COMMUNITY_TYPE_BASIC,
- .data1 = COMMUNITY_WELLKNOWN,
- .data2 = COMMUNITY_NO_EXPSUBCONFED
+ .c.b.data1 = COMMUNITY_WELLKNOWN,
+ .c.b.data2 = COMMUNITY_NO_EXPSUBCONFED
};
void