From 54494a532fdf6f4dd77028993c4dccd7de875d3d Mon Sep 17 00:00:00 2001 From: claudio Date: Wed, 7 Feb 2018 00:02:02 +0000 Subject: [PATCH] Add plumbing inside of the prefix handling to put prefixes on either the 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 | 12 +++---- usr.sbin/bgpd/rde.h | 20 +++++------ usr.sbin/bgpd/rde_rib.c | 75 +++++++++++++++++++++++++++++------------ 3 files changed, 68 insertions(+), 39 deletions(-) diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 7ec8171bc18..416f72bc95d 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -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 @@ -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); diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index 84bdb0b7ad2..dc02d3dc721 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -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 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); diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index 8959bbd8a04..cddb8d3e23d 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.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 @@ -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 -- 2.20.1