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

Reply via email to