Add plumbing inside of the prefix handling to put prefixes on either the
authorclaudio <claudio@openbsd.org>
Wed, 7 Feb 2018 00:02:02 +0000 (00:02 +0000)
committerclaudio <claudio@openbsd.org>
Wed, 7 Feb 2018 00:02:02 +0000 (00:02 +0000)
prefixes or updates list depending on flags passed to the functions.
While there also introduce a similar flag for rde_aspath and adjust
path_compare so that this flag is ignored (liked the linked one).
OK benno@

usr.sbin/bgpd/rde.c
usr.sbin/bgpd/rde.h
usr.sbin/bgpd/rde_rib.c

index 7ec8171..416f72b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rde.c,v 1.376 2018/02/05 23:29:59 claudio Exp $ */
+/*     $OpenBSD: rde.c,v 1.377 2018/02/07 00:02:02 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -1334,7 +1334,7 @@ rde_update_update(struct rde_peer *peer, struct rde_aspath *asp,
 
        peer->prefix_rcvd_update++;
        /* add original path to the Adj-RIB-In */
-       if (path_update(&ribs[RIB_ADJ_IN].rib, peer, asp, prefix, prefixlen))
+       if (path_update(&ribs[RIB_ADJ_IN].rib, peer, asp, prefix, prefixlen, 0))
                peer->prefix_cnt++;
 
        for (i = RIB_LOC_START; i < rib_size; i++) {
@@ -1351,7 +1351,7 @@ rde_update_update(struct rde_peer *peer, struct rde_aspath *asp,
                        rde_update_log("update", i, peer,
                            &fasp->nexthop->exit_nexthop, prefix, prefixlen);
                        path_update(&ribs[i].rib, peer, fasp, prefix,
-                           prefixlen);
+                           prefixlen, 0);
                } else if (prefix_remove(&ribs[i].rib, peer, prefix, prefixlen,
                    0)) {
                        rde_update_log("filtered withdraw", i, peer,
@@ -3039,7 +3039,7 @@ rde_softreconfig_in(struct rib_entry *re, void *ptr)
                if (oa == ACTION_DENY && na == ACTION_ALLOW) {
                        /* update Local-RIB */
                        path_update(&rib->rib, peer, nasp, &addr,
-                           pt->prefixlen);
+                           pt->prefixlen, 0);
                } else if (oa == ACTION_ALLOW && na == ACTION_DENY) {
                        /* remove from Local-RIB */
                        prefix_remove(&rib->rib, peer, &addr, pt->prefixlen, 0);
@@ -3047,7 +3047,7 @@ rde_softreconfig_in(struct rib_entry *re, void *ptr)
                        if (path_compare(nasp, oasp) != 0)
                                /* send update */
                                path_update(&rib->rib, peer, nasp, &addr,
-                                   pt->prefixlen);
+                                   pt->prefixlen, 0);
                }
 
                if (oasp != asp)
@@ -3610,7 +3610,7 @@ network_add(struct network_config *nc, int flagstatic)
                if (*ribs[i].name == '\0')
                        break;
                path_update(&ribs[i].rib, peerself, asp, &nc->prefix,
-                   nc->prefixlen);
+                   nc->prefixlen, 0);
        }
        path_put(asp);
        filterset_free(&nc->attrset);
index 84bdb0b..dc02d3d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rde.h,v 1.165 2018/02/05 23:29:59 claudio Exp $ */
+/*     $OpenBSD: rde.h,v 1.166 2018/02/07 00:02:02 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> and
@@ -176,8 +176,9 @@ struct path_table {
 #define        F_NEXTHOP_BLACKHOLE     0x04000
 #define        F_NEXTHOP_NOMODIFY      0x08000
 #define        F_NEXTHOP_MASK          0x0f000
-#define        F_ATTR_PARSE_ERR        0x10000
-#define        F_ATTR_LINKED           0x20000
+#define        F_ATTR_PARSE_ERR        0x10000 /* parse error, not eligable */
+#define        F_ATTR_LINKED           0x20000 /* if set path is on various lists */
+#define        F_ATTR_UPDATE           0x20000 /* if set linked on update_l */
 
 
 #define ORIGIN_IGP             0
@@ -313,10 +314,13 @@ struct prefix {
        struct rib_entry                *re;
        union {
                struct rde_aspath               *_aspath;
-       } _p;
+       }                                _p;
        time_t                           lastchange;
+       int                              flags;
 };
 
+#define F_PREFIX_USE_UPDATES   0x01    /* linked onto the updates list */
+
 extern struct rde_memstats rdemem;
 
 /* prototypes */
@@ -467,9 +471,8 @@ void                 path_init(u_int32_t);
 void            path_init(u_int32_t);
 void            path_shutdown(void);
 int             path_update(struct rib *, struct rde_peer *,
-                    struct rde_aspath *, struct bgpd_addr *, int);
+                    struct rde_aspath *, struct bgpd_addr *, int, int);
 int             path_compare(struct rde_aspath *, struct rde_aspath *);
