Claudio Jeker(cje...@diehard.n-r-g.com) on 2017.05.31 00:27:21 +0200: > After looking at what IETF and IANA did to extended communities I decided > to refactor the code a major bit and hopefully that will work a bit better > than what we had before. When I implemented it first I foolishliy assumed > that the transitive flag is a flag but it seems that people decided > differently later on. > > This also implements a few more ext-communities mainly origin validation > state. > > It also fixes a bug if found while testing that is already there :)
much more readable than what we have. ok > -- > :wq Claudio > > Index: bgpctl/bgpctl.c > =================================================================== > RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v > retrieving revision 1.194 > diff -u -p -r1.194 bgpctl.c > --- bgpctl/bgpctl.c 29 May 2017 09:56:33 -0000 1.194 > +++ bgpctl/bgpctl.c 30 May 2017 21:00:08 -0000 > @@ -1598,29 +1598,47 @@ show_ext_community(u_char *data, u_int16 > type = data[i]; > subtype = data[i + 1]; > > - switch (type & EXT_COMMUNITY_VALUE) { > - case EXT_COMMUNITY_TWO_AS: > + printf("%s ", log_ext_subtype(type, subtype)); > + > + switch (type) { > + case EXT_COMMUNITY_TRANS_TWO_AS: > memcpy(&as2, data + i + 2, sizeof(as2)); > memcpy(&u32, data + i + 4, sizeof(u32)); > - printf("%s %s:%u", log_ext_subtype(subtype), > - log_as(ntohs(as2)), ntohl(u32)); > + printf("%s:%u", log_as(ntohs(as2)), ntohl(u32)); > break; > - case EXT_COMMUNITY_IPV4: > + case EXT_COMMUNITY_TRANS_IPV4: > memcpy(&ip, data + i + 2, sizeof(ip)); > memcpy(&u16, data + i + 6, sizeof(u16)); > - printf("%s %s:%hu", log_ext_subtype(subtype), > - inet_ntoa(ip), ntohs(u16)); > + printf("%s:%hu", inet_ntoa(ip), ntohs(u16)); > break; > - case EXT_COMMUNITY_FOUR_AS: > + case EXT_COMMUNITY_TRANS_FOUR_AS: > memcpy(&as4, data + i + 2, sizeof(as4)); > memcpy(&u16, data + i + 6, sizeof(u16)); > - printf("%s %s:%hu", log_ext_subtype(subtype), > - log_as(ntohl(as4)), ntohs(u16)); > + printf("%s:%hu", log_as(ntohl(as4)), ntohs(u16)); > break; > - case EXT_COMMUNITY_OPAQUE: > + case EXT_COMMUNITY_TRANS_OPAQUE: > + case EXT_COMMUNITY_TRANS_EVPN: > memcpy(&ext, data + i, sizeof(ext)); > ext = betoh64(ext) & 0xffffffffffffLL; > - printf("%s 0x%llx", log_ext_subtype(subtype), ext); > + printf("0x%llx", ext); > + break; > + case EXT_COMMUNITY_NON_TRANS_OPAQUE: > + memcpy(&ext, data + i, sizeof(ext)); > + ext = betoh64(ext) & 0xffffffffffffLL; > + switch (ext) { > + 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; > + default: > + printf("0x%llx ", ext); > + break; > + } > break; > default: > memcpy(&ext, data + i, sizeof(ext)); > Index: bgpd/bgpd.h > =================================================================== > RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v > retrieving revision 1.307 > diff -u -p -r1.307 bgpd.h > --- bgpd/bgpd.h 28 May 2017 20:14:15 -0000 1.307 > +++ bgpd/bgpd.h 30 May 2017 22:23:03 -0000 > @@ -760,18 +760,23 @@ struct filter_peers { > #define EXT_COMMUNITY_IANA 0x80 > #define EXT_COMMUNITY_TRANSITIVE 0x40 > #define EXT_COMMUNITY_VALUE 0x3f > -/* extended types */ > -#define EXT_COMMUNITY_TWO_AS 0 /* 2 octet AS specific */ > -#define EXT_COMMUNITY_IPV4 1 /* IPv4 specific */ > -#define EXT_COMMUNITY_FOUR_AS 2 /* 4 octet AS specific > */ > -#define EXT_COMMUNITY_OPAQUE 3 /* opaque ext community */ > -/* sub types */ > -#define EXT_COMMUNITY_ROUTE_TGT 2 /* RFC 4360 & RFC4364 */ > -#define EXT_COMMUNITY_ROUTE_ORIG 3 /* RFC 4360 & RFC4364 */ > -#define EXT_COMMUNITY_OSPF_DOM_ID 5 /* RFC 4577 */ > -#define EXT_COMMUNITY_OSPF_RTR_TYPE 6 /* RFC 4577 */ > -#define EXT_COMMUNITY_OSPF_RTR_ID 7 /* RFC 4577 */ > -#define EXT_COMMUNITY_BGP_COLLECT 8 /* RFC 4384 */ > +/* extended types transitive */ > +#define EXT_COMMUNITY_TRANS_TWO_AS 0x00 /* 2 octet AS specific */ > +#define EXT_COMMUNITY_TRANS_IPV4 0x01 /* IPv4 specific */ > +#define EXT_COMMUNITY_TRANS_FOUR_AS 0x02 /* 4 octet AS specific */ > +#define EXT_COMMUNITY_TRANS_OPAQUE 0x03 /* opaque ext community */ > +#define EXT_COMMUNITY_TRANS_EVPN 0x06 /* EVPN RFC7432 */ > +/* extended types non-transitive */ > +#define EXT_COMMUNITY_NON_TRANS_TWO_AS 0x40 /* 2 octet AS specific > */ > +#define EXT_COMMUNITY_NON_TRANS_IPV4 0x41 /* IPv4 specific */ > +#define EXT_COMMUNITY_NON_TRANS_FOUR_AS 0x42 /* 4 octet AS specific > */ > +#define EXT_COMMUNITY_NON_TRANS_OPAQUE 0x43 /* opaque ext community > */ > + > +/* BGP Origin Validation State Extended Community RFC8097 */ > +#define EXT_COMMUNITY_OVS_VALID 0 > +#define EXT_COMMUNITY_OVS_NOTFOUND 1 > +#define EXT_COMMUNITY_OVS_INVALID 2 > + > /* other handy defines */ > #define EXT_COMMUNITY_OPAQUE_MAX 0xffffffffffffULL > #define EXT_COMMUNITY_FLAG_VALID 0x01 > @@ -779,22 +784,41 @@ struct filter_peers { > struct ext_comm_pairs { > u_int8_t type; > u_int8_t subtype; > - u_int8_t transitive; /* transitive bit needs to be set */ > + const char *subname; > }; > > -#define IANA_EXT_COMMUNITIES { \ > - { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_ROUTE_TGT, 0 }, \ > - { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_ROUTE_ORIG, 0 }, \ > - { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_OSPF_DOM_ID, 0 }, \ > - { EXT_COMMUNITY_TWO_AS, EXT_COMMUNITY_BGP_COLLECT, 0 }, \ > - { EXT_COMMUNITY_FOUR_AS, EXT_COMMUNITY_ROUTE_TGT, 0 }, \ > - { EXT_COMMUNITY_FOUR_AS, EXT_COMMUNITY_ROUTE_ORIG, 0 }, \ > - { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_ROUTE_TGT, 0 }, \ > - { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_ROUTE_ORIG, 0 }, \ > - { EXT_COMMUNITY_IPV4, EXT_COMMUNITY_OSPF_RTR_ID, 0 }, \ > - { EXT_COMMUNITY_OPAQUE, EXT_COMMUNITY_OSPF_RTR_TYPE, 0 } \ > +#define IANA_EXT_COMMUNITIES { \ > + { EXT_COMMUNITY_TRANS_TWO_AS, 0x02, "rt" }, \ > + { EXT_COMMUNITY_TRANS_TWO_AS, 0x03, "soo" }, \ > + { EXT_COMMUNITY_TRANS_TWO_AS, 0x05, "odi" }, \ > + { EXT_COMMUNITY_TRANS_TWO_AS, 0x08, "bdc" }, \ > + { EXT_COMMUNITY_TRANS_TWO_AS, 0x09, "srcas" }, \ > + { EXT_COMMUNITY_TRANS_TWO_AS, 0x0a, "l2vid" }, \ > + \ > + { EXT_COMMUNITY_TRANS_FOUR_AS, 0x02, "rt" }, \ > + { EXT_COMMUNITY_TRANS_FOUR_AS, 0x03, "soo" }, \ > + { EXT_COMMUNITY_TRANS_FOUR_AS, 0x05, "odi" }, \ > + { EXT_COMMUNITY_TRANS_FOUR_AS, 0x08, "bdc" }, \ > + { EXT_COMMUNITY_TRANS_FOUR_AS, 0x09, "srcas" }, \ > + \ > + { EXT_COMMUNITY_TRANS_IPV4, 0x02, "rt" }, \ > + { EXT_COMMUNITY_TRANS_IPV4, 0x03, "soo" }, \ > + { EXT_COMMUNITY_TRANS_IPV4, 0x05, "odi" }, \ > + { EXT_COMMUNITY_TRANS_IPV4, 0x07, "ori" }, \ > + { EXT_COMMUNITY_TRANS_IPV4, 0x0a, "l2vid" }, \ > + { EXT_COMMUNITY_TRANS_IPV4, 0x0b, "vrfri" }, \ > + \ > + { EXT_COMMUNITY_TRANS_OPAQUE, 0x06, "ort" }, \ > + { EXT_COMMUNITY_TRANS_OPAQUE, 0x0d, "defgw" }, \ > + \ > + { EXT_COMMUNITY_NON_TRANS_OPAQUE, 0x00, "ovs" }, \ > + \ > + { EXT_COMMUNITY_TRANS_EVPN, 0x00, "mac-mob" }, \ > + { EXT_COMMUNITY_TRANS_EVPN, 0x01, "esi-lab" }, \ > + { EXT_COMMUNITY_TRANS_EVPN, 0x02, "esi-rt" }, \ > } > > +extern const struct ext_comm_pairs iana_ext_comms[]; > > struct filter_prefix { > struct bgpd_addr addr; > @@ -1079,7 +1103,7 @@ const char *log_in6addr(const struct in6 > const char *log_sockaddr(struct sockaddr *); > const char *log_as(u_int32_t); > const char *log_rd(u_int64_t); > -const char *log_ext_subtype(u_int8_t); > +const char *log_ext_subtype(u_int8_t, u_int8_t); > const char *log_shutcomm(const char *); > int aspath_snprint(char *, size_t, void *, u_int16_t); > int aspath_asprint(char **, void *, u_int16_t); > Index: bgpd/kroute.c > =================================================================== > RCS file: /cvs/src/usr.sbin/bgpd/kroute.c,v > retrieving revision 1.213 > diff -u -p -r1.213 kroute.c > --- bgpd/kroute.c 28 May 2017 15:16:33 -0000 1.213 > +++ bgpd/kroute.c 28 May 2017 19:05:28 -0000 > @@ -1281,6 +1281,10 @@ kr_redistribute(int type, struct ktable > kr->flags |= F_REDISTRIBUTED; > > sendit: > + log_debug("kr_redistribute: %s (%s)", inet_ntoa(kr->prefix), > + type == IMSG_NETWORK_ADD ? "IMSG_NETWORK_ADD" : > + "IMSG_NETWORK_REMOVE"); > + > bzero(&net, sizeof(net)); > net.prefix.aid = AID_INET; > net.prefix.v4.s_addr = kr->prefix.s_addr; > @@ -1350,6 +1354,11 @@ kr_redistribute6(int type, struct ktable > } else > kr6->flags |= F_REDISTRIBUTED; > sendit: > + log_debug("kr_redistribute6: %s/%u (%s)", > + log_in6addr(&kr6->prefix), kr6->prefixlen, > + type == IMSG_NETWORK_ADD ? "IMSG_NETWORK_ADD" : > + "IMSG_NETWORK_REMOVE"); > + > bzero(&net, sizeof(net)); > net.prefix.aid = AID_INET6; > memcpy(&net.prefix.v6, &kr6->prefix, sizeof(struct in6_addr)); > @@ -1389,9 +1398,13 @@ kr_reload(void) > if (hasdyn) { > /* only evaluate the full tree if we need */ > RB_FOREACH(kr, kroute_tree, &kt->krt) > - kr_redistribute(IMSG_NETWORK_ADD, kt, &kr->r); > + if(!(kr->r.flags & F_DOWN)) > + kr_redistribute(IMSG_NETWORK_ADD, > + kt, &kr->r); > RB_FOREACH(kr6, kroute6_tree, &kt->krt6) > - kr_redistribute6(IMSG_NETWORK_ADD, kt, &kr6->r); > + if(!(kr6->r.flags & F_DOWN)) > + kr_redistribute6(IMSG_NETWORK_ADD, > + kt, &kr6->r); > } > } > > @@ -2502,6 +2515,10 @@ if_change(u_short ifindex, int flags, st > if (kt == NULL) > continue; > > + kr_redistribute(reachable ? > + IMSG_NETWORK_ADD : IMSG_NETWORK_REMOVE, > + kt, &(kkr->kr->r)); > + > knexthop_track(kt, kkr->kr); > } > LIST_FOREACH(kkr6, &kif->kroute6_l, entry) { > @@ -2512,6 +2529,10 @@ if_change(u_short ifindex, int flags, st > > if (kt == NULL) > continue; > + > + kr_redistribute6(reachable ? > + IMSG_NETWORK_ADD : IMSG_NETWORK_REMOVE, > + kt, &(kkr6->kr->r)); > > knexthop_track(kt, kkr6->kr); > } > Index: bgpd/parse.y > =================================================================== > RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v > retrieving revision 1.307 > diff -u -p -r1.307 parse.y > --- bgpd/parse.y 29 May 2017 07:49:27 -0000 1.307 > +++ bgpd/parse.y 30 May 2017 22:24:17 -0000 > @@ -150,7 +150,7 @@ int getcommunity(char *); > int parsecommunity(struct filter_community *, char *); > int64_t getlargecommunity(char *); > int parselargecommunity(struct filter_largecommunity *, char *); > -int parsesubtype(char *); > +int parsesubtype(char *, int *, int *); > int parseextvalue(char *, u_int32_t *); > int parseextcommunity(struct filter_extcommunity *, char *, > char *); > @@ -871,13 +871,13 @@ rdomainopts : RD STRING { > } > rd = betoh64(rd) & 0xffffffffffffULL; > switch (ext.type) { > - case EXT_COMMUNITY_TWO_AS: > + case EXT_COMMUNITY_TRANS_TWO_AS: > rd |= (0ULL << 48); > break; > - case EXT_COMMUNITY_IPV4: > + case EXT_COMMUNITY_TRANS_IPV4: > rd |= (1ULL << 48); > break; > - case EXT_COMMUNITY_FOUR_AS: > + case EXT_COMMUNITY_TRANS_FOUR_AS: > rd |= (2ULL << 48); > break; > default: > @@ -3089,26 +3089,23 @@ parselargecommunity(struct filter_largec > } > > int > -parsesubtype(char *type) > +parsesubtype(char *name, int *type, int *subtype) > { > - /* this has to be sorted always */ > - static const struct keywords keywords[] = { > - { "bdc", EXT_COMMUNITY_BGP_COLLECT }, > - { "odi", EXT_COMMUNITY_OSPF_DOM_ID }, > - { "ori", EXT_COMMUNITY_OSPF_RTR_ID }, > - { "ort", EXT_COMMUNITY_OSPF_RTR_TYPE }, > - { "rt", EXT_COMMUNITY_ROUTE_TGT }, > - { "soo", EXT_COMMUNITY_ROUTE_ORIG } > - }; > - const struct keywords *p; > - > - p = bsearch(type, keywords, sizeof(keywords)/sizeof(keywords[0]), > - sizeof(keywords[0]), kw_cmp); > + const struct ext_comm_pairs *cp; > + int found = 0; > > - if (p) > - return (p->k_val); > - else > - return (-1); > + for (cp = iana_ext_comms; cp->subname != NULL; cp++) { > + if (strcmp(name, cp->subname) == 0) { > + if (found == 0) { > + *type = cp->type; > + *subtype = cp->subtype; > + } > + found++; > + } > + } > + if (found > 1) > + *type = -1; > + return (found); > } > > int > @@ -3127,10 +3124,10 @@ parseextvalue(char *s, u_int32_t *v) > return (-1); > } > *v = uval; > - if (uval > USHRT_MAX) > - return (EXT_COMMUNITY_FOUR_AS); > + if (uval <= USHRT_MAX) > + return (EXT_COMMUNITY_TRANS_TWO_AS); > else > - return (EXT_COMMUNITY_TWO_AS); > + return (EXT_COMMUNITY_TRANS_FOUR_AS); > } else if (strchr(p + 1, '.') == NULL) { > /* AS_DOT number (4-byte) */ > *p++ = '\0'; > @@ -3145,7 +3142,7 @@ parseextvalue(char *s, u_int32_t *v) > return (-1); > } > *v = uval | (uvalh << 16); > - return (EXT_COMMUNITY_FOUR_AS); > + return (EXT_COMMUNITY_TRANS_FOUR_AS); > } else { > /* more than one dot -> IP address */ > if (inet_aton(s, &ip) == 0) { > @@ -3153,7 +3150,7 @@ parseextvalue(char *s, u_int32_t *v) > return (-1); > } > *v = ip.s_addr; > - return (EXT_COMMUNITY_IPV4); > + return (EXT_COMMUNITY_TRANS_IPV4); > } > return (-1); > } > @@ -3161,75 +3158,90 @@ parseextvalue(char *s, u_int32_t *v) > int > parseextcommunity(struct filter_extcommunity *c, char *t, char *s) > { > - const struct ext_comm_pairs iana[] = IANA_EXT_COMMUNITIES; > + const struct ext_comm_pairs *cp; > const char *errstr; > u_int64_t ullval; > u_int32_t uval; > char *p, *ep; > - unsigned int i; > int type, subtype; > > - if ((subtype = parsesubtype(t)) == -1) { > + if (parsesubtype(t, &type, &subtype) == 0) { > yyerror("Bad ext-community unknown type"); > return (-1); > } > > - if ((p = strchr(s, ':')) == NULL) { > - type = EXT_COMMUNITY_OPAQUE, > - errno = 0; > - ullval = strtoull(s, &ep, 0); > - if (s[0] == '\0' || *ep != '\0') { > - yyerror("Bad ext-community bad value"); > - return (-1); > - } > - if (errno == ERANGE && ullval > EXT_COMMUNITY_OPAQUE_MAX) { > - yyerror("Bad ext-community value to big"); > + switch (type) { > + case -1: > + if ((p = strchr(s, ':')) == NULL) { > + yyerror("Bad ext-community %s is %s", s, errstr); > return (-1); > } > - c->data.ext_opaq = ullval; > - } else { > *p++ = '\0'; > if ((type = parseextvalue(s, &uval)) == -1) > return (-1); > switch (type) { > - case EXT_COMMUNITY_TWO_AS: > + case EXT_COMMUNITY_TRANS_TWO_AS: > ullval = strtonum(p, 0, UINT_MAX, &errstr); > break; > - case EXT_COMMUNITY_IPV4: > - case EXT_COMMUNITY_FOUR_AS: > + case EXT_COMMUNITY_TRANS_IPV4: > + case EXT_COMMUNITY_TRANS_FOUR_AS: > ullval = strtonum(p, 0, USHRT_MAX, &errstr); > break; > default: > fatalx("parseextcommunity: unexpected result"); > } > if (errstr) { > - yyerror("Bad ext-community %s is %s", p, > - errstr); > + yyerror("Bad ext-community %s is %s", p, errstr); > return (-1); > } > switch (type) { > - case EXT_COMMUNITY_TWO_AS: > + case EXT_COMMUNITY_TRANS_TWO_AS: > c->data.ext_as.as = uval; > c->data.ext_as.val = ullval; > break; > - case EXT_COMMUNITY_IPV4: > + case EXT_COMMUNITY_TRANS_IPV4: > c->data.ext_ip.addr.s_addr = uval; > c->data.ext_ip.val = ullval; > break; > - case EXT_COMMUNITY_FOUR_AS: > + case EXT_COMMUNITY_TRANS_FOUR_AS: > c->data.ext_as4.as4 = uval; > c->data.ext_as4.val = ullval; > break; > } > + break; > + case EXT_COMMUNITY_TRANS_OPAQUE: > + case EXT_COMMUNITY_TRANS_EVPN: > + errno = 0; > + ullval = strtoull(s, &ep, 0); > + if (s[0] == '\0' || *ep != '\0') { > + yyerror("Bad ext-community bad value"); > + return (-1); > + } > + if (errno == ERANGE && ullval > EXT_COMMUNITY_OPAQUE_MAX) { > + yyerror("Bad ext-community value to big"); > + return (-1); > + } > + c->data.ext_opaq = ullval; > + break; > + case EXT_COMMUNITY_NON_TRANS_OPAQUE: > + if (strcmp(s, "valid") == 0) > + c->data.ext_opaq = EXT_COMMUNITY_OVS_VALID; > + else if (strcmp(s, "invalid") == 0) > + c->data.ext_opaq = EXT_COMMUNITY_OVS_INVALID; > + else if (strcmp(s, "not-found") == 0) > + c->data.ext_opaq = EXT_COMMUNITY_OVS_NOTFOUND; > + else { > + yyerror("Bad ext-community %s is %s", s, errstr); > + return (-1); > + } > + break; > } > c->type = type; > c->subtype = subtype; > > /* verify type/subtype combo */ > - for (i = 0; i < sizeof(iana)/sizeof(iana[0]); i++) { > - if (iana[i].type == type && iana[i].subtype == subtype) { > - if (iana[i].transitive) > - c->type |= EXT_COMMUNITY_TRANSITIVE; > + for (cp = iana_ext_comms; cp->subname != NULL; cp++) { > + if (cp->type == type && cp->subtype == subtype) { > c->flags |= EXT_COMMUNITY_FLAG_VALID; > return (0); > } > Index: bgpd/printconf.c > =================================================================== > RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v > retrieving revision 1.103 > diff -u -p -r1.103 printconf.c > --- bgpd/printconf.c 27 May 2017 18:12:23 -0000 1.103 > +++ bgpd/printconf.c 30 May 2017 20:48:39 -0000 > @@ -145,25 +145,39 @@ print_largecommunity(int64_t as, int64_t > void > print_extcommunity(struct filter_extcommunity *c) > { > - switch (c->type & EXT_COMMUNITY_VALUE) { > - case EXT_COMMUNITY_TWO_AS: > - printf("%s %hu:%u ", log_ext_subtype(c->subtype), > - c->data.ext_as.as, c->data.ext_as.val); > + 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_IPV4: > - printf("%s %s:%u ", log_ext_subtype(c->subtype), > - inet_ntoa(c->data.ext_ip.addr), c->data.ext_ip.val); > + case EXT_COMMUNITY_TRANS_IPV4: > + printf("%s:%u ", inet_ntoa(c->data.ext_ip.addr), > + c->data.ext_ip.val); > break; > - case EXT_COMMUNITY_FOUR_AS: > - printf("%s %s:%u ", log_ext_subtype(c->subtype), > - log_as(c->data.ext_as4.as4), c->data.ext_as.val); > + 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_OPAQUE: > - printf("%s 0x%llx ", log_ext_subtype(c->subtype), > - c->data.ext_opaq); > + 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 "); > + break; > + case EXT_COMMUNITY_OVS_INVALID: > + printf("invalid "); > + break; > + } > break; > default: > - printf("0x%x 0x%llx ", c->type, c->data.ext_opaq); > + printf("0x%llx ", c->data.ext_opaq); > break; > } > } > Index: bgpd/rde_attr.c > =================================================================== > RCS file: /cvs/src/usr.sbin/bgpd/rde_attr.c,v > retrieving revision 1.98 > diff -u -p -r1.98 rde_attr.c > --- bgpd/rde_attr.c 26 May 2017 20:55:30 -0000 1.98 > +++ bgpd/rde_attr.c 30 May 2017 20:41:34 -0000 > @@ -1253,23 +1253,23 @@ community_ext_conv(struct filter_extcomm > > com = (u_int64_t)c->type << 56; > switch (c->type & EXT_COMMUNITY_VALUE) { > - case EXT_COMMUNITY_TWO_AS: > + 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; > break; > - case EXT_COMMUNITY_IPV4: > + 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_FOUR_AS: > + 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; > break; > - case EXT_COMMUNITY_OPAQUE: > + case EXT_COMMUNITY_TRANS_OPAQUE: > com |= (u_int64_t)c->subtype << 48; > com |= c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX; > break; > @@ -1298,10 +1298,10 @@ community_ext_matchone(struct filter_ext > return (0); > > switch (c->type & EXT_COMMUNITY_VALUE) { > - case EXT_COMMUNITY_TWO_AS: > - case EXT_COMMUNITY_IPV4: > - case EXT_COMMUNITY_FOUR_AS: > - case EXT_COMMUNITY_OPAQUE: > + 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)) > @@ -1317,7 +1317,7 @@ community_ext_matchone(struct filter_ext > > > switch (c->type & EXT_COMMUNITY_VALUE) { > - case EXT_COMMUNITY_TWO_AS: > + case EXT_COMMUNITY_TRANS_TWO_AS: > com = (u_int64_t)c->data.ext_as.as << 32; > mask = 0xffffULL << 32; > if ((com & mask) != (community & mask)) > @@ -1328,7 +1328,7 @@ community_ext_matchone(struct filter_ext > if ((com & mask) == (community & mask)) > return (1); > break; > - case EXT_COMMUNITY_IPV4: > + case EXT_COMMUNITY_TRANS_IPV4: > ip = ntohl(c->data.ext_ip.addr.s_addr); > com = (u_int64_t)ip << 16; > mask = 0xffffffff0000ULL; > @@ -1340,7 +1340,7 @@ community_ext_matchone(struct filter_ext > if ((com & mask) == (community & mask)) > return (1); > break; > - case EXT_COMMUNITY_FOUR_AS: > + case EXT_COMMUNITY_TRANS_FOUR_AS: > com = (u_int64_t)c->data.ext_as4.as4 << 16; > mask = 0xffffffffULL << 16; > if ((com & mask) != (community & mask)) > @@ -1351,7 +1351,7 @@ community_ext_matchone(struct filter_ext > if ((com & mask) == (community & mask)) > return (1); > break; > - case EXT_COMMUNITY_OPAQUE: > + case EXT_COMMUNITY_TRANS_OPAQUE: > com = c->data.ext_opaq & EXT_COMMUNITY_OPAQUE_MAX; > mask = EXT_COMMUNITY_OPAQUE_MAX; > if ((com & mask) == (community & mask)) > Index: bgpd/util.c > =================================================================== > RCS file: /cvs/src/usr.sbin/bgpd/util.c,v > retrieving revision 1.24 > diff -u -p -r1.24 util.c > --- bgpd/util.c 24 Jan 2017 04:22:42 -0000 1.24 > +++ bgpd/util.c 30 May 2017 20:54:08 -0000 > @@ -112,17 +112,17 @@ log_rd(u_int64_t rd) > > rd = betoh64(rd); > switch (rd >> 48) { > - case EXT_COMMUNITY_TWO_AS: > + case EXT_COMMUNITY_TRANS_TWO_AS: > u32 = rd & 0xffffffff; > u16 = (rd >> 32) & 0xffff; > snprintf(buf, sizeof(buf), "rd %hu:%u", u16, u32); > break; > - case EXT_COMMUNITY_FOUR_AS: > + case EXT_COMMUNITY_TRANS_FOUR_AS: > u32 = (rd >> 16) & 0xffffffff; > u16 = rd & 0xffff; > snprintf(buf, sizeof(buf), "rd %s:%hu", log_as(u32), u16); > break; > - case EXT_COMMUNITY_IPV4: > + case EXT_COMMUNITY_TRANS_IPV4: > u32 = (rd >> 16) & 0xffffffff; > u16 = rd & 0xffff; > addr.s_addr = htonl(u32); > @@ -134,30 +134,22 @@ log_rd(u_int64_t rd) > return (buf); > } > > +const struct ext_comm_pairs iana_ext_comms[] = IANA_EXT_COMMUNITIES; > + > /* NOTE: this function does not check if the type/subtype combo is > * actually valid. */ > const char * > -log_ext_subtype(u_int8_t subtype) > +log_ext_subtype(u_int8_t type, u_int8_t subtype) > { > static char etype[6]; > + const struct ext_comm_pairs *cp; > > - switch (subtype) { > - case EXT_COMMUNITY_ROUTE_TGT: > - return ("rt"); /* route target */ > - case EXT_COMMUNITY_ROUTE_ORIG: > - return ("soo"); /* source of origin */ > - case EXT_COMMUNITY_OSPF_DOM_ID: > - return ("odi"); /* ospf domain id */ > - case EXT_COMMUNITY_OSPF_RTR_TYPE: > - return ("ort"); /* ospf route type */ > - case EXT_COMMUNITY_OSPF_RTR_ID: > - return ("ori"); /* ospf router id */ > - case EXT_COMMUNITY_BGP_COLLECT: > - return ("bdc"); /* bgp data collection */ > - default: > - snprintf(etype, sizeof(etype), "[%u]", subtype); > - return (etype); > + for (cp = iana_ext_comms; cp->subname != NULL; cp++) { > + if (type == cp->type && subtype == cp->subtype) > + return (cp->subname); > } > + snprintf(etype, sizeof(etype), "[%u]", subtype); > + return (etype); > } > > const char * >