From ca69ff0dd9096e3ac14c2db5373ee21b855fdfd7 Mon Sep 17 00:00:00 2001 From: claudio Date: Fri, 8 Jul 2022 08:11:25 +0000 Subject: [PATCH] Assign a local path_id to all prefixes For add-path a unique path_id needs to be assigne to all prefixes. Use a random number since the RFC explicitly mentions that there is no meaning what the value means. The local path_id is inherited to all the RIBs. Adj-RIB-Out handling is not yet down. OK tb@ --- usr.sbin/bgpd/rde.c | 67 +++++++++++++++++++++++++++++++++++------ usr.sbin/bgpd/rde.h | 5 +-- usr.sbin/bgpd/rde_rib.c | 42 ++++++++++++++------------ 3 files changed, 83 insertions(+), 31 deletions(-) diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 4a1c5152a1e..0e34027b132 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.551 2022/07/07 13:55:52 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.552 2022/07/08 08:11:25 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -1600,6 +1600,46 @@ done: rde_filterstate_clean(&state); } +/* + * Check if path_id is already in use. + */ +static int +pathid_conflict(struct rib_entry *re, uint32_t pathid) +{ + struct prefix *p; + + if (re == NULL) + return 0; + + TAILQ_FOREACH(p, &re->prefix_h, entry.list.rib) + if (p->path_id_tx == pathid) + return 1; + return 0; +} + +static uint32_t +pathid_assign(struct rde_peer *peer, uint32_t path_id, + struct bgpd_addr *prefix, uint8_t prefixlen) +{ + struct rib_entry *re; + struct prefix *p = NULL; + uint32_t path_id_tx; + + /* Assign a send side path_id to all paths */ + re = rib_get(rib_byid(RIB_ADJ_IN), prefix, prefixlen); + if (re != NULL) + p = prefix_bypeer(re, peer, path_id); + if (p != NULL) + path_id_tx = p->path_id_tx; + else { + do { + /* assign new local path_id */ + path_id_tx = arc4random(); + } while (pathid_conflict(re, path_id_tx)); + } + return path_id_tx; +} + int rde_update_update(struct rde_peer *peer, uint32_t path_id, struct filterstate *in, struct bgpd_addr *prefix, uint8_t prefixlen) @@ -1608,15 +1648,18 @@ rde_update_update(struct rde_peer *peer, uint32_t path_id, enum filter_actions action; uint8_t vstate; uint16_t i; + uint32_t path_id_tx; const char *wmsg = "filtered, withdraw"; peer->prefix_rcvd_update++; vstate = rde_roa_validity(&rde_roa, prefix, prefixlen, aspath_origin(in->aspath.aspath)); + path_id_tx = pathid_assign(peer, path_id, prefix, prefixlen); + /* add original path to the Adj-RIB-In */ - if (prefix_update(rib_byid(RIB_ADJ_IN), peer, path_id, in, - prefix, prefixlen, vstate) == 1) + if (prefix_update(rib_byid(RIB_ADJ_IN), peer, path_id, path_id_tx, + in, prefix, prefixlen, vstate) == 1) peer->prefix_cnt++; /* max prefix checker */ @@ -1644,8 +1687,8 @@ rde_update_update(struct rde_peer *peer, uint32_t path_id, rde_update_log("update", i, peer, &state.nexthop->exit_nexthop, prefix, prefixlen); - prefix_update(rib, peer, path_id, &state, prefix, - prefixlen, vstate); + prefix_update(rib, peer, path_id, path_id_tx, &state, + prefix, prefixlen, vstate); } else if (prefix_withdraw(rib, peer, path_id, prefix, prefixlen)) { rde_update_log(wmsg, i, peer, @@ -3719,7 +3762,8 @@ rde_softreconfig_in(struct rib_entry *re, void *bula) if (action == ACTION_ALLOW) { /* update Local-RIB */ - prefix_update(rib, peer, p->path_id, &state, + prefix_update(rib, peer, p->path_id, + p->path_id_tx, &state, &prefix, pt->prefixlen, p->validation_state); } else if (action == ACTION_DENY) { @@ -3858,7 +3902,8 @@ rde_roa_softreload(struct rib_entry *re, void *bula) if (action == ACTION_ALLOW) { /* update Local-RIB */ - prefix_update(rib, peer, p->path_id, &state, + prefix_update(rib, peer, p->path_id, + p->path_id_tx, &state, &prefix, pt->prefixlen, p->validation_state); } else if (action == ACTION_DENY) { @@ -4026,6 +4071,7 @@ network_add(struct network_config *nc, struct filterstate *state) struct in6_addr prefix6; uint8_t vstate; uint16_t i; + uint32_t path_id_tx; if (nc->rd != 0) { SIMPLEQ_FOREACH(vpn, &conf->l3vpns, entry) { @@ -4087,8 +4133,9 @@ network_add(struct network_config *nc, struct filterstate *state) vstate = rde_roa_validity(&rde_roa, &nc->prefix, nc->prefixlen, aspath_origin(state->aspath.aspath)); - if (prefix_update(rib_byid(RIB_ADJ_IN), peerself, 0, state, &nc->prefix, - nc->prefixlen, vstate) == 1) + path_id_tx = pathid_assign(peerself, 0, &nc->prefix, nc->prefixlen); + if (prefix_update(rib_byid(RIB_ADJ_IN), peerself, 0, path_id_tx, + state, &nc->prefix, nc->prefixlen, vstate) == 1) peerself->prefix_cnt++; for (i = RIB_LOC_START; i < rib_size; i++) { struct rib *rib = rib_byid(i); @@ -4097,7 +4144,7 @@ network_add(struct network_config *nc, struct filterstate *state) rde_update_log("announce", i, peerself, state->nexthop ? &state->nexthop->exit_nexthop : NULL, &nc->prefix, nc->prefixlen); - prefix_update(rib, peerself, 0, state, &nc->prefix, + prefix_update(rib, peerself, 0, path_id_tx, state, &nc->prefix, nc->prefixlen, vstate); } filterset_free(&nc->attrset); diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index af61093f5d6..56c567f9abe 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.256 2022/07/07 12:16:04 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.257 2022/07/08 08:11:25 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker and @@ -611,7 +611,8 @@ struct prefix *prefix_adjout_lookup(struct rde_peer *, struct bgpd_addr *, int); struct prefix *prefix_adjout_next(struct rde_peer *, struct prefix *); int prefix_update(struct rib *, struct rde_peer *, uint32_t, - struct filterstate *, struct bgpd_addr *, int, uint8_t); + uint32_t, struct filterstate *, struct bgpd_addr *, + int, uint8_t); int prefix_withdraw(struct rib *, struct rde_peer *, uint32_t, struct bgpd_addr *, int); void prefix_add_eor(struct rde_peer *, uint8_t); diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index 6977578d59b..69db4e83b4d 100644 --- a/usr.sbin/bgpd/rde_rib.c +++ b/usr.sbin/bgpd/rde_rib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_rib.c,v 1.238 2022/05/23 13:40:12 deraadt Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.239 2022/07/08 08:11:25 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker @@ -842,7 +842,7 @@ path_put(struct rde_aspath *asp) /* prefix specific functions */ static int prefix_add(struct bgpd_addr *, int, struct rib *, - struct rde_peer *, uint32_t, struct rde_aspath *, + struct rde_peer *, uint32_t, uint32_t, struct rde_aspath *, struct rde_community *, struct nexthop *, uint8_t, uint8_t); static int prefix_move(struct prefix *, struct rde_peer *, @@ -850,7 +850,7 @@ static int prefix_move(struct prefix *, struct rde_peer *, struct nexthop *, uint8_t, uint8_t); static void prefix_link(struct prefix *, struct rib_entry *, - struct pt_entry *, struct rde_peer *, uint32_t, + struct pt_entry *, struct rde_peer *, uint32_t, uint32_t, struct rde_aspath *, struct rde_community *, struct nexthop *, uint8_t, uint8_t); static void prefix_unlink(struct prefix *); @@ -1001,8 +1001,8 @@ prefix_adjout_match(struct rde_peer *peer, struct bgpd_addr *addr) */ int prefix_update(struct rib *rib, struct rde_peer *peer, uint32_t path_id, - struct filterstate *state, struct bgpd_addr *prefix, int prefixlen, - uint8_t vstate) + uint32_t path_id_tx, struct filterstate *state, struct bgpd_addr *prefix, + int prefixlen, uint8_t vstate) { struct rde_aspath *asp, *nasp = &state->aspath; struct rde_community *comm, *ncomm = &state->communities; @@ -1012,6 +1012,8 @@ prefix_update(struct rib *rib, struct rde_peer *peer, uint32_t path_id, * First try to find a prefix in the specified RIB. */ if ((p = prefix_get(rib, peer, path_id, prefix, prefixlen)) != NULL) { + if (path_id_tx != p->path_id_tx) + fatalx("path_id mismatch"); if (prefix_nexthop(p) == state->nexthop && prefix_nhflags(p) == state->nhflags && communities_equal(ncomm, prefix_communities(p)) && @@ -1044,8 +1046,9 @@ prefix_update(struct rib *rib, struct rde_peer *peer, uint32_t path_id, return (prefix_move(p, peer, asp, comm, state->nexthop, state->nhflags, vstate)); else - return (prefix_add(prefix, prefixlen, rib, peer, path_id, asp, - comm, state->nexthop, state->nhflags, vstate)); + return (prefix_add(prefix, prefixlen, rib, peer, path_id, + path_id_tx, asp, comm, state->nexthop, state->nhflags, + vstate)); } /* @@ -1053,9 +1056,9 @@ prefix_update(struct rib *rib, struct rde_peer *peer, uint32_t path_id, */ static int prefix_add(struct bgpd_addr *prefix, int prefixlen, struct rib *rib, - struct rde_peer *peer, uint32_t path_id, struct rde_aspath *asp, - struct rde_community *comm, struct nexthop *nexthop, uint8_t nhflags, - uint8_t vstate) + struct rde_peer *peer, uint32_t path_id, uint32_t path_id_tx, + struct rde_aspath *asp, struct rde_community *comm, + struct nexthop *nexthop, uint8_t nhflags, uint8_t vstate) { struct prefix *p; struct rib_entry *re; @@ -1065,8 +1068,8 @@ prefix_add(struct bgpd_addr *prefix, int prefixlen, struct rib *rib, re = rib_add(rib, prefix, prefixlen); p = prefix_alloc(); - prefix_link(p, re, re->prefix, peer, path_id, asp, comm, nexthop, - nhflags, vstate); + prefix_link(p, re, re->prefix, peer, path_id, path_id_tx, asp, comm, + nexthop, nhflags, vstate); /* add possible pftable reference form aspath */ if (asp && asp->pftableid) @@ -1094,8 +1097,8 @@ prefix_move(struct prefix *p, struct rde_peer *peer, /* add new prefix node */ np = prefix_alloc(); - prefix_link(np, prefix_re(p), p->pt, peer, p->path_id, asp, comm, - nexthop, nhflags, vstate); + prefix_link(np, prefix_re(p), p->pt, peer, p->path_id, p->path_id_tx, + asp, comm, nexthop, nhflags, vstate); /* add possible pftable reference from new aspath */ if (asp && asp->pftableid) @@ -1232,8 +1235,8 @@ prefix_adjout_update(struct rde_peer *peer, struct filterstate *state, comm = communities_link(&state->communities); } - prefix_link(p, NULL, p->pt, peer, 0, asp, comm, state->nexthop, - state->nhflags, vstate); + prefix_link(p, NULL, p->pt, peer, 0, /* XXX */ 0, asp, comm, + state->nexthop, state->nhflags, vstate); peer->prefix_out_cnt++; if (p->flags & PREFIX_FLAG_MASK) @@ -1549,9 +1552,9 @@ prefix_destroy(struct prefix *p) */ static void prefix_link(struct prefix *p, struct rib_entry *re, struct pt_entry *pt, - struct rde_peer *peer, uint32_t path_id, struct rde_aspath *asp, - struct rde_community *comm, struct nexthop *nexthop, uint8_t nhflags, - uint8_t vstate) + struct rde_peer *peer, uint32_t path_id, uint32_t path_id_tx, + struct rde_aspath *asp, struct rde_community *comm, + struct nexthop *nexthop, uint8_t nhflags, uint8_t vstate) { if (re) p->entry.list.re = re; @@ -1560,6 +1563,7 @@ prefix_link(struct prefix *p, struct rib_entry *re, struct pt_entry *pt, p->peer = peer; p->pt = pt_ref(pt); p->path_id = path_id; + p->path_id_tx = path_id_tx; p->validation_state = vstate; p->nhflags = nhflags; p->nexthop = nexthop_ref(nexthop); -- 2.20.1