-struct rde_aspath *path_lookup(struct rde_aspath *, struct rde_peer *);
 void            path_remove(struct rde_aspath *);
 u_int32_t       path_remove_stale(struct rde_aspath *, u_int8_t);
 void            path_destroy(struct rde_aspath *);
@@ -479,11 +482,6 @@ struct rde_aspath *path_get(void);
 void            path_put(struct rde_aspath *);
 
 #define        PREFIX_SIZE(x)  (((x) + 7) / 8 + 1)
-struct prefix  *prefix_get(struct rib *, struct rde_peer *,
-                   struct bgpd_addr *, int, u_int32_t);
-int             prefix_add(struct rib *, struct rde_aspath *,
-                   struct bgpd_addr *, int);
-void            prefix_move(struct rde_aspath *, struct prefix *);
 int             prefix_remove(struct rib *, struct rde_peer *,
                    struct bgpd_addr *, int, u_int32_t);
 int             prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t);
index 8959bbd..cddb8d3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rde_rib.c,v 1.157 2018/02/05 23:29:59 claudio Exp $ */
+/*     $OpenBSD: rde_rib.c,v 1.158 2018/02/07 00:02:02 claudio Exp $ */
 
 /*
  * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@@ -47,6 +47,12 @@ struct rib_entry *rib_restart(struct rib_context *);
 RB_PROTOTYPE(rib_tree, rib_entry, rib_e, rib_compare);
 RB_GENERATE(rib_tree, rib_entry, rib_e, rib_compare);
 
+struct prefix  *prefix_get(struct rib *, struct rde_peer *,
+                   struct bgpd_addr *, int, u_int32_t);
+int             prefix_add(struct rib *, struct rde_aspath *,
+                   struct bgpd_addr *, int, int);
+void            prefix_move(struct rde_aspath *, struct prefix *, int);
+
 static inline void
 re_lock(struct rib_entry *re)
 {
@@ -348,6 +354,7 @@ rib_restart(struct rib_context *ctx)
 
 /* path specific functions */
 
+static struct rde_aspath *path_lookup(struct rde_aspath *, struct rde_peer *);
 static void    path_link(struct rde_aspath *, struct rde_peer *);
 
 struct path_table pathtable;
