Claudio Jeker([email protected]) 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);
>