On Tue, Jun 15, 2021 at 06:14:38PM +0200, Claudio Jeker wrote:
> The Adj-RIB-Out should show what is sent to the peer. bgpd did not fully
> do that since it adjusted the ASPATH and the nexthop afterwards when
> building the actual UPDATE.
>
> This diff changes that and moves the ASPATH prepend for ebgp sessions and
> the selection of the nexthop. Thanks to this the output of `bgpctl show
> rib out` should now show what is actually sent.
>
> Please test.
> --
> :wq Claudio
>
> Index: rde.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
> retrieving revision 1.524
> diff -u -p -r1.524 rde.c
> --- rde.c 27 May 2021 16:32:13 -0000 1.524
> +++ rde.c 15 Jun 2021 12:44:32 -0000
> @@ -3567,6 +3567,14 @@ rde_softreconfig_out(struct rib_entry *r
> return;
>
> LIST_FOREACH(peer, &peerlist, peer_l) {
> + /* skip ourself */
> + if (peer == peerself)
> + continue;
> + if (peer->state != PEER_UP)
> + continue;
> + /* check if peer actually supports the address family */
> + if (peer->capa.mp[re->prefix->aid] == 0)
> + continue;
> if (peer->loc_rib_id == re->rib_id && peer->reconf_out)
> /* Regenerate all updates. */
> up_generate_updates(out_rules, peer, p, p);
This part of the diff fixes a few other issues. Mainly errors on startup
because wrong prefixes are sent out. Also errors about unknown peer with
id 1 are gone after adding this.
So people who noticed IPv6 updates on IPv4 sessions and vice versa should
try this out.
> Index: rde_rib.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
> retrieving revision 1.221
> diff -u -p -r1.221 rde_rib.c
> --- rde_rib.c 4 May 2021 09:27:09 -0000 1.221
> +++ rde_rib.c 15 Jun 2021 16:04:19 -0000
> @@ -1940,7 +1940,7 @@ nexthop_hash(struct bgpd_addr *nexthop)
> sizeof(struct in6_addr));
> break;
> default:
> - fatalx("nexthop_hash: unsupported AF");
> + fatalx("nexthop_hash: unsupported AID %d", nexthop->aid);
> }
> return (&nexthoptable.nexthop_hashtbl[h &
> nexthoptable.nexthop_hashmask]);
> }
> Index: rde_update.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_update.c,v
> retrieving revision 1.129
> diff -u -p -r1.129 rde_update.c
> --- rde_update.c 27 May 2021 14:32:08 -0000 1.129
> +++ rde_update.c 15 Jun 2021 16:02:50 -0000
> @@ -45,6 +45,8 @@ static struct community comm_no_expsubco
> .data2 = COMMUNITY_NO_EXPSUBCONFED
> };
>
> +static void up_prep_adjout(struct rde_peer *, struct filterstate *,
> u_int8_t);
> +
> static int
> up_test_update(struct rde_peer *peer, struct prefix *p)
> {
> @@ -166,6 +168,8 @@ again:
> goto again;
> }
>
> + up_prep_adjout(peer, &state, addr.aid);
> +
> /* only send update if path changed */
> if (prefix_adjout_update(peer, &state, &addr,
> new->pt->prefixlen, prefix_vstate(new)) == 1) {
> @@ -225,6 +229,8 @@ up_generate_default(struct filter_head *
> return;
> }
>
> + up_prep_adjout(peer, &state, addr.aid);
> +
> if (prefix_adjout_update(peer, &state, &addr, 0, ROA_NOTFOUND) == 1) {
> peer->prefix_out_cnt++;
> peer->up_nlricnt++;
> @@ -244,7 +250,6 @@ up_generate_default(struct filter_head *
> }
> }
>
> -/* only for IPv4 */
> static struct bgpd_addr *
> up_get_nexthop(struct rde_peer *peer, struct filterstate *state, u_int8_t
> aid)
> {
> @@ -325,6 +330,32 @@ up_get_nexthop(struct rde_peer *peer, st
> }
> }
>
> +static void
> +up_prep_adjout(struct rde_peer *peer, struct filterstate *state, u_int8_t
> aid)
> +{
> + struct bgpd_addr *nexthop;
> + struct nexthop *nh;
> + u_char *np;
> + u_int16_t nl;
> +
> + /* prepend local AS number for eBGP sessions. */
> + if (peer->conf.ebgp && (peer->flags & PEERFLAG_TRANS_AS) == 0) {
> + u_int32_t prep_as = peer->conf.local_as;
> + np = aspath_prepend(state->aspath.aspath, prep_as, 1, &nl);
> + aspath_put(state->aspath.aspath);
> + state->aspath.aspath = aspath_get(np, nl);
> + free(np);
> + }
> +
> + /* update nexthop */
> + nexthop = up_get_nexthop(peer, state, aid);
> + nh = nexthop_get(nexthop);
> + nexthop_unref(state->nexthop);
> + state->nexthop = nh;
> + state->nhflags = 0;
> +}
> +
> +
> static int
> up_generate_attr(u_char *buf, int len, struct rde_peer *peer,
> struct filterstate *state, u_int8_t aid)
> @@ -334,7 +365,7 @@ up_generate_attr(u_char *buf, int len, s
> struct attr *oa = NULL, *newaggr = NULL;
> u_char *pdata;
> u_int32_t tmp32;
> - in_addr_t nexthop;
> + struct bgpd_addr *nexthop;
> int flags, r, neednewpath = 0;
> u_int16_t wlen = 0, plen;
> u_int8_t oalen = 0, type;
> @@ -363,13 +394,8 @@ up_generate_attr(u_char *buf, int len, s
> return (-1);
> break;
> case ATTR_ASPATH:
> - if (!peer->conf.ebgp ||
> - peer->flags & PEERFLAG_TRANS_AS)
> - pdata = aspath_prepend(asp->aspath,
> - peer->conf.local_as, 0, &plen);
> - else
> - pdata = aspath_prepend(asp->aspath,
> - peer->conf.local_as, 1, &plen);
> + plen = aspath_length(asp->aspath);
> + pdata = aspath_dump(asp->aspath);
>
> if (!peer_has_as4byte(peer))
> pdata = aspath_deflate(pdata, &plen,
> @@ -378,16 +404,16 @@ up_generate_attr(u_char *buf, int len, s
> if ((r = attr_write(buf + wlen, len, ATTR_WELL_KNOWN,
> ATTR_ASPATH, pdata, plen)) == -1)
> return (-1);
> - free(pdata);
> + if (!peer_has_as4byte(peer))
> + free(pdata);
> break;
> case ATTR_NEXTHOP:
> switch (aid) {
> case AID_INET:
> - nexthop =
> - up_get_nexthop(peer, state, aid)->v4.s_addr;
> + nexthop = &state->nexthop->exit_nexthop;
> if ((r = attr_write(buf + wlen, len,
> - ATTR_WELL_KNOWN, ATTR_NEXTHOP, &nexthop,
> - 4)) == -1)
> + ATTR_WELL_KNOWN, ATTR_NEXTHOP,
> + &nexthop->v4.s_addr, 4)) == -1)
> return (-1);
> break;
> default:
> @@ -442,13 +468,9 @@ up_generate_attr(u_char *buf, int len, s
> */
> case ATTR_AS4_PATH:
> if (neednewpath) {
> - if (!peer->conf.ebgp ||
> - peer->flags & PEERFLAG_TRANS_AS)
> - pdata = aspath_prepend(asp->aspath,
> - peer->conf.local_as, 0, &plen);
> - else
> - pdata = aspath_prepend(asp->aspath,
> - peer->conf.local_as, 1, &plen);
> + plen = aspath_length(asp->aspath);
> + pdata = aspath_dump(asp->aspath);
> +
> flags = ATTR_OPTIONAL|ATTR_TRANSITIVE;
> if (!(asp->flags & F_PREFIX_ANNOUNCED))
> flags |= ATTR_PARTIAL;
> @@ -457,7 +479,6 @@ up_generate_attr(u_char *buf, int len, s
> else if ((r = attr_write(buf + wlen, len, flags,
> ATTR_AS4_PATH, pdata, plen)) == -1)
> return (-1);
> - free(pdata);
> }
> break;
> case ATTR_AS4_AGGREGATOR:
> @@ -786,7 +807,7 @@ up_generate_mp_reach(u_char *buf, int le
>
> /* write nexthop */
> attrbuf += 4;
> - nexthop = up_get_nexthop(peer, state, aid);
> + nexthop = &state->nexthop->exit_nexthop;
> memcpy(attrbuf, &nexthop->v6, sizeof(struct in6_addr));
> break;
> case AID_VPN_IPv4:
> @@ -804,7 +825,7 @@ up_generate_mp_reach(u_char *buf, int le
>
> /* write nexthop */
> attrbuf += 12;
> - nexthop = up_get_nexthop(peer, state, aid);
> + nexthop = &state->nexthop->exit_nexthop;
> memcpy(attrbuf, &nexthop->v4, sizeof(struct in_addr));
> break;
> case AID_VPN_IPv6:
> @@ -822,7 +843,7 @@ up_generate_mp_reach(u_char *buf, int le
>
> /* write nexthop */
> attrbuf += 12;
> - nexthop = up_get_nexthop(peer, state, aid);
> + nexthop = &state->nexthop->exit_nexthop;
> memcpy(attrbuf, &nexthop->v6, sizeof(struct in6_addr));
> break;
> default:
>
--
:wq Claudio