Claudio Jeker(cje...@diehard.n-r-g.com) on 2019.06.22 10:30:46 +0200:
> Once again I broke mrt table dumps a bit. This time by not dumping the

sorry about that.

> community data anymore. Add this back by adding the needed code in
> rde_community.c and some other minor adjustments.
> 
> With this the just commited regress test passes again :)

and i checked the dumps, and the code looks ok.

> -- 
> :wq Claudio
> 
> Index: mrt.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/mrt.c,v
> retrieving revision 1.95
> diff -u -p -r1.95 mrt.c
> --- mrt.c     22 Jun 2019 05:44:05 -0000      1.95
> +++ mrt.c     22 Jun 2019 06:34:50 -0000
> @@ -34,7 +34,8 @@
>  #include "mrt.h"
>  #include "log.h"
>  
> -int mrt_attr_dump(struct ibuf *, struct rde_aspath *, struct bgpd_addr *, 
> int);
> +int mrt_attr_dump(struct ibuf *, struct rde_aspath *, struct rde_community *,
> +    struct bgpd_addr *, int);
>  int mrt_dump_entry_mp(struct mrt *, struct prefix *, u_int16_t,
>      struct rde_peer*);
>  int mrt_dump_entry(struct mrt *, struct prefix *, u_int16_t, struct 
> rde_peer*);
> @@ -143,8 +144,8 @@ fail:
>  }
>  
>  int
> -mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct bgpd_addr 
> *nexthop,
> -    int v2)
> +mrt_attr_dump(struct ibuf *buf, struct rde_aspath *a, struct rde_community 
> *c,
> +    struct bgpd_addr *nexthop, int v2)
>  {
>       struct attr     *oa;
>       u_char          *pdata;
> @@ -188,6 +189,10 @@ mrt_attr_dump(struct ibuf *buf, struct r
>       if (attr_writebuf(buf, ATTR_WELL_KNOWN, ATTR_LOCALPREF, &tmp, 4) == -1)
>               return (-1);
>  
> +     /* communities */
> +     if (community_writebuf(buf, c) == -1)
> +             return (-1);
> +
>       /* dump all other path attributes without modification */
>       for (l = 0; l < a->others_len; l++) {
>               if ((oa = a->others[l]) == NULL)
> @@ -272,7 +277,8 @@ mrt_dump_entry_mp(struct mrt *mrt, struc
>               return (-1);
>       }
>  
> -     if (mrt_attr_dump(buf, prefix_aspath(p), NULL, 0) == -1) {
> +     if (mrt_attr_dump(buf, prefix_aspath(p), prefix_communities(p),
> +         NULL, 0) == -1) {
>               log_warnx("mrt_dump_entry_mp: mrt_attr_dump error");
>               goto fail;
>       }
> @@ -401,7 +407,8 @@ mrt_dump_entry(struct mrt *mrt, struct p
>               nh = &addr;
>       } else
>               nh = &nexthop->exit_nexthop;
> -     if (mrt_attr_dump(buf, prefix_aspath(p), nh, 0) == -1) {
> +     if (mrt_attr_dump(buf, prefix_aspath(p), prefix_communities(p),
> +         nh, 0) == -1) {
>               log_warnx("mrt_dump_entry: mrt_attr_dump error");
>               ibuf_free(buf);
>               return (-1);
> @@ -529,7 +536,8 @@ mrt_dump_entry_v2(struct mrt *mrt, struc
>                       log_warn("%s: ibuf_dynamic", __func__);
>                       return (-1);
>               }
> -             if (mrt_attr_dump(tbuf, prefix_aspath(p), nh, 1) == -1) {
> +             if (mrt_attr_dump(tbuf, prefix_aspath(p), prefix_communities(p),
> +                 nh, 1) == -1) {
>                       log_warnx("%s: mrt_attr_dump error", __func__);
>                       ibuf_free(buf);
>                       return (-1);
> @@ -641,7 +649,7 @@ mrt_dump_peer(struct ibuf *buf, struct r
>                       goto fail;
>               }
>               break;
> -     case AID_UNSPEC: /* XXX special handling for peer_self? */
> +     case AID_UNSPEC: /* XXX special handling for peerself? */
>               DUMP_NLONG(buf, 0);
>               break;
>       default:
> Index: rde.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
> retrieving revision 1.217
> diff -u -p -r1.217 rde.h
> --- rde.h     22 Jun 2019 05:44:05 -0000      1.217
> +++ rde.h     22 Jun 2019 06:34:50 -0000
> @@ -395,20 +395,21 @@ u_char          *aspath_override(struct aspath *
>                   u_int16_t *);
>  int           aspath_lenmatch(struct aspath *, enum aslen_spec, u_int);
>  
> -int   community_match(struct rde_community *, struct community *,
> +int  community_match(struct rde_community *, struct community *,
>           struct rde_peer *);
> -int   community_set(struct rde_community *, struct community *,
> +int  community_set(struct rde_community *, struct community *,
>           struct rde_peer *);
> -void  community_delete(struct rde_community *, struct community *,
> +void community_delete(struct rde_community *, struct community *,
>           struct rde_peer *);
>  
> -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_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_write(struct rde_community *, void *, u_int16_t);
> -int   community_large_write(struct rde_community *, void *, u_int16_t);
> -int   community_ext_write(struct rde_community *, int, void *, u_int16_t);
> +int  community_write(struct rde_community *, void *, u_int16_t);
> +int  community_large_write(struct rde_community *, void *, u_int16_t);
> +int  community_ext_write(struct rde_community *, int, void *, u_int16_t);
> +int  community_writebuf(struct ibuf *, struct rde_community *);
>  
>  void                  communities_init(u_int32_t);
>  void                  communities_shutdown(void);
> Index: rde_attr.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_attr.c,v
> retrieving revision 1.122
> diff -u -p -r1.122 rde_attr.c
> --- rde_attr.c        17 Jun 2019 11:02:19 -0000      1.122
> +++ rde_attr.c        21 Jun 2019 09:45:42 -0000
> @@ -86,7 +86,7 @@ attr_writebuf(struct ibuf *buf, u_int8_t
>  
>       if (ibuf_add(buf, hdr, flags & ATTR_EXTLEN ? 4 : 3) == -1)
>               return (-1);
> -     if (ibuf_add(buf, data, data_len) == -1)
> +     if (data && ibuf_add(buf, data, data_len) == -1)
>               return (-1);
>       return (0);
>  }
> Index: rde_community.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_community.c,v
> retrieving revision 1.1
> diff -u -p -r1.1 rde_community.c
> --- rde_community.c   17 Jun 2019 11:02:19 -0000      1.1
> +++ rde_community.c   21 Jun 2019 09:57:20 -0000
> @@ -607,6 +607,121 @@ community_ext_write(struct rde_community
>  }
>  
>  /*
> + * Convert communities back to the wireformat and dump them into the ibuf 
> buf.
> + * This function is used by the mrt dump code.
> + */
> +int
> +community_writebuf(struct ibuf *buf, struct rde_community *comm)
> +{
> +     size_t l, basic_n = 0, large_n = 0, ext_n = 0;
> +     int flags;
> +
> +     /* first count how many communities will be written */
> +     for (l = 0; l < comm->nentries; l++)
> +             if ((u_int8_t)comm->communities[l].flags ==
> +                 COMMUNITY_TYPE_BASIC)
> +                     basic_n++;
> +             else if ((u_int8_t)comm->communities[l].flags ==
> +                 COMMUNITY_TYPE_EXT)
> +                     ext_n++;
> +             else if ((u_int8_t)comm->communities[l].flags ==
> +                 COMMUNITY_TYPE_LARGE)
> +                     large_n++;
> +
> +
> +     if (basic_n != 0) {
> +             /* write attribute header */
> +             flags = ATTR_OPTIONAL | ATTR_TRANSITIVE;
> +             if (comm->flags & PARTIAL_COMMUNITIES)
> +                     flags |= ATTR_PARTIAL;
> +
> +             if (attr_writebuf(buf, flags, ATTR_COMMUNITIES, NULL,
> +                 basic_n * 4) == -1)
> +                     return -1;
> +
> +             /* write out the communities */
> +             for (l = 0; l < comm->nentries; l++)
> +                     if ((u_int8_t)comm->communities[l].flags ==
> +                         COMMUNITY_TYPE_BASIC) {
> +                             u_int16_t c;
> +                             c = htons(comm->communities[l].data1);
> +                             if (ibuf_add(buf, &c, sizeof(c)) == -1)
> +                                     return (-1);
> +                             c = htons(comm->communities[l].data2);
> +                             if (ibuf_add(buf, &c, sizeof(c)) == -1)
> +                                     return (-1);
> +                     }
> +     }
> +     if (ext_n != 0) {
> +             /* write attribute header */
> +             flags = ATTR_OPTIONAL | ATTR_TRANSITIVE;
> +             if (comm->flags & PARTIAL_COMMUNITIES)
> +                     flags |= ATTR_PARTIAL;
> +
> +             if (attr_writebuf(buf, flags, ATTR_EXT_COMMUNITIES, NULL,
> +                 ext_n * 8) == -1)
> +                     return -1;
> +
> +             /* write out the communities */
> +             for (l = 0; l < comm->nentries; l++) {
> +                     struct community *cp;
> +                     u_int64_t ext;
> +
> +                     cp = comm->communities + l;
> +                     if ((u_int8_t)cp->flags != COMMUNITY_TYPE_EXT)
> +                             continue;
> +
> +                     ext = (u_int64_t)cp->data3 << 48;
> +                     switch (cp->data3 >> 8) {
> +                     case EXT_COMMUNITY_TRANS_TWO_AS:
> +                     case EXT_COMMUNITY_TRANS_OPAQUE:
> +                     case EXT_COMMUNITY_TRANS_EVPN:
> +                     case EXT_COMMUNITY_NON_TRANS_OPAQUE:
> +                             ext |= ((u_int64_t)cp->data1 & 0xffff) << 32;
> +                             ext |= (u_int64_t)cp->data2;
> +                             break;
> +                     case EXT_COMMUNITY_TRANS_FOUR_AS:
> +                     case EXT_COMMUNITY_TRANS_IPV4:
> +                             ext |= (u_int64_t)cp->data1 << 16;
> +                             ext |= (u_int64_t)cp->data2 & 0xffff;
> +                             break;
> +                     }
> +                     ext = htobe64(ext);
> +                     if (ibuf_add(buf, &ext, sizeof(ext)) == -1)
> +                             return (-1);
> +             }
> +     }
> +     if (large_n != 0) {
> +             /* write attribute header */
> +             flags = ATTR_OPTIONAL | ATTR_TRANSITIVE;
> +             if (comm->flags & PARTIAL_COMMUNITIES)
> +                     flags |= ATTR_PARTIAL;
> +
> +             if (attr_writebuf(buf, flags, ATTR_LARGE_COMMUNITIES, NULL,
> +                 large_n * 12) == -1)
> +                     return -1;
> +
> +             /* write out the communities */
> +             for (l = 0; l < comm->nentries; l++)
> +                     if ((u_int8_t)comm->communities[l].flags ==
> +                         COMMUNITY_TYPE_LARGE) {
> +                             u_int32_t c;
> +                             c = htonl(comm->communities[l].data1);
> +                             if (ibuf_add(buf, &c, sizeof(c)) == -1)
> +                                     return (-1);
> +                             c = htonl(comm->communities[l].data2);
> +                             if (ibuf_add(buf, &c, sizeof(c)) == -1)
> +                                     return (-1);
> +                             c = htonl(comm->communities[l].data3);
> +                             if (ibuf_add(buf, &c, sizeof(c)) == -1)
> +                                     return (-1);
> +                     }
> +     }
> +
> +     return 0;
> +}
> +
> +/*
>   * Global RIB cache for communities
>   */
>  LIST_HEAD(commhead, rde_community);
> 

Reply via email to