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
> 

Reply via email to