Claudio Jeker(cje...@diehard.n-r-g.com) on 2018.12.12 14:19:36 +0100: > 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).
ok benno@ one space too much, see below. I like it. Unfortunatly, the diff shows how stupid extended communities are, and refactoring it can't do much to improve that. /B. > > -- > :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; > + } ^space > *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 >