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); >