On Wed, May 25, 2022 at 02:46:55PM +0200, Claudio Jeker wrote:
> Noticed this morning working on something else. The non-transitive
> extended community support is fairly messed up. In my case (set
> ext-community rt 1:1) it causes the community to be skipped.
> 
> First of all the check in non_transitive_community() is messed up. It uses
> the wrong data field, does a unneccessary ntohl and the logic seems also
> to be reversed.
> 
> While looking at this I decided to fix the various switch statements on
> type to mask out the two high bits with this extending ext community types
> should be a bit easier.
>
> While there be strict from where bgpd accepts non-transitive
> ext-communities. Now non-transitive ext communities are filtered in and out
> for ebgp sessions. So non-transitive ext communities only pass on ibgp
> sessions.
> 
> For the rde_attr_add() the system defaults to ibgp since this is for
> network announcements.
> 
> There is also a trivial fix to the bgpd unittests that I excluded here.
> 
> With this ext-communities are properly sent on updates.
> OK?

Makes sense, one comment below.

> -- 
> :wq Claudio
> 
> Index: rde.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
> retrieving revision 1.545
> diff -u -p -r1.545 rde.c
> --- rde.c     6 May 2022 15:51:09 -0000       1.545
> +++ rde.c     25 May 2022 12:30:44 -0000
> @@ -1917,8 +1917,8 @@ bad_flags:
>               if (!CHECK_FLAGS(flags, ATTR_OPTIONAL|ATTR_TRANSITIVE,
>                   ATTR_PARTIAL))
>                       goto bad_flags;
> -             if (community_ext_add(&state->communities, flags, p,
> -                 attr_len) == -1) {
> +             if (community_ext_add(&state->communities, flags,
> +                 peer->conf.ebgp, p, attr_len) == -1) {
>                       /*
>                        * mark update as bad and withdraw all routes as per
>                        * RFC 7606
> @@ -2062,8 +2062,8 @@ rde_attr_add(struct filterstate *state, 
>               return community_large_add(&state->communities, flags, p,
>                   attr_len);
>       case ATTR_EXT_COMMUNITIES:
> -             return community_ext_add(&state->communities, flags, p,
> -                 attr_len);
> +             return community_ext_add(&state->communities, flags, 0,
> +                 p, attr_len);
>       }
>  
>       if (attr_optadd(&state->aspath, flags, type, p, attr_len) == -1)
> Index: rde.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
> retrieving revision 1.251
> diff -u -p -r1.251 rde.h
> --- rde.h     22 Mar 2022 10:53:08 -0000      1.251
> +++ rde.h     25 May 2022 12:30:44 -0000
> @@ -459,7 +459,7 @@ void      community_delete(struct rde_communi
>  
>  int  community_add(struct rde_community *, int, void *, size_t);
>  int  community_large_add(struct rde_community *, int, void *, size_t);
> -int  community_ext_add(struct rde_community *, int, void *, size_t);
> +int  community_ext_add(struct rde_community *, int, int, void *, size_t);
>  
>  int  community_write(struct rde_community *, void *, uint16_t);
>  int  community_large_write(struct rde_community *, void *, uint16_t);
> Index: rde_community.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_community.c,v
> retrieving revision 1.4
> diff -u -p -r1.4 rde_community.c
> --- rde_community.c   6 Feb 2022 09:51:19 -0000       1.4
> +++ rde_community.c   25 May 2022 12:30:44 -0000
> @@ -99,7 +99,7 @@ fc2c(struct community *fc, struct rde_pe
>               subtype = fc->data3 & 0xff;
>  
>               c->data3 = type << 8 | subtype;
> -             switch (type) {
> +             switch (type & EXT_COMMUNITY_VALUE) {
>               case -1:

Should that '-1' not be changed to 'EXT_COMMUNITY_VALUE'?  Since you now
mask out the high two bits, it is no longer possible to reach this case.

>                       /* special case for 'ext-community rt *' */
>                       if ((fc->flags >> 8 & 0xff) != COMMUNITY_ANY ||
> @@ -141,7 +141,6 @@ fc2c(struct community *fc, struct rde_pe
>                       return 0;
>               case EXT_COMMUNITY_TRANS_OPAQUE:
>               case EXT_COMMUNITY_TRANS_EVPN:
> -             case EXT_COMMUNITY_NON_TRANS_OPAQUE:
>                       if ((fc->flags >> 8 & 0xff) == COMMUNITY_ANY)
>                               break;
>  
> @@ -244,10 +243,9 @@ insert_community(struct rde_community *c
>  }
>  
>  static int
> -non_transitive_community(struct community *c)
> +non_transitive_ext_community(struct community *c)
>  {
> -     if ((uint8_t)c->flags == COMMUNITY_TYPE_EXT &&
> -         !((ntohl(c->data1) >> 24) & EXT_COMMUNITY_NON_TRANSITIVE))
> +     if ((c->data3 >> 8) & EXT_COMMUNITY_NON_TRANSITIVE)
>               return 1;
>       return 0;
>  }
> @@ -404,7 +402,8 @@ community_large_add(struct rde_community
>  }
>  
>  int
> -community_ext_add(struct rde_community *comm, int flags, void *buf, size_t 
> len)
> +community_ext_add(struct rde_community *comm, int flags, int ebgp,
> +    void *buf, size_t len)
>  {
>       struct community set = { .flags = COMMUNITY_TYPE_EXT };
>       uint8_t *b = buf, type;
> @@ -422,11 +421,13 @@ community_ext_add(struct rde_community *
>  
>               c = be64toh(c);
>               type = c >> 56;
> -             switch (type) {
> +             /* filter out non-transitive ext communuties from ebgp peers */
> +             if (ebgp && (type & EXT_COMMUNITY_NON_TRANSITIVE))
> +                     continue;
> +             switch (type & EXT_COMMUNITY_VALUE) {
>               case EXT_COMMUNITY_TRANS_TWO_AS:
>               case EXT_COMMUNITY_TRANS_OPAQUE:
>               case EXT_COMMUNITY_TRANS_EVPN:
> -             case EXT_COMMUNITY_NON_TRANS_OPAQUE:
>                       set.data1 = c >> 32 & 0xffff;
>                       set.data2 = c;
>                       break;
> @@ -564,7 +565,7 @@ community_ext_write(struct rde_community
>       for (l = 0; l < comm->nentries; l++)
>               if ((uint8_t)comm->communities[l].flags ==
>                   COMMUNITY_TYPE_EXT && !(ebgp &&
> -                 non_transitive_community(&comm->communities[l])))
> +                 non_transitive_ext_community(&comm->communities[l])))
>                       n++;
>  
>       if (n == 0)
> @@ -580,13 +581,12 @@ community_ext_write(struct rde_community
>       for (l = 0; l < comm->nentries; l++) {
>               cp = comm->communities + l;
>               if ((uint8_t)cp->flags == COMMUNITY_TYPE_EXT && !(ebgp &&
> -                 non_transitive_community(cp))) {
> +                 non_transitive_ext_community(cp))) {
>                       ext = (uint64_t)cp->data3 << 48;
> -                     switch (cp->data3 >> 8) {
> +                     switch ((cp->data3 >> 8) & EXT_COMMUNITY_VALUE) {
>                       case EXT_COMMUNITY_TRANS_TWO_AS:
>                       case EXT_COMMUNITY_TRANS_OPAQUE:
>                       case EXT_COMMUNITY_TRANS_EVPN:
> -                     case EXT_COMMUNITY_NON_TRANS_OPAQUE:
>                               ext |= ((uint64_t)cp->data1 & 0xffff) << 32;
>                               ext |= (uint64_t)cp->data2;
>                               break;
> @@ -672,11 +672,10 @@ community_writebuf(struct ibuf *buf, str
>                               continue;
>  
>                       ext = (uint64_t)cp->data3 << 48;
> -                     switch (cp->data3 >> 8) {
> +                     switch ((cp->data3 >> 8) & EXT_COMMUNITY_VALUE) {
>                       case EXT_COMMUNITY_TRANS_TWO_AS:
>                       case EXT_COMMUNITY_TRANS_OPAQUE:
>                       case EXT_COMMUNITY_TRANS_EVPN:
> -                     case EXT_COMMUNITY_NON_TRANS_OPAQUE:
>                               ext |= ((uint64_t)cp->data1 & 0xffff) << 32;
>                               ext |= (uint64_t)cp->data2;
>                               break;
> @@ -919,7 +918,7 @@ community_to_rd(struct community *fc, ui
>       if (fc2c(fc, NULL, &c, NULL) == -1)
>               return -1;
>  
> -     switch (c.data3 >> 8) {
> +     switch ((c.data3 >> 8) & EXT_COMMUNITY_VALUE) {
>       case EXT_COMMUNITY_TRANS_TWO_AS:
>               rd = (0ULL << 48);
>               rd |= ((uint64_t)c.data1 & 0xffff) << 32;
> 

Reply via email to