Change struct prefix a bit. Make the aspath pointer opaque and remove the
authorclaudio <claudio@openbsd.org>
Mon, 5 Feb 2018 03:55:54 +0000 (03:55 +0000)
committerclaudio <claudio@openbsd.org>
Mon, 5 Feb 2018 03:55:54 +0000 (03:55 +0000)
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
usr.sbin/bgpd/rde.c
usr.sbin/bgpd/rde.h
usr.sbin/bgpd/rde_decide.c
usr.sbin/bgpd/rde_rib.c
usr.sbin/bgpd/rde_update.c

index 468ad5e..8a419d5 100644 (file)
@@ -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 <claudio@openbsd.org>
@@ -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));
        }
 }
 
index bb44bbd..072bcd6 100644 (file)
@@ -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 <henning@openbsd.org>
@@ -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)
index 3b333d7..2684d5e 100644 (file)
@@ -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 <claudio@openbsd.org> and
@@ -25,6 +25,7 @@
 #include <stdint.h>
 
 #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);
index 2e5c2ab..846ed06 100644 (file)
@@ -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 <claudio@openbsd.org>
@@ -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++;
        }
 }
index afceee3..349c66b 100644 (file)
@@ -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 <claudio@openbsd.org>
@@ -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;
 
        /*
index 96dfa3c..80c1319 100644 (file)
@@ -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 <claudio@openbsd.org>
@@ -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);
        }
 }