-/* $OpenBSD: rde.h,v 1.288 2023/03/28 15:17:34 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.289 2023/03/29 10:46:11 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
struct prefix *prefix_get(struct rib *, struct rde_peer *, uint32_t,
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 pt_entry *);
+struct prefix *prefix_adjout_first(struct rde_peer *, struct pt_entry *);
+struct prefix *prefix_adjout_next(struct rde_peer *, struct prefix *);
struct prefix *prefix_adjout_lookup(struct rde_peer *, struct bgpd_addr *,
int);
-struct prefix *prefix_adjout_next(struct rde_peer *, struct prefix *);
+struct prefix *prefix_adjout_match(struct rde_peer *, struct bgpd_addr *);
+struct prefix *prefix_match(struct rde_peer *, struct bgpd_addr *);
int prefix_update(struct rib *, struct rde_peer *, uint32_t,
uint32_t, struct filterstate *, struct bgpd_addr *, int);
int prefix_withdraw(struct rib *, struct rde_peer *, uint32_t,
struct bgpd_addr *, int);
void prefix_add_eor(struct rde_peer *, uint8_t);
void prefix_adjout_update(struct prefix *, struct rde_peer *,
- struct filterstate *, struct bgpd_addr *, int, uint32_t);
+ struct filterstate *, struct pt_entry *, uint32_t);
void prefix_adjout_withdraw(struct prefix *);
void prefix_adjout_destroy(struct prefix *);
void prefix_adjout_dump(struct rde_peer *, void *,
-/* $OpenBSD: rde_rib.c,v 1.256 2023/03/28 15:17:34 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.257 2023/03/29 10:46:11 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
*/
struct prefix *
prefix_adjout_get(struct rde_peer *peer, uint32_t path_id_tx,
- struct bgpd_addr *prefix, int prefixlen)
+ struct pt_entry *pte)
{
struct prefix xp;
memset(&xp, 0, sizeof(xp));
- xp.pt = pt_fill(prefix, prefixlen);
+ xp.pt = pte;
xp.path_id_tx = path_id_tx;
return RB_FIND(prefix_index, &peer->adj_rib_out, &xp);
* Returns NULL if not found.
*/
struct prefix *
-prefix_adjout_lookup(struct rde_peer *peer, struct bgpd_addr *prefix,
- int prefixlen)
+prefix_adjout_first(struct rde_peer *peer, struct pt_entry *pte)
{
struct prefix xp, *np;
memset(&xp, 0, sizeof(xp));
- xp.pt = 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 np;
}
+/*
+ * Lookup addr/prefixlen in the peer prefix_index. Returns first match.
+ * Returns NULL if not found.
+ */
+struct prefix *
+prefix_adjout_lookup(struct rde_peer *peer, struct bgpd_addr *addr, int plen)
+{
+ return prefix_adjout_first(peer, pt_fill(addr, plen));
+}
+
/*
* Lookup addr in the peer prefix_index. Returns first match.
* Returns NULL if not found.
*/
void
prefix_adjout_update(struct prefix *p, struct rde_peer *peer,
- struct filterstate *state, struct bgpd_addr *prefix, int prefixlen,
- uint32_t path_id_tx)
+ struct filterstate *state, struct pt_entry *pte, uint32_t path_id_tx)
{
struct rde_aspath *asp;
struct rde_community *comm;
/* initially mark DEAD so code below is skipped */
p->flags |= PREFIX_FLAG_ADJOUT | PREFIX_FLAG_DEAD;
- p->pt = pt_get(prefix, prefixlen);
- if (p->pt == NULL)
- p->pt = pt_add(prefix, prefixlen);
- pt_ref(p->pt);
+ p->pt = pt_ref(pte);
p->peer = peer;
p->path_id_tx = path_id_tx;
/* if pending update unhook it before it is unlinked */
if (p->flags & PREFIX_FLAG_UPDATE) {
- RB_REMOVE(prefix_tree, &peer->updates[prefix->aid], p);
+ RB_REMOVE(prefix_tree, &peer->updates[pte->aid], p);
peer->stats.pending_update--;
}
peer->stats.prefix_out_cnt--;
}
if (p->flags & PREFIX_FLAG_WITHDRAW) {
- RB_REMOVE(prefix_tree, &peer->withdraws[prefix->aid], p);
+ RB_REMOVE(prefix_tree, &peer->withdraws[pte->aid], p);
peer->stats.pending_withdraw--;
}
if (p->flags & PREFIX_FLAG_MASK)
fatalx("%s: bad flags %x", __func__, p->flags);
p->flags |= PREFIX_FLAG_UPDATE;
- if (RB_INSERT(prefix_tree, &peer->updates[prefix->aid], p) != NULL)
+ if (RB_INSERT(prefix_tree, &peer->updates[pte->aid], p) != NULL)
fatalx("%s: RB tree invariant violated", __func__);
peer->stats.pending_update++;
}
-/* $OpenBSD: rde_update.c,v 1.160 2023/03/28 15:17:34 claudio Exp $ */
+/* $OpenBSD: rde_update.c,v 1.161 2023/03/29 10:46:11 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
* - UP_EXCLUDED if prefix was excluded because of up_test_update()
*/
static enum up_state
-up_process_prefix(struct rde_peer *peer, struct prefix *new, struct prefix *p,
- struct bgpd_addr *addr, uint8_t plen)
+up_process_prefix(struct rde_peer *peer, struct prefix *new, struct prefix *p)
{
struct filterstate state;
+ struct bgpd_addr addr;
int excluded = 0;
/*
excluded = 1;
rde_filterstate_prep(&state, new);
- if (rde_filter(peer->out_rules, peer, prefix_peer(new), addr, plen,
- &state) == ACTION_DENY) {
+ pt_getaddr(new->pt, &addr);
+ if (rde_filter(peer->out_rules, peer, prefix_peer(new), &addr,
+ new->pt->prefixlen, &state) == ACTION_DENY) {
rde_filterstate_clean(&state);
return UP_FILTERED;
}
/* Open Policy Check: acts like an output filter */
- if (up_enforce_open_policy(peer, &state, addr->aid)) {
+ if (up_enforce_open_policy(peer, &state, new->pt->aid)) {
rde_filterstate_clean(&state);
return UP_FILTERED;
}
/* from here on we know this is an update */
if (p == (void *)-1)
- p = prefix_adjout_get(peer, new->path_id_tx, addr, plen);
+ p = prefix_adjout_get(peer, new->path_id_tx, new->pt);
- up_prep_adjout(peer, &state, addr->aid);
- prefix_adjout_update(p, peer, &state, addr, plen, new->path_id_tx);
+ up_prep_adjout(peer, &state, new->pt->aid);
+ prefix_adjout_update(p, peer, &state, new->pt, new->path_id_tx);
rde_filterstate_clean(&state);
/* max prefix checker outbound */
void
up_generate_updates(struct rde_peer *peer, struct rib_entry *re)
{
- struct bgpd_addr addr;
struct prefix *new, *p;
- uint8_t prefixlen;
- pt_getaddr(re->prefix, &addr);
- prefixlen = re->prefix->prefixlen;
-
- p = prefix_adjout_lookup(peer, &addr, prefixlen);
+ p = prefix_adjout_first(peer, re->prefix);
new = prefix_best(re);
while (new != NULL) {
- switch (up_process_prefix(peer, new, p, &addr, prefixlen)) {
+ switch (up_process_prefix(peer, new, p)) {
case UP_OK:
case UP_ERR_LIMIT:
return;
void
up_generate_addpath(struct rde_peer *peer, struct rib_entry *re)
{
- struct bgpd_addr addr;
struct prefix *head, *new, *p;
- uint8_t prefixlen;
int maxpaths = 0, extrapaths = 0, extra;
int checkmode = 1;
- pt_getaddr(re->prefix, &addr);
- prefixlen = re->prefix->prefixlen;
-
- head = prefix_adjout_lookup(peer, &addr, prefixlen);
+ head = prefix_adjout_first(peer, re->prefix);
/* mark all paths as stale */
for (p = head; p != NULL; p = prefix_adjout_next(peer, p))
}
}
- switch (up_process_prefix(peer, new, (void *)-1, &addr,
- prefixlen)) {
+ switch (up_process_prefix(peer, new, (void *)-1)) {
case UP_OK:
maxpaths++;
extrapaths += extra;
up_generate_addpath_all(struct rde_peer *peer, struct rib_entry *re,
struct prefix *new, struct prefix *old)
{
- struct bgpd_addr addr;
struct prefix *p, *head = NULL;
- uint8_t prefixlen;
int all = 0;
- pt_getaddr(re->prefix, &addr);
- prefixlen = re->prefix->prefixlen;
-
/*
* if old and new are NULL then insert all prefixes from best,
* clearing old routes in the process
*/
if (old == NULL && new == NULL) {
/* mark all paths as stale */
- head = prefix_adjout_lookup(peer, &addr, prefixlen);
+ head = prefix_adjout_first(peer, re->prefix);
for (p = head; p != NULL; p = prefix_adjout_next(peer, p))
p->flags |= PREFIX_FLAG_STALE;
if (old != NULL) {
/* withdraw stale paths */
- p = prefix_adjout_get(peer, old->path_id_tx, &addr, prefixlen);
+ p = prefix_adjout_get(peer, old->path_id_tx, old->pt);
if (p != NULL)
prefix_adjout_withdraw(p);
}
/* add new path (or multiple if all is set) */
while (new != NULL) {
- switch (up_process_prefix(peer, new, (void *)-1, &addr,
- prefixlen)) {
+ switch (up_process_prefix(peer, new, (void *)-1)) {
case UP_OK:
case UP_FILTERED:
case UP_EXCLUDED:
}
}
-struct rib_entry *rib_add(struct rib *, struct bgpd_addr *, int);
-void rib_remove(struct rib_entry *);
-int rib_empty(struct rib_entry *);
-
/* send a default route to the specified peer */
void
up_generate_default(struct rde_peer *peer, uint8_t aid)
struct filterstate state;
struct rde_aspath *asp;
struct prefix *p;
+ struct pt_entry *pte;
struct bgpd_addr addr;
if (peer->capa.mp[aid] == 0)
}
up_prep_adjout(peer, &state, addr.aid);
- prefix_adjout_update(p, peer, &state, &addr, 0, 0);
+ /* can't use pt_fill here since prefix_adjout_update keeps a ref */
+ pte = pt_get(&addr, 0);
+ if (pte == NULL)
+ pte = pt_add(&addr, 0);
+ prefix_adjout_update(p, peer, &state, pte, 0);
rde_filterstate_clean(&state);
/* max prefix checker outbound */