-/* $OpenBSD: rde.c,v 1.535 2022/02/24 14:54:03 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.536 2022/02/25 11:36:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
do {
if (req->prefixlen == hostplen)
- p = prefix_match(peer, &req->prefix);
+ p = prefix_adjout_match(peer,
+ &req->prefix);
else
- p = prefix_lookup(peer, &req->prefix,
- req->prefixlen);
- if (p)
+ p = prefix_adjout_lookup(peer,
+ &req->prefix, req->prefixlen);
+ /* dump all matching paths */
+ while (p != NULL) {
rde_dump_adjout_upcall(p, ctx);
+ p = prefix_adjout_next(peer, p);
+ };
} while ((peer = peer_match(&req->neighbor,
peer->conf.id)));
-/* $OpenBSD: rde.h,v 1.243 2022/02/06 09:51:19 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.244 2022/02/25 11:36:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
#define PREFIX_SIZE(x) (((x) + 7) / 8 + 1)
struct prefix *prefix_get(struct rib *, struct rde_peer *, uint32_t,
struct bgpd_addr *, int);
-struct prefix *prefix_lookup(struct rde_peer *, struct bgpd_addr *, int);
+struct prefix *prefix_adjout_get(struct rde_peer *, uint32_t,
+ struct bgpd_addr *, int);
struct prefix *prefix_match(struct rde_peer *, struct bgpd_addr *);
+struct prefix *prefix_adjout_match(struct rde_peer *, struct bgpd_addr *);
+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);
int prefix_withdraw(struct rib *, struct rde_peer *, uint32_t,
-/* $OpenBSD: rde_rib.c,v 1.225 2022/02/06 09:51:19 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.226 2022/02/25 11:36:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
static void prefix_free(struct prefix *);
/* RB tree comparison function */
+static inline int
+prefix_index_cmp(struct prefix *a, struct prefix *b)
+{
+ int r;
+ r = pt_prefix_cmp(a->pt, b->pt);
+ if (r != 0)
+ return r;
+
+ if (a->path_id_tx > b->path_id_tx)
+ return 1;
+ if (a->path_id_tx < b->path_id_tx)
+ return -1;
+ return 0;
+}
+
static inline int
prefix_cmp(struct prefix *a, struct prefix *b)
{
return (a->nexthop > b->nexthop ? 1 : -1);
if (a->nhflags != b->nhflags)
return (a->nhflags > b->nhflags ? 1 : -1);
- /* XXX path_id ??? */
- return pt_prefix_cmp(a->pt, b->pt);
-}
-
-static inline int
-prefix_index_cmp(struct prefix *a, struct prefix *b)
-{
- /* XXX path_id ??? */
- return pt_prefix_cmp(a->pt, b->pt);
+ return prefix_index_cmp(a, b);
}
RB_GENERATE(prefix_tree, prefix, entry.tree.update, prefix_cmp)
RB_GENERATE_STATIC(prefix_index, prefix, entry.tree.index, prefix_index_cmp)
/*
- * search for specified prefix of a peer. Returns NULL if not found.
+ * Search for specified prefix of a peer. Returns NULL if not found.
*/
struct prefix *
prefix_get(struct rib *rib, struct rde_peer *peer, uint32_t path_id,
}
/*
- * lookup prefix in the peer prefix_index. Returns NULL if not found.
+ * Search for specified prefix in the peer prefix_index.
+ * Returns NULL if not found.
*/
struct prefix *
-prefix_lookup(struct rde_peer *peer, struct bgpd_addr *prefix,
- int prefixlen)
+prefix_adjout_get(struct rde_peer *peer, uint32_t path_id,
+ struct bgpd_addr *prefix, int prefixlen)
{
struct prefix xp;
struct pt_entry *pte;
memset(&xp, 0, sizeof(xp));
pte = pt_fill(prefix, prefixlen);
xp.pt = pte;
+ xp.path_id_tx = path_id;
return RB_FIND(prefix_index, &peer->adj_rib_out, &xp);
}
+/*
+ * Lookup a prefix without considering path_id in the peer prefix_index.
+ * Returns NULL if not found.
+ */
+struct prefix *
+prefix_adjout_lookup(struct rde_peer *peer, struct bgpd_addr *prefix,
+ int prefixlen)
+{
+ struct prefix xp, *np;
+ struct pt_entry *pte;
+
+ memset(&xp, 0, sizeof(xp));
+ pte = pt_fill(prefix, prefixlen);
+ xp.pt = pte;
+
+ np = RB_NFIND(prefix_index, &peer->adj_rib_out, &xp);
+ if (np != NULL && pt_prefix_cmp(np->pt, xp.pt) != 0)
+ return NULL;
+ return np;
+}
+
+struct prefix *
+prefix_adjout_next(struct rde_peer *peer, struct prefix *p)
+{
+ struct prefix *np;
+
+ np = RB_NEXT(prefix_index, &peer->adj_rib_out, p);
+ if (np == NULL || p->pt != np->pt)
+ return NULL;
+ return np;
+}
+
+/*
+ * Lookup addr in the peer prefix_index. Returns first match.
+ * Returns NULL if not found.
+ */
struct prefix *
-prefix_match(struct rde_peer *peer, struct bgpd_addr *addr)
+prefix_adjout_match(struct rde_peer *peer, struct bgpd_addr *addr)
{
struct prefix *p;
int i;
case AID_INET:
case AID_VPN_IPv4:
for (i = 32; i >= 0; i--) {
- p = prefix_lookup(peer, addr, i);
+ p = prefix_adjout_lookup(peer, addr, i);
if (p != NULL)
return p;
}
case AID_INET6:
case AID_VPN_IPv6:
for (i = 128; i >= 0; i--) {
- p = prefix_lookup(peer, addr, i);
+ p = prefix_adjout_lookup(peer, addr, i);
if (p != NULL)
return p;
}
struct prefix *p;
int created = 0;
- if ((p = prefix_lookup(peer, prefix, prefixlen)) != NULL) {
+ if ((p = prefix_adjout_get(peer, 0, prefix, prefixlen)) != NULL) {
if ((p->flags & PREFIX_FLAG_ADJOUT) == 0)
fatalx("%s: prefix without PREFIX_FLAG_ADJOUT hit",
__func__);
p->pt = pt_add(prefix, prefixlen);
pt_ref(p->pt);
p->peer = peer;
+ p->path_id_tx = 0 /* XXX force this for now */;
if (RB_INSERT(prefix_index, &peer->adj_rib_out, p) != NULL)
fatalx("%s: RB index invariant violated", __func__);
{
struct prefix *p;
- p = prefix_lookup(peer, prefix, prefixlen);
+ p = prefix_adjout_get(peer, 0, prefix, prefixlen);
if (p == NULL) /* Got a dummy withdrawn request. */
return (0);