-/* $OpenBSD: mrt.c,v 1.83 2017/05/27 10:55:45 phessler Exp $ */
+/* $OpenBSD: mrt.c,v 1.84 2018/02/05 03:55:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
struct rde_peer *peer)
{
struct ibuf *buf, *hbuf = NULL, *h2buf = NULL;
+ struct nexthop *n;
struct bgpd_addr addr, nexthop, *nh;
u_int16_t len;
u_int8_t aid;
return (-1);
}
- if (mrt_attr_dump(buf, p->aspath, NULL, 0) == -1) {
+ if (mrt_attr_dump(buf, prefix_aspath(p), NULL, 0) == -1) {
log_warnx("mrt_dump_entry_mp: mrt_attr_dump error");
goto fail;
}
DUMP_SHORT(h2buf, /* ifindex */ 0);
/* XXX is this for peer self? */
- aid = peer->remote_addr.aid == AID_UNSPEC ? p->prefix->aid :
+ aid = peer->remote_addr.aid == AID_UNSPEC ? p->re->prefix->aid :
peer->remote_addr.aid;
switch (aid) {
case AID_INET:
DUMP_SHORT(h2buf, 1); /* status */
DUMP_LONG(h2buf, p->lastchange); /* originated */
- pt_getaddr(p->prefix, &addr);
+ pt_getaddr(p->re->prefix, &addr);
- if (p->aspath->nexthop == NULL) {
+ n = prefix_aspath(p)->nexthop;
+ if (n == NULL) {
bzero(&nexthop, sizeof(struct bgpd_addr));
nexthop.aid = addr.aid;
nh = &nexthop;
} else
- nh = &p->aspath->nexthop->exit_nexthop;
+ nh = &n->exit_nexthop;
switch (addr.aid) {
case AID_INET:
goto fail;
}
- if (prefix_writebuf(h2buf, &addr, p->prefix->prefixlen) == -1) {
+ if (prefix_writebuf(h2buf, &addr, p->re->prefix->prefixlen) == -1) {
log_warn("mrt_dump_entry_mp: prefix_writebuf error");
goto fail;
}
struct rde_peer *peer)
{
struct ibuf *buf, *hbuf;
+ struct nexthop *nexthop;
struct bgpd_addr addr, *nh;
size_t len;
u_int16_t subtype;
u_int8_t dummy;
- if (p->prefix->aid != peer->remote_addr.aid &&
- p->prefix->aid != AID_INET && p->prefix->aid != AID_INET6)
+ if (p->re->prefix->aid != peer->remote_addr.aid &&
+ p->re->prefix->aid != AID_INET && p->re->prefix->aid != AID_INET6)
/* only able to dump pure IPv4/IPv6 */
return (0);
return (-1);
}
- if (p->aspath->nexthop == NULL) {
+ nexthop = prefix_aspath(p)->nexthop;
+ if (nexthop == NULL) {
bzero(&addr, sizeof(struct bgpd_addr));
- addr.aid = p->prefix->aid;
+ addr.aid = p->re->prefix->aid;
nh = &addr;
} else
- nh = &p->aspath->nexthop->exit_nexthop;
- if (mrt_attr_dump(buf, p->aspath, nh, 0) == -1) {
+ nh = &nexthop->exit_nexthop;
+ if (mrt_attr_dump(buf, prefix_aspath(p), nh, 0) == -1) {
log_warnx("mrt_dump_entry: mrt_attr_dump error");
ibuf_free(buf);
return (-1);
}
len = ibuf_size(buf);
- aid2afi(p->prefix->aid, &subtype, &dummy);
+ aid2afi(p->re->prefix->aid, &subtype, &dummy);
if (mrt_dump_hdr_rde(&hbuf, MSG_TABLE_DUMP, subtype, len) == -1) {
ibuf_free(buf);
return (-1);
DUMP_SHORT(hbuf, 0);
DUMP_SHORT(hbuf, snum);
- pt_getaddr(p->prefix, &addr);
- switch (p->prefix->aid) {
+ pt_getaddr(p->re->prefix, &addr);
+ switch (p->re->prefix->aid) {
case AID_INET:
DUMP_NLONG(hbuf, addr.v4.s_addr);
break;
}
break;
}
- DUMP_BYTE(hbuf, p->prefix->prefixlen);
+ DUMP_BYTE(hbuf, p->re->prefix->prefixlen);
DUMP_BYTE(hbuf, 1); /* state */
DUMP_LONG(hbuf, p->lastchange); /* originated */
- switch (p->prefix->aid) {
+ switch (p->re->prefix->aid) {
case AID_INET:
DUMP_NLONG(hbuf, peer->remote_addr.v4.s_addr);
break;
}
nump = 0;
LIST_FOREACH(p, &re->prefix_h, rib_l) {
+ struct nexthop *nexthop;
struct bgpd_addr *nh;
struct ibuf *tbuf;
- if (p->aspath->nexthop == NULL) {
+ nexthop = prefix_aspath(p)->nexthop;
+ if (nexthop == NULL) {
bzero(&addr, sizeof(struct bgpd_addr));
- addr.aid = p->prefix->aid;
+ addr.aid = re->prefix->aid;
nh = &addr;
} else
- nh = &p->aspath->nexthop->exit_nexthop;
+ nh = &nexthop->exit_nexthop;
- DUMP_SHORT(buf, p->aspath->peer->mrt_idx);
+ DUMP_SHORT(buf, prefix_peer(p)->mrt_idx);
DUMP_LONG(buf, p->lastchange); /* originated */
if ((tbuf = ibuf_dynamic(0, MAX_PKTSIZE)) == NULL) {
log_warn("%s: ibuf_dynamic", __func__);
return (-1);
}
- if (mrt_attr_dump(tbuf, p->aspath, nh, 1) == -1) {
+ if (mrt_attr_dump(tbuf, prefix_aspath(p), nh, 1) == -1) {
log_warnx("%s: mrt_attr_dump error", __func__);
ibuf_free(buf);
return (-1);
LIST_FOREACH(p, &re->prefix_h, rib_l) {
if (mrtbuf->type == MRT_TABLE_DUMP)
mrt_dump_entry(mrtbuf, p, mrtbuf->seqnum++,
- p->aspath->peer);
+ prefix_peer(p));
else
mrt_dump_entry_mp(mrtbuf, p, mrtbuf->seqnum++,
- p->aspath->peer);
+ prefix_peer(p));
}
}
-/* $OpenBSD: rde.c,v 1.374 2018/02/04 05:08:16 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.375 2018/02/05 03:55:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
/* announced network may have a NULL nexthop */
bzero(&rib.true_nexthop, sizeof(rib.true_nexthop));
bzero(&rib.exit_nexthop, sizeof(rib.exit_nexthop));
- rib.true_nexthop.aid = p->prefix->aid;
- rib.exit_nexthop.aid = p->prefix->aid;
+ rib.true_nexthop.aid = p->re->prefix->aid;
+ rib.exit_nexthop.aid = p->re->prefix->aid;
}
- pt_getaddr(p->prefix, &rib.prefix);
- rib.prefixlen = p->prefix->prefixlen;
+ pt_getaddr(p->re->prefix, &rib.prefix);
+ rib.prefixlen = p->re->prefix->prefixlen;
rib.origin = asp->origin;
rib.flags = 0;
if (p->re->active == p)
rib.flags |= F_PREF_ELIGIBLE;
if (asp->flags & F_ATTR_LOOP)
rib.flags &= ~F_PREF_ELIGIBLE;
- staletime = asp->peer->staletime[p->prefix->aid];
+ staletime = asp->peer->staletime[p->re->prefix->aid];
if (staletime && p->lastchange <= staletime)
rib.flags |= F_PREF_STALE;
rib.aspath_len = aspath_length(asp->aspath);
struct ctl_show_rib_request *req)
{
struct bgpd_addr addr;
- struct rde_aspath *asp;
+ struct rde_aspath *asp, *fasp;
enum filter_actions a;
if (up_test_update(peer, p) != 1)
return;
- pt_getaddr(p->prefix, &addr);
- a = rde_filter(out_rules, &asp, peer, p->aspath, &addr,
- p->prefix->prefixlen, p->aspath->peer);
- if (asp)
- asp->peer = p->aspath->peer;
+ pt_getaddr(p->re->prefix, &addr);
+ asp = prefix_aspath(p);
+ a = rde_filter(out_rules, &fasp, peer, asp, &addr,
+ p->re->prefix->prefixlen, asp->peer);
+ if (fasp)
+ fasp->peer = asp->peer;
else
- asp = p->aspath;
+ fasp = asp;
if (a == ACTION_ALLOW)
- rde_dump_rib_as(p, asp, req->pid, req->flags);
+ rde_dump_rib_as(p, fasp, req->pid, req->flags);
- if (asp != p->aspath)
- path_put(asp);
+ if (fasp != asp)
+ path_put(fasp);
}
void
rde_dump_filter(struct prefix *p, struct ctl_show_rib_request *req)
{
struct rde_peer *peer;
+ struct rde_aspath *asp;
if (req->flags & F_CTL_ADJ_IN ||
!(req->flags & (F_CTL_ADJ_IN|F_CTL_ADJ_OUT))) {
- if (req->peerid && req->peerid != p->aspath->peer->conf.id)
+ asp = prefix_aspath(p);
+ if (req->peerid && req->peerid != asp->peer->conf.id)
return;
if (req->type == IMSG_CTL_SHOW_RIB_AS &&
- !aspath_match(p->aspath->aspath->data,
- p->aspath->aspath->len, &req->as, req->as.as))
+ !aspath_match(asp->aspath->data, asp->aspath->len,
+ &req->as, req->as.as))
return;
if (req->type == IMSG_CTL_SHOW_RIB_COMMUNITY &&
- !community_match(p->aspath, req->community.as,
+ !community_match(asp, req->community.as,
req->community.type))
return;
if (req->type == IMSG_CTL_SHOW_RIB_EXTCOMMUNITY &&
- !community_ext_match(p->aspath, &req->extcommunity, 0))
+ !community_ext_match(asp, &req->extcommunity, 0))
return;
if (req->type == IMSG_CTL_SHOW_RIB_LARGECOMMUNITY &&
- !community_large_match(p->aspath, req->large_community.as,
+ !community_large_match(asp, req->large_community.as,
req->large_community.ld1, req->large_community.ld2))
return;
if ((req->flags & F_CTL_ACTIVE) && p->re->active != p)
return;
- rde_dump_rib_as(p, p->aspath, req->pid, req->flags);
+ rde_dump_rib_as(p, asp, req->pid, req->flags);
} else if (req->flags & F_CTL_ADJ_OUT) {
if (p->re->active != p)
/* only consider active prefix */
struct kroute_full kr;
struct bgpd_addr addr;
struct prefix *p;
+ struct rde_aspath *asp;
struct rdomain *rd;
enum imsg_type type;
* Make sure that self announce prefixes are not committed to the
* FIB. If both prefixes are unreachable no update is needed.
*/
- if ((old == NULL || old->aspath->flags & F_PREFIX_ANNOUNCED) &&
- (new == NULL || new->aspath->flags & F_PREFIX_ANNOUNCED))
+ if ((old == NULL || prefix_aspath(old)->flags & F_PREFIX_ANNOUNCED) &&
+ (new == NULL || prefix_aspath(new)->flags & F_PREFIX_ANNOUNCED))
return;
- if (new == NULL || new->aspath->flags & F_PREFIX_ANNOUNCED) {
+ if (new == NULL || prefix_aspath(new)->flags & F_PREFIX_ANNOUNCED) {
type = IMSG_KROUTE_DELETE;
p = old;
} else {
p = new;
}
- pt_getaddr(p->prefix, &addr);
+ asp = prefix_aspath(p);
+ pt_getaddr(p->re->prefix, &addr);
bzero(&kr, sizeof(kr));
memcpy(&kr.prefix, &addr, sizeof(kr.prefix));
- kr.prefixlen = p->prefix->prefixlen;
- if (p->aspath->flags & F_NEXTHOP_REJECT)
+ kr.prefixlen = p->re->prefix->prefixlen;
+ if (asp->flags & F_NEXTHOP_REJECT)
kr.flags |= F_REJECT;
- if (p->aspath->flags & F_NEXTHOP_BLACKHOLE)
+ if (asp->flags & F_NEXTHOP_BLACKHOLE)
kr.flags |= F_BLACKHOLE;
if (type == IMSG_KROUTE_CHANGE)
- memcpy(&kr.nexthop, &p->aspath->nexthop->true_nexthop,
+ memcpy(&kr.nexthop, &asp->nexthop->true_nexthop,
sizeof(kr.nexthop));
- strlcpy(kr.label, rtlabel_id2name(p->aspath->rtlabelid),
- sizeof(kr.label));
+ strlcpy(kr.label, rtlabel_id2name(asp->rtlabelid), sizeof(kr.label));
switch (addr.aid) {
case AID_VPN_IPv4:
break;
SIMPLEQ_FOREACH(rd, rdomains_l, entry) {
- if (!rde_rdomain_import(p->aspath, rd))
+ if (!rde_rdomain_import(asp, rd))
continue;
/* must send exit_nexthop so that correct MPLS tunnel
* is chosen
*/
if (type == IMSG_KROUTE_CHANGE)
- memcpy(&kr.nexthop,
- &p->aspath->nexthop->exit_nexthop,
+ memcpy(&kr.nexthop, &asp->nexthop->exit_nexthop,
sizeof(kr.nexthop));
if (imsg_compose(ibuf_main, type, rd->rtableid, 0, -1,
&kr, sizeof(kr)) == -1)
* so cache the values.
*/
np = LIST_NEXT(p, rib_l);
- asp = p->aspath;
+ asp = prefix_aspath(p);
peer = asp->peer;
/* check if prefix changed */
if (up_test_update(peer, p) != 1)
return;
- oa = rde_filter(out_rules_tmp, &oasp, peer, p->aspath,
- &addr, pt->prefixlen, p->aspath->peer);
- na = rde_filter(out_rules, &nasp, peer, p->aspath,
- &addr, pt->prefixlen, p->aspath->peer);
- oasp = oasp != NULL ? oasp : p->aspath;
- nasp = nasp != NULL ? nasp : p->aspath;
+ oa = rde_filter(out_rules_tmp, &oasp, peer, prefix_aspath(p),
+ &addr, pt->prefixlen, prefix_peer(p));
+ na = rde_filter(out_rules, &nasp, peer, prefix_aspath(p),
+ &addr, pt->prefixlen, prefix_peer(p));
+ oasp = oasp != NULL ? oasp : prefix_aspath(p);
+ nasp = nasp != NULL ? nasp : prefix_aspath(p);
/* go through all 4 possible combinations */
/* if (oa == ACTION_DENY && na == ACTION_DENY) */
up_generate(peer, nasp, &addr, pt->prefixlen);
}
- if (oasp != p->aspath)
+ if (oasp != prefix_aspath(p))
path_put(oasp);
- if (nasp != p->aspath)
+ if (nasp != prefix_aspath(p))
path_put(nasp);
}
if (up_test_update(peer, p) != 1)
return;
- oa = rde_filter(out_rules_tmp, &oasp, peer, p->aspath,
- &addr, pt->prefixlen, p->aspath->peer);
- oasp = oasp != NULL ? oasp : p->aspath;
+ oa = rde_filter(out_rules_tmp, &oasp, peer, prefix_aspath(p),
+ &addr, pt->prefixlen, prefix_peer(p));
+ oasp = oasp != NULL ? oasp : prefix_aspath(p);
if (oa == ACTION_DENY)
/* nothing todo */
/* send withdraw */
up_generate(peer, NULL, &addr, pt->prefixlen);
done:
- if (oasp != p->aspath)
+ if (oasp != prefix_aspath(p))
path_put(oasp);
}
network_dump_upcall(struct rib_entry *re, void *ptr)
{
struct prefix *p;
+ struct rde_aspath *asp;
struct kroute_full k;
struct bgpd_addr addr;
struct rde_dump_ctx *ctx = ptr;
LIST_FOREACH(p, &re->prefix_h, rib_l) {
- if (!(p->aspath->flags & F_PREFIX_ANNOUNCED))
+ asp = prefix_aspath(p);
+ if (!(asp->flags & F_PREFIX_ANNOUNCED))
continue;
- pt_getaddr(p->prefix, &addr);
+ pt_getaddr(p->re->prefix, &addr);
bzero(&k, sizeof(k));
memcpy(&k.prefix, &addr, sizeof(k.prefix));
- if (p->aspath->nexthop == NULL ||
- p->aspath->nexthop->state != NEXTHOP_REACH)
+ if (asp->nexthop == NULL ||
+ asp->nexthop->state != NEXTHOP_REACH)
k.nexthop.aid = k.prefix.aid;
else
- memcpy(&k.nexthop, &p->aspath->nexthop->true_nexthop,
+ memcpy(&k.nexthop, &asp->nexthop->true_nexthop,
sizeof(k.nexthop));
- k.prefixlen = p->prefix->prefixlen;
+ k.prefixlen = p->re->prefix->prefixlen;
k.flags = F_KERNEL;
- if ((p->aspath->flags & F_ANN_DYNAMIC) == 0)
+ if ((asp->flags & F_ANN_DYNAMIC) == 0)
k.flags = F_STATIC;
if (imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_NETWORK, 0,
ctx->req.pid, -1, &k, sizeof(k)) == -1)
-/* $OpenBSD: rde.h,v 1.163 2018/02/04 05:08:16 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.164 2018/02/05 03:55:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
#include <stdint.h>
#include "bgpd.h"
+#include "log.h"
/* rde internal structures */
struct prefix {
LIST_ENTRY(prefix) rib_l, path_l;
- struct rde_aspath *aspath;
- struct pt_entry *prefix;
struct rib_entry *re;
+ union {
+ struct rde_aspath *_aspath;
+ } _p;
time_t lastchange;
};
void rde_filter_calc_skip_steps(struct filter_head *);
/* rde_prefix.c */
-#define pt_empty(pt) ((pt)->refcnt == 0)
-#define pt_ref(pt) do { \
- ++(pt)->refcnt; \
- if ((pt)->refcnt == 0) \
- fatalx("pt_ref: overflow"); \
-} while(0)
-#define pt_unref(pt) do { \
- if ((pt)->refcnt == 0) \
- fatalx("pt_unref: underflow"); \
- --(pt)->refcnt; \
-} while(0)
+static inline int
+pt_empty(struct pt_entry *pt)
+{
+ return (pt->refcnt == 0);
+}
+
+static inline void
+pt_ref(struct pt_entry *pt)
+{
+ ++pt->refcnt;
+ if (pt->refcnt == 0)
+ fatalx("pt_ref: overflow");
+}
+
+static inline void
+pt_unref(struct pt_entry *pt)
+{
+ if (pt->refcnt == 0)
+ fatalx("pt_unref: underflow");
+ --pt->refcnt;
+}
void pt_init(void);
void pt_shutdown(void);
enum nexthop_state);
void prefix_destroy(struct prefix *);
void prefix_network_clean(struct rde_peer *, time_t, u_int32_t);
+void prefix_relink(struct prefix *, struct rde_aspath *, int);
+
+static inline struct rde_aspath *
+prefix_aspath(struct prefix *p)
+{
+ return (p->_p._aspath);
+}
+
+static inline struct rde_peer *
+prefix_peer(struct prefix *p)
+{
+ return (p->_p._aspath->peer);
+}
void nexthop_init(u_int32_t);
void nexthop_shutdown(void);
-/* $OpenBSD: rde_decide.c,v 1.66 2017/01/25 00:15:38 claudio Exp $ */
+/* $OpenBSD: rde_decide.c,v 1.67 2018/02/05 03:55:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
prefix_cmp(struct prefix *p1, struct prefix *p2)
{
struct rde_aspath *asp1, *asp2;
+ struct rde_peer *peer1, *peer2;
struct attr *a;
u_int32_t p1id, p2id;
int p1cnt, p2cnt;
if (p2 == NULL)
return (1);
- asp1 = p1->aspath;
- asp2 = p2->aspath;
+ asp1 = prefix_aspath(p1);
+ asp2 = prefix_aspath(p2);
/* pathes with errors are not eligible */
if (asp1->flags & F_ATTR_PARSE_ERR)
return (p2cnt - p1cnt);
/* 12. lowest peer address wins (IPv4 is better than IPv6) */
- if (memcmp(&p1->aspath->peer->remote_addr,
- &p2->aspath->peer->remote_addr,
- sizeof(p1->aspath->peer->remote_addr)) != 0)
- return (-memcmp(&p1->aspath->peer->remote_addr,
- &p2->aspath->peer->remote_addr,
- sizeof(p1->aspath->peer->remote_addr)));
+ peer1 = prefix_peer(p1);
+ peer2 = prefix_peer(p2);
+ if (memcmp(&peer1->remote_addr, &peer2->remote_addr,
+ sizeof(peer1->remote_addr)) != 0)
+ return (-memcmp(&peer1->remote_addr, &peer2->remote_addr,
+ sizeof(peer1->remote_addr)));
/* 13. for announced prefixes prefer dynamic routes */
if ((asp1->flags & F_ANN_DYNAMIC) != (asp2->flags & F_ANN_DYNAMIC)) {
if (p != NULL)
LIST_INSERT_HEAD(&re->prefix_h, p, rib_l);
if (re->active != NULL) {
- re->active->aspath->active_cnt--;
+ prefix_aspath(re->active)->active_cnt--;
re->active = NULL;
}
return;
}
xp = LIST_FIRST(&re->prefix_h);
- if (xp == NULL || xp->aspath->flags & (F_ATTR_LOOP|F_ATTR_PARSE_ERR) ||
- (xp->aspath->nexthop != NULL &&
- xp->aspath->nexthop->state != NEXTHOP_REACH))
- /* xp is ineligible */
- xp = NULL;
+ if (xp != NULL) {
+ struct rde_aspath *xasp = prefix_aspath(xp);
+ if (xasp->flags & (F_ATTR_LOOP|F_ATTR_PARSE_ERR) ||
+ (xasp->nexthop != NULL &&
+ xasp->nexthop->state != NEXTHOP_REACH))
+ /* xp is ineligible */
+ xp = NULL;
+ }
if (re->active != xp) {
/* need to generate an update */
if (re->active != NULL)
- re->active->aspath->active_cnt--;
+ prefix_aspath(re->active)->active_cnt--;
/*
* Send update with remove for re->active and add for xp
re->active = xp;
if (xp != NULL)
- xp->aspath->active_cnt++;
+ prefix_aspath(xp)->active_cnt++;
}
}
-/* $OpenBSD: rde_rib.c,v 1.155 2018/02/04 05:08:16 claudio Exp $ */
+/* $OpenBSD: rde_rib.c,v 1.156 2018/02/05 03:55:54 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
* use the default for loop.
*/
while ((p = LIST_FIRST(&re->prefix_h))) {
+ struct rde_aspath *asp = prefix_aspath(p);
np = LIST_NEXT(p, rib_l);
- if (p->aspath->pftableid) {
+ if (asp->pftableid) {
struct bgpd_addr addr;
- pt_getaddr(p->prefix, &addr);
+ pt_getaddr(p->re->prefix, &addr);
/* Commit is done in peer_down() */
- rde_send_pftable(p->aspath->pftableid, &addr,
- p->prefix->prefixlen, 1);
+ rde_send_pftable(asp->pftableid, &addr,
+ p->re->prefix->prefixlen, 1);
}
prefix_destroy(p);
if (np == NULL)
SIPHASH_KEY pathtablekey;
/* XXX the hash should also include communities and the other attrs */
-#define PATH_HASH(x) \
- &pathtable.path_hashtbl[SipHash24(&pathtablekey, (x)->data, (x)->len) & \
+#define PATH_HASH(x) \
+ &pathtable.path_hashtbl[x == NULL ? 0 : \
+ SipHash24(&pathtablekey, (x)->data, (x)->len) & \
pathtable.path_hashmask]
void
* First try to find a prefix in the specified RIB.
*/
if ((p = prefix_get(rib, peer, prefix, prefixlen, 0)) != NULL) {
- if (path_compare(nasp, p->aspath) == 0) {
+ if (path_compare(nasp, prefix_aspath(p)) == 0) {
/* no change, update last change */
p->lastchange = time(NULL);
return (0);
if (asp->pftableid) {
struct bgpd_addr addr;
- pt_getaddr(p->prefix, &addr);
+ pt_getaddr(p->re->prefix, &addr);
/* Commit is done in peer_down() */
- rde_send_pftable(p->aspath->pftableid, &addr,
- p->prefix->prefixlen, 1);
+ rde_send_pftable(prefix_aspath(p)->pftableid, &addr,
+ p->re->prefix->prefixlen, 1);
}
prefix_destroy(p);
}
staletime = asp->peer->staletime[aid];
for (p = LIST_FIRST(&asp->prefix_h); p != NULL; p = np) {
np = LIST_NEXT(p, path_l);
- if (p->prefix->aid != aid)
+ if (p->re->prefix->aid != aid)
continue;
if (staletime && p->lastchange > staletime)
if (asp->pftableid) {
struct bgpd_addr addr;
- pt_getaddr(p->prefix, &addr);
+ pt_getaddr(p->re->prefix, &addr);
/* Commit is done in peer_flush() */
- rde_send_pftable(p->aspath->pftableid, &addr,
- p->prefix->prefixlen, 1);
+ rde_send_pftable(prefix_aspath(p)->pftableid, &addr,
+ p->re->prefix->prefixlen, 1);
}
/* only count Adj-RIB-In */
prefix_link(p, re, asp);
return (1);
} else {
- if (p->aspath != asp) {
+ if (prefix_aspath(p) != asp) {
/* prefix belongs to a different aspath so move */
prefix_move(asp, p);
} else
struct prefix *np;
struct rde_aspath *oasp;
- if (asp->peer != p->aspath->peer)
+ if (asp->peer != prefix_peer(p))
fatalx("prefix_move: cross peer move");
/* create new prefix node */
np = prefix_alloc();
- np->aspath = asp;
+ np->_p._aspath = asp;
/* peer and prefix pointers are still equal */
- np->prefix = p->prefix;
np->re = p->re;
np->lastchange = time(NULL);
prefix_evaluate(np, np->re);
/* remove old prefix node */
- oasp = p->aspath;
+ oasp = prefix_aspath(p);
LIST_REMOVE(p, path_l);
PREFIX_COUNT(oasp, -1);
/* as before peer count needs no update because of move */
/* destroy all references to other objects and free the old prefix */
- p->aspath = NULL;
- p->prefix = NULL;
+ p->_p._aspath = NULL;
p->re = NULL;
prefix_free(p);
struct rde_aspath *asp;
re = rib_get(rib, prefix, prefixlen);
- if (re == NULL) /* Got a dummy withdrawn request */
+ if (re == NULL) /* Got a dummy withdrawn request */
return (0);
p = prefix_bypeer(re, peer, flags);
if (p == NULL) /* Got a dummy withdrawn request. */
return (0);
- asp = p->aspath;
-
+ asp = prefix_aspath(p);
if (asp->pftableid) {
/* only prefixes in the local RIB were pushed into pf */
rde_send_pftable(asp->pftableid, prefix, prefixlen, 1);
struct prefix *p;
LIST_FOREACH(p, &re->prefix_h, rib_l) {
- if (p->aspath->peer != peer)
+ if (prefix_peer(p) != peer)
continue;
- if (p->aspath->flags & flags &&
+ if (prefix_aspath(p)->flags & flags &&
(flags & F_ANN_DYNAMIC) !=
- (p->aspath->flags & F_ANN_DYNAMIC))
+ (prefix_aspath(p)->flags & F_ANN_DYNAMIC))
continue;
return (p);
}
{
struct rde_aspath *asp;
- asp = p->aspath;
+ asp = prefix_aspath(p);
prefix_unlink(p);
prefix_free(p);
LIST_INSERT_HEAD(&asp->prefix_h, pref, path_l);
PREFIX_COUNT(asp, 1);
- pref->aspath = asp;
+ pref->_p._aspath = asp;
pref->re = re;
- pref->prefix = re->prefix;
- pt_ref(pref->prefix);
pref->lastchange = time(NULL);
/* make route decision */
prefix_evaluate(NULL, re);
LIST_REMOVE(pref, path_l);
- PREFIX_COUNT(pref->aspath, -1);
+ PREFIX_COUNT(prefix_aspath(pref), -1);
- pt_unref(pref->prefix);
- if (pt_empty(pref->prefix))
- pt_remove(pref->prefix);
if (rib_empty(re))
rib_remove(re);
/* destroy all references to other objects */
- pref->aspath = NULL;
- pref->prefix = NULL;
+ pref->_p._aspath = NULL;
pref->re = NULL;
/*
-/* $OpenBSD: rde_update.c,v 1.87 2018/02/04 05:08:16 claudio Exp $ */
+/* $OpenBSD: rde_update.c,v 1.88 2018/02/05 03:55:54 claudio Exp $ */
/*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
up_test_update(struct rde_peer *peer, struct prefix *p)
{
struct bgpd_addr addr;
+ struct rde_aspath *asp;
+ struct rde_peer *prefp;
struct attr *attr;
if (peer->state != PEER_UP)
/* no prefix available */
return (0);
- if (peer == p->aspath->peer)
+ prefp = prefix_peer(p);
+ asp = prefix_aspath(p);
+
+ if (peer == prefp)
/* Do not send routes back to sender */
return (0);
- if (p->aspath->flags & F_ATTR_PARSE_ERR)
+ if (asp->flags & F_ATTR_PARSE_ERR)
fatalx("try to send out a botched path");
- if (p->aspath->flags & F_ATTR_LOOP)
+ if (asp->flags & F_ATTR_LOOP)
fatalx("try to send out a looped path");
- pt_getaddr(p->prefix, &addr);
+ pt_getaddr(p->re->prefix, &addr);
if (peer->capa.mp[addr.aid] == 0)
return (-1);
- if (!p->aspath->peer->conf.ebgp && !peer->conf.ebgp) {
+ if (!prefp->conf.ebgp && !peer->conf.ebgp) {
/*
* route reflector redistribution rules:
* 1. if announce is set -> announce
* 4. old non-client, new client -> yes
* 5. old client, new client -> yes
*/
- if (p->aspath->peer->conf.reflector_client == 0 &&
+ if (prefp->conf.reflector_client == 0 &&
peer->conf.reflector_client == 0 &&
- (p->aspath->flags & F_PREFIX_ANNOUNCED) == 0)
+ (asp->flags & F_PREFIX_ANNOUNCED) == 0)
/* Do not redistribute updates to ibgp peers */
return (0);
}
* pass only prefix that have an aspath count
* of zero this is equal to the ^$ regex.
*/
- if (p->aspath->aspath->ascnt != 0)
+ if (asp->aspath->ascnt != 0)
return (0);
break;
}
/* well known communities */
- if (community_match(p->aspath,
- COMMUNITY_WELLKNOWN, COMMUNITY_NO_ADVERTISE))
+ if (community_match(asp, COMMUNITY_WELLKNOWN, COMMUNITY_NO_ADVERTISE))
return (0);
- if (peer->conf.ebgp && community_match(p->aspath,
- COMMUNITY_WELLKNOWN, COMMUNITY_NO_EXPORT))
+ if (peer->conf.ebgp && community_match(asp, COMMUNITY_WELLKNOWN,
+ COMMUNITY_NO_EXPORT))
return (0);
- if (peer->conf.ebgp && community_match(p->aspath,
- COMMUNITY_WELLKNOWN, COMMUNITY_NO_EXPSUBCONFED))
+ if (peer->conf.ebgp && community_match(asp, COMMUNITY_WELLKNOWN,
+ COMMUNITY_NO_EXPSUBCONFED))
return (0);
/*
* Don't send messages back to originator
* this is not specified in the RFC but seems logical.
*/
- if ((attr = attr_optget(p->aspath, ATTR_ORIGINATOR_ID)) != NULL) {
+ if ((attr = attr_optget(asp, ATTR_ORIGINATOR_ID)) != NULL) {
if (memcmp(attr->data, &peer->remote_bgpid,
sizeof(peer->remote_bgpid)) == 0) {
/* would cause loop don't send */
up_generate_updates(struct filter_head *rules, struct rde_peer *peer,
struct prefix *new, struct prefix *old)
{
- struct rde_aspath *asp;
+ struct rde_aspath *asp, *fasp;
struct bgpd_addr addr;
if (peer->state != PEER_UP)
if (up_test_update(peer, old) != 1)
return;
- pt_getaddr(old->prefix, &addr);
- if (rde_filter(rules, NULL, peer, old->aspath, &addr,
- old->prefix->prefixlen, old->aspath->peer) == ACTION_DENY)
+ asp = prefix_aspath(old);
+ pt_getaddr(old->re->prefix, &addr);
+ if (rde_filter(rules, NULL, peer, asp, &addr,
+ old->re->prefix->prefixlen, asp->peer) == ACTION_DENY)
return;
/* withdraw prefix */
- up_generate(peer, NULL, &addr, old->prefix->prefixlen);
+ up_generate(peer, NULL, &addr, old->re->prefix->prefixlen);
} else {
switch (up_test_update(peer, new)) {
case 1:
return;
}
- pt_getaddr(new->prefix, &addr);
- if (rde_filter(rules, &asp, peer, new->aspath, &addr,
- new->prefix->prefixlen, new->aspath->peer) == ACTION_DENY) {
- path_put(asp);
+ asp = prefix_aspath(new);
+ pt_getaddr(new->re->prefix, &addr);
+ if (rde_filter(rules, &fasp, peer, asp, &addr,
+ new->re->prefix->prefixlen, asp->peer) == ACTION_DENY) {
+ path_put(fasp);
goto withdraw;
}
- if (asp == NULL)
- asp = new->aspath;
+ if (fasp == NULL)
+ fasp = asp;
- up_generate(peer, asp, &addr, new->prefix->prefixlen);
+ up_generate(peer, fasp, &addr, new->re->prefix->prefixlen);
/* free modified aspath */
- if (asp != new->aspath)
- path_put(asp);
+ if (fasp != asp)
+ path_put(fasp);
}
}