From 2b6d2161ac7b5eca12c9e051c994a7239c33806c Mon Sep 17 00:00:00 2001 From: claudio Date: Mon, 5 Feb 2018 03:55:54 +0000 Subject: [PATCH] Change struct prefix a bit. Make the aspath pointer opaque and remove the direct pointer to the pt_prefix struct. To getter functions prefix_aspath() and prefix_peer() added to make access of the opaque pointers possible. Looks good henning@ and benno@ --- usr.sbin/bgpd/mrt.c | 56 ++++++++++-------- usr.sbin/bgpd/rde.c | 117 +++++++++++++++++++------------------ usr.sbin/bgpd/rde.h | 53 ++++++++++++----- usr.sbin/bgpd/rde_decide.c | 38 ++++++------ usr.sbin/bgpd/rde_rib.c | 69 ++++++++++------------ usr.sbin/bgpd/rde_update.c | 66 +++++++++++---------- 6 files changed, 219 insertions(+), 180 deletions(-) diff --git a/usr.sbin/bgpd/mrt.c b/usr.sbin/bgpd/mrt.c index 468ad5eaec8..8a419d5da3f 100644 --- a/usr.sbin/bgpd/mrt.c +++ b/usr.sbin/bgpd/mrt.c @@ -1,4 +1,4 @@ -/* $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 @@ -253,6 +253,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum, 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; @@ -262,7 +263,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum, 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; } @@ -280,7 +281,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum, 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: @@ -307,14 +308,15 @@ mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum, 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: @@ -337,7 +339,7 @@ mrt_dump_entry_mp(struct mrt *mrt, struct prefix *p, u_int16_t snum, 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; } @@ -367,13 +369,14 @@ mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum, 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); @@ -382,19 +385,20 @@ mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum, 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); @@ -403,8 +407,8 @@ mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum, 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; @@ -415,11 +419,11 @@ mrt_dump_entry(struct mrt *mrt, struct prefix *p, u_int16_t snum, } 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; @@ -493,24 +497,26 @@ mrt_dump_entry_v2(struct mrt *mrt, struct rib_entry *re, u_int32_t snum) } 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); @@ -659,10 +665,10 @@ mrt_dump_upcall(struct rib_entry *re, void *ptr) 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)); } } diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index bb44bbd2ae5..072bcd630c9 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $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 @@ -2209,11 +2209,11 @@ rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags) /* 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) @@ -2226,7 +2226,7 @@ rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags) 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); @@ -2266,54 +2266,57 @@ rde_dump_filterout(struct rde_peer *peer, struct prefix *p, 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 */ @@ -2572,6 +2575,7 @@ rde_send_kroute(struct rib *rib, struct prefix *new, struct prefix *old) struct kroute_full kr; struct bgpd_addr addr; struct prefix *p; + struct rde_aspath *asp; struct rdomain *rd; enum imsg_type type; @@ -2579,11 +2583,11 @@ rde_send_kroute(struct rib *rib, struct prefix *new, struct prefix *old) * 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 { @@ -2591,19 +2595,19 @@ rde_send_kroute(struct rib *rib, struct prefix *new, struct prefix *old) 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: @@ -2612,14 +2616,13 @@ rde_send_kroute(struct rib *rib, struct prefix *new, struct prefix *old) 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) @@ -3013,7 +3016,7 @@ rde_softreconfig_in(struct rib_entry *re, void *ptr) * so cache the values. */ np = LIST_NEXT(p, rib_l); - asp = p->aspath; + asp = prefix_aspath(p); peer = asp->peer; /* check if prefix changed */ @@ -3076,12 +3079,12 @@ rde_softreconfig_out(struct rib_entry *re, void *ptr) 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) */ @@ -3098,9 +3101,9 @@ rde_softreconfig_out(struct rib_entry *re, void *ptr) 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); } @@ -3121,9 +3124,9 @@ rde_softreconfig_unload_peer(struct rib_entry *re, void *ptr) 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 */ @@ -3132,7 +3135,7 @@ rde_softreconfig_unload_peer(struct rib_entry *re, void *ptr) /* send withdraw */ up_generate(peer, NULL, &addr, pt->prefixlen); done: - if (oasp != p->aspath) + if (oasp != prefix_aspath(p)) path_put(oasp); } @@ -3663,26 +3666,28 @@ void 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) diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index 3b333d79df0..2684d5e3120 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $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 and @@ -25,6 +25,7 @@ #include #include "bgpd.h" +#include "log.h" /* rde internal structures */ @@ -307,9 +308,10 @@ struct rib_desc { 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; }; @@ -407,17 +409,27 @@ int rde_filter_equal(struct filter_head *, struct filter_head *, 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); @@ -480,6 +492,19 @@ void prefix_updateall(struct rde_aspath *, enum nexthop_state, 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); diff --git a/usr.sbin/bgpd/rde_decide.c b/usr.sbin/bgpd/rde_decide.c index 2e5c2ab884d..846ed0653fb 100644 --- a/usr.sbin/bgpd/rde_decide.c +++ b/usr.sbin/bgpd/rde_decide.c @@ -1,4 +1,4 @@ -/* $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 @@ -110,6 +110,7 @@ int 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; @@ -119,8 +120,8 @@ prefix_cmp(struct prefix *p1, struct prefix *p2) 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) @@ -215,12 +216,12 @@ prefix_cmp(struct prefix *p1, struct prefix *p2) 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)) { @@ -249,7 +250,7 @@ prefix_evaluate(struct prefix *p, struct rib_entry *re) 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; @@ -272,16 +273,19 @@ prefix_evaluate(struct prefix *p, struct rib_entry *re) } 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 @@ -294,6 +298,6 @@ prefix_evaluate(struct prefix *p, struct rib_entry *re) re->active = xp; if (xp != NULL) - xp->aspath->active_cnt++; + prefix_aspath(xp)->active_cnt++; } } diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index afceee32f85..349c66bd990 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.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 @@ -149,14 +149,15 @@ rib_free(struct rib *rib) * 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) @@ -354,8 +355,9 @@ struct path_table pathtable; 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 @@ -404,7 +406,7 @@ path_update(struct rib *rib, struct rde_peer *peer, struct rde_aspath *nasp, * 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); @@ -500,10 +502,10 @@ path_remove(struct rde_aspath *asp) 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); } @@ -522,7 +524,7 @@ path_remove_stale(struct rde_aspath *asp, u_int8_t aid) 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) @@ -531,10 +533,10 @@ path_remove_stale(struct rde_aspath *asp, u_int8_t aid) 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 */ @@ -705,7 +707,7 @@ prefix_add(struct rib *rib, struct rde_aspath *asp, struct bgpd_addr *prefix, 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 @@ -723,14 +725,13 @@ prefix_move(struct rde_aspath *asp, struct prefix *p) 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); @@ -754,14 +755,13 @@ prefix_move(struct rde_aspath *asp, struct prefix *p) 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); @@ -783,15 +783,14 @@ prefix_remove(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix, 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); @@ -874,11 +873,11 @@ prefix_bypeer(struct rib_entry *re, struct rde_peer *peer, u_int32_t flags) 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); } @@ -933,7 +932,7 @@ prefix_destroy(struct prefix *p) { struct rde_aspath *asp; - asp = p->aspath; + asp = prefix_aspath(p); prefix_unlink(p); prefix_free(p); @@ -975,10 +974,8 @@ prefix_link(struct prefix *pref, struct rib_entry *re, struct rde_aspath *asp) 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 */ @@ -998,17 +995,13 @@ prefix_unlink(struct prefix *pref) 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; /* diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c index 96dfa3c6b40..80c13193291 100644 --- a/usr.sbin/bgpd/rde_update.c +++ b/usr.sbin/bgpd/rde_update.c @@ -1,4 +1,4 @@ -/* $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 @@ -275,6 +275,8 @@ int 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) @@ -284,20 +286,23 @@ up_test_update(struct rde_peer *peer, struct prefix *p) /* 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 @@ -306,9 +311,9 @@ up_test_update(struct rde_peer *peer, struct prefix *p) * 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); } @@ -330,27 +335,26 @@ up_test_update(struct rde_peer *peer, struct prefix *p) * 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 */ @@ -406,7 +410,7 @@ void 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) @@ -417,13 +421,14 @@ withdraw: 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: @@ -434,20 +439,21 @@ withdraw: 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); } } -- 2.20.1