@@ -392,10 +399,11 @@ path_shutdown(void)
 
 int
 path_update(struct rib *rib, struct rde_peer *peer, struct rde_aspath *nasp,
-    struct bgpd_addr *prefix, int prefixlen)
+    struct bgpd_addr *prefix, int prefixlen, int flag)
 {
        struct rde_aspath       *asp;
        struct prefix           *p;
+       int                      pflag = 0;
 
        if (nasp->pftableid) {
                rde_send_pftable(nasp->pftableid, prefix, prefixlen, 0);
@@ -426,9 +434,9 @@ path_update(struct rib *rib, struct rde_peer *peer, struct rde_aspath *nasp,
 
        /* If the prefix was found move it else add it to the aspath. */
        if (p != NULL)
-               prefix_move(asp, p);
+               prefix_move(asp, p, pflag);
        else
-               return (prefix_add(rib, asp, prefix, prefixlen));
+               return (prefix_add(rib, asp, prefix, prefixlen, pflag));
        return (0);
 }
 
@@ -437,13 +445,21 @@ path_compare(struct rde_aspath *a, struct rde_aspath *b)
 {
        int              r;
 
-       if (a->origin > b->origin)
+       if (a == NULL && b == NULL)
+               return (0);
+       else if (b == NULL)
                return (1);
-       if (a->origin < b->origin)
+       else if (a == NULL)
                return (-1);
-       if ((a->flags & ~F_ATTR_LINKED) > (b->flags & ~F_ATTR_LINKED))
+       if ((a->flags & ~(F_ATTR_LINKED | F_ATTR_UPDATE)) >
+           (b->flags & ~(F_ATTR_LINKED | F_ATTR_UPDATE)))
                return (1);
-       if ((a->flags & ~F_ATTR_LINKED) < (b->flags & ~F_ATTR_LINKED))
+       if ((a->flags & ~(F_ATTR_LINKED | F_ATTR_UPDATE)) <
+           (b->flags & ~(F_ATTR_LINKED | F_ATTR_UPDATE)))
+               return (-1);
+       if (a->origin > b->origin)
+               return (1);
+       if (a->origin < b->origin)
                return (-1);
        if (a->med > b->med)
                return (1);
@@ -477,7 +493,7 @@ path_compare(struct rde_aspath *a, struct rde_aspath *b)
        return (attr_compare(a, b));
 }
 
-struct rde_aspath *
+static struct rde_aspath *
 path_lookup(struct rde_aspath *aspath, struct rde_peer *peer)
 {
        struct aspath_head      *head;
@@ -654,7 +670,7 @@ path_copy(struct rde_aspath *asp)
        nasp->pftableid = asp->pftableid;
        pftable_ref(nasp->pftableid);
 
-       nasp->flags = asp->flags & ~F_ATTR_LINKED;
+       nasp->flags = asp->flags & ~(F_ATTR_LINKED | F_ATTR_UPDATE);
        attr_copy(nasp, asp);
 
        return (nasp);
@@ -705,7 +721,7 @@ path_put(struct rde_aspath *asp)
 static struct prefix   *prefix_alloc(void);
 static void             prefix_free(struct prefix *);
 static void             prefix_link(struct prefix *, struct rib_entry *,
-                            struct rde_aspath *);
+                            struct rde_aspath *, int);
 static void             prefix_unlink(struct prefix *);
 
 /*
@@ -728,7 +744,7 @@ prefix_get(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix,
  */
 int
 prefix_add(struct rib *rib, struct rde_aspath *asp, struct bgpd_addr *prefix,
-    int prefixlen)
+    int prefixlen, int flag)
 
 {
        struct prefix           *p;
@@ -741,12 +757,12 @@ prefix_add(struct rib *rib, struct rde_aspath *asp, struct bgpd_addr *prefix,
        p = prefix_bypeer(re, asp->peer, asp->flags);
        if (p == NULL) {
                p = prefix_alloc();
-               prefix_link(p, re, asp);
+               prefix_link(p, re, asp, flag);
                return (1);
        } else {
                if (prefix_aspath(p) != asp) {
                        /* prefix belongs to a different aspath so move */
-                       prefix_move(asp, p);
+                       prefix_move(asp, p, flag);
                } else
                        p->lastchange = time(NULL);
                return (0);
@@ -757,7 +773,7 @@ prefix_add(struct rib *rib, struct rde_aspath *asp, struct bgpd_addr *prefix,
  * Move the prefix to the specified as path, removes the old asp if needed.
  */
 void
-prefix_move(struct rde_aspath *asp, struct prefix *p)
+prefix_move(struct rde_aspath *asp, struct prefix *p, int flag)
 {
        struct prefix           *np;
        struct rde_aspath       *oasp;
@@ -768,12 +784,15 @@ prefix_move(struct rde_aspath *asp, struct prefix *p)
        /* create new prefix node */
        np = prefix_alloc();
        np->_p._aspath = asp;
-       /* peer and prefix pointers are still equal */
        np->re = p->re;
        np->lastchange = time(NULL);
+       np->flags = flag;
 
        /* add to new as path */
-       TAILQ_INSERT_HEAD(&asp->prefixes, np, path_l);
+       if (np->flags & F_PREFIX_USE_UPDATES)
+               TAILQ_INSERT_HEAD(&asp->updates, np, path_l);
+       else
+               TAILQ_INSERT_HEAD(&asp->prefixes, np, path_l);
        PREFIX_COUNT(asp, 1);
        /*
         * no need to update the peer prefix count because we are only moving
@@ -793,7 +812,10 @@ prefix_move(struct rde_aspath *asp, struct prefix *p)
 
        /* remove old prefix node */
        oasp = prefix_aspath(p);
-       TAILQ_REMOVE(&oasp->prefixes, p, path_l);
+       if (p->flags & F_PREFIX_USE_UPDATES)
+               TAILQ_REMOVE(&oasp->updates, p, path_l);
+       else
+               TAILQ_REMOVE(&oasp->prefixes, p, path_l);
        PREFIX_COUNT(oasp, -1);
        /* as before peer count needs no update because of move */
 
@@ -1011,14 +1033,19 @@ prefix_network_clean(struct rde_peer *peer, time_t reloadtime, u_int32_t flags)
  * Link a prefix into the different parent objects.
  */
 static void
-prefix_link(struct prefix *pref, struct rib_entry *re, struct rde_aspath *asp)
+prefix_link(struct prefix *pref, struct rib_entry *re, struct rde_aspath *asp,
+    int flag)
 {
-       TAILQ_INSERT_HEAD(&asp->prefixes, pref, path_l);
+       if (flag & F_PREFIX_USE_UPDATES)
+               TAILQ_INSERT_HEAD(&asp->updates, pref, path_l);
+       else
+               TAILQ_INSERT_HEAD(&asp->prefixes, pref, path_l);
        PREFIX_COUNT(asp, 1);
 
        pref->_p._aspath = asp;
        pref->re = re;
        pref->lastchange = time(NULL);
+       pref->flags = flag;
 
        /* make route decision */
        prefix_evaluate(pref, re);
@@ -1037,15 +1064,19 @@ prefix_unlink(struct prefix *pref)
        LIST_REMOVE(pref, rib_l);
        prefix_evaluate(NULL, re);
 
-       pq = &prefix_aspath(pref)->prefixes;
-       TAILQ_REMOVE(pq, pref, path_l);
+       if (pref->flags & F_PREFIX_USE_UPDATES)
+               pq = &prefix_aspath(pref)->updates;
+       else
+               pq = &prefix_aspath(pref)->prefixes;
 
+       TAILQ_REMOVE(pq, pref, path_l);
        if (rib_empty(re))
                rib_remove(re);
 
        /* destroy all references to other objects */
        pref->_p._aspath = NULL;
        pref->re = NULL;
+       pref->flags = 0;
 
        /*
         * It's the caller's duty to do accounting and remove empty aspath