-/* $OpenBSD: rde.c,v 1.530 2021/06/25 09:25:48 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.531 2021/07/27 07:50:01 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
struct ibuf *wbuf;
struct attr *a;
struct nexthop *nexthop;
+ struct rib_entry *re;
void *bp;
time_t staletime;
size_t aslen;
rib.origin = asp->origin;
rib.validation_state = p->validation_state;
rib.flags = 0;
- if (p->re != NULL && p->re->active == p)
+ re = prefix_re(p);
+ if (re != NULL && re->active == p)
rib.flags |= F_PREF_ACTIVE;
if (!prefix_peer(p)->conf.ebgp)
rib.flags |= F_PREF_INTERNAL;
rde_dump_filter(struct prefix *p, struct ctl_show_rib_request *req)
{
struct rde_aspath *asp;
+ struct rib_entry *re;
if (!rde_match_peer(prefix_peer(p), &req->neighbor))
return;
asp = prefix_aspath(p);
+ re = prefix_re(p);
if (asp == NULL) /* skip pending withdraw in Adj-RIB-Out */
return;
- if ((req->flags & F_CTL_ACTIVE) && p->re->active != p)
+ if ((req->flags & F_CTL_ACTIVE) && re != NULL && re->active != p)
return;
if ((req->flags & F_CTL_INVALID) &&
(asp->flags & F_ATTR_PARSE_ERR) == 0)
-/* $OpenBSD: rde.h,v 1.240 2021/06/17 16:05:26 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.241 2021/07/27 07:50:02 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
struct filter_head *in_rules_tmp;
u_int rtableid;
u_int rtableid_tmp;
+ enum reconf_action state, fibstate;
+ u_int16_t id;
u_int16_t flags;
u_int16_t flags_tmp;
- u_int16_t id;
- enum reconf_action state, fibstate;
};
#define RIB_ADJ_IN 0
union {
struct {
LIST_ENTRY(prefix) rib, nexthop;
+ struct rib_entry *re;
} list;
struct {
RB_ENTRY(prefix) index, update;
} tree;
} entry;
struct pt_entry *pt;
- struct rib_entry *re;
struct rde_aspath *aspath;
struct rde_community *communities;
struct rde_peer *peer;
#define PREFIX_FLAG_DEAD 0x04 /* locked but removed */
#define PREFIX_FLAG_STALE 0x08 /* stale entry (graceful reload) */
#define PREFIX_FLAG_MASK 0x0f /* mask for the prefix types */
+#define PREFIX_FLAG_ADJOUT 0x10 /* prefix is in the adj-out rib */
#define PREFIX_NEXTHOP_LINKED 0x40 /* prefix is linked onto nexthop list */
#define PREFIX_FLAG_LOCKED 0x80 /* locked by rib walker */
};
return (p->validation_state & ROA_MASK);
}
+static inline struct rib_entry *
+prefix_re(struct prefix *p)
+{
+ if (p->flags & PREFIX_FLAG_ADJOUT)
+ return NULL;
+ return (p->entry.list.re);
+}
+
void nexthop_init(u_int32_t);
void nexthop_shutdown(void);
int nexthop_pending(void);
-/* $OpenBSD: rde_rib.c,v 1.222 2021/06/17 08:16:04 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.223 2021/07/27 07:50:02 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
{
struct prefix *np;
+ if (p->flags & PREFIX_FLAG_ADJOUT)
+ fatalx("%s: prefix with PREFIX_FLAG_ADJOUT hit", __func__);
+
if (peer != prefix_peer(p))
fatalx("prefix_move: cross peer move");
np->aspath = path_ref(asp);
np->communities = communities_ref(comm);
np->peer = peer;
- np->re = p->re;
+ np->entry.list.re = prefix_re(p);
np->pt = p->pt; /* skip refcnt update since ref is moved */
np->validation_state = vstate;
np->nhflags = nhflags;
* no need to update the peer prefix count because we are only moving
* the prefix without changing the peer.
*/
- prefix_evaluate(np->re, np, p);
+ prefix_evaluate(prefix_re(np), np, p);
/* remove possible pftable reference from old path first */
if (p->aspath && p->aspath->pftableid)
p->nexthop = NULL;
p->aspath = NULL;
p->peer = NULL;
- p->re = NULL;
p->pt = NULL;
+ p->entry.list.re = NULL;
prefix_free(p);
return (0);
if (p == NULL) /* Got a dummy withdrawn request. */
return (0);
+ if (p->flags & PREFIX_FLAG_ADJOUT)
+ fatalx("%s: prefix with PREFIX_FLAG_ADJOUT hit", __func__);
asp = prefix_aspath(p);
if (asp && asp->pftableid)
/* only prefixes in the local RIB were pushed into pf */
struct prefix *p;
p = prefix_alloc();
+ p->flags = PREFIX_FLAG_ADJOUT | PREFIX_FLAG_UPDATE;
p->eor = 1;
- p->flags = PREFIX_FLAG_UPDATE;
if (RB_INSERT(prefix_tree, &peer->updates[aid], p) != NULL)
/* no need to add if EoR marker already present */
prefix_free(p);
int created = 0;
if ((p = prefix_lookup(peer, prefix, prefixlen)) != NULL) {
+ if ((p->flags & PREFIX_FLAG_ADJOUT) == 0)
+ fatalx("%s: prefix without PREFIX_FLAG_ADJOUT hit",
+ __func__);
/* prefix is already in the Adj-RIB-Out */
if (p->flags & PREFIX_FLAG_WITHDRAW) {
created = 1; /* consider this a new entry */
/* peer and pt remain */
} else {
p = prefix_alloc();
+ p->flags |= PREFIX_FLAG_ADJOUT;
created = 1;
p->pt = pt_get(prefix, prefixlen);
if (p == NULL) /* Got a dummy withdrawn request. */
return (0);
+ if ((p->flags & PREFIX_FLAG_ADJOUT) == 0)
+ fatalx("%s: prefix without PREFIX_FLAG_ADJOUT hit", __func__);
+
/* already a withdraw, shortcut */
if (p->flags & PREFIX_FLAG_WITHDRAW) {
p->lastchange = getmonotime();
{
struct rde_peer *peer = prefix_peer(p);
+ if ((p->flags & PREFIX_FLAG_ADJOUT) == 0)
+ fatalx("%s: prefix without PREFIX_FLAG_ADJOUT hit", __func__);
+
if (p->eor) {
/* EOR marker is not linked in the index */
prefix_free(p);
prefix_evaluate_all(struct prefix *p, enum nexthop_state state,
enum nexthop_state oldstate)
{
+ struct rib_entry *re = prefix_re(p);
+
/* Skip non local-RIBs or RIBs that are flagged as noeval. */
- if (re_rib(p->re)->flags & F_RIB_NOEVALUATE) {
+ if (re_rib(re)->flags & F_RIB_NOEVALUATE) {
log_warnx("%s: prefix with F_RIB_NOEVALUATE hit", __func__);
return;
}
* the routing decision so shortcut here.
*/
if (state == NEXTHOP_REACH) {
- if ((re_rib(p->re)->flags & F_RIB_NOFIB) == 0 &&
- p == p->re->active)
- rde_send_kroute(re_rib(p->re), p, NULL);
+ if ((re_rib(re)->flags & F_RIB_NOFIB) == 0 &&
+ p == re->active)
+ rde_send_kroute(re_rib(re), p, NULL);
}
return;
}
/* redo the route decision */
- prefix_evaluate(p->re, p, p);
+ prefix_evaluate(prefix_re(p), p, p);
}
/* kill a prefix. */
prefix_destroy(struct prefix *p)
{
/* make route decision */
- prefix_evaluate(p->re, NULL, p);
+ prefix_evaluate(prefix_re(p), NULL, p);
prefix_unlink(p);
prefix_free(p);
struct rde_aspath *asp, struct rde_community *comm,
struct nexthop *nexthop, u_int8_t nhflags, u_int8_t vstate)
{
+ if (p->flags & PREFIX_FLAG_ADJOUT)
+ fatalx("%s: prefix with PREFIX_FLAG_ADJOUT hit", __func__);
+
+ p->entry.list.re = re;
p->aspath = path_ref(asp);
p->communities = communities_ref(comm);
p->peer = peer;
p->pt = pt_ref(re->prefix);
- p->re = re;
p->validation_state = vstate;
p->nhflags = nhflags;
p->nexthop = nexthop_ref(nexthop);
static void
prefix_unlink(struct prefix *p)
{
- struct rib_entry *re = p->re;
+ struct rib_entry *re = prefix_re(p);
/* destroy all references to other objects */
nexthop_unlink(p);
p->nexthop = NULL;
p->aspath = NULL;
p->peer = NULL;
- p->re = NULL;
p->pt = NULL;
if (re && rib_empty(re))
return;
/* no need to link prefixes in RIBs that have no decision process */
- if (re_rib(p->re)->flags & F_RIB_NOEVALUATE)
+ if (re_rib(prefix_re(p))->flags & F_RIB_NOEVALUATE)
return;
p->flags |= PREFIX_NEXTHOP_LINKED;