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 *
> 

Reply via email to