From 40222bad1bc7c06ab659feae858f4bfbec35b40c Mon Sep 17 00:00:00 2001 From: claudio Date: Fri, 3 Aug 2018 16:31:22 +0000 Subject: [PATCH] Move nexthop and nexthop flags from the rde_aspath to struct prefix. struct prefix will be slowly becomming the hub of the rib. OK phessler@ job@ --- usr.sbin/bgpd/rde.c | 43 ++++----- usr.sbin/bgpd/rde.h | 52 +++++----- usr.sbin/bgpd/rde_filter.c | 8 +- usr.sbin/bgpd/rde_rib.c | 193 ++++++++++++++++++------------------- usr.sbin/bgpd/rde_update.c | 18 ++-- 5 files changed, 158 insertions(+), 156 deletions(-) diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index bdb405e4c90..b149451abc9 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.407 2018/08/03 14:10:39 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.408 2018/08/03 16:31:22 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -991,7 +991,7 @@ rde_update_dispatch(struct imsg *imsg) imsg->hdr.len - IMSG_HEADER_SIZE - 4 - withdrawn_len - attrpath_len; bzero(&mpa, sizeof(mpa)); - rde_filterstate_prep(&state, NULL, NULL); + rde_filterstate_prep(&state, NULL, NULL, 0); if (attrpath_len != 0) { /* 0 = no NLRI information in this message */ /* parse path attributes */ while (len > 0) { @@ -1306,7 +1306,8 @@ rde_update_update(struct rde_peer *peer, struct filterstate *in, for (i = RIB_LOC_START; i < rib_size; i++) { if (*ribs[i].name == '\0') break; - rde_filterstate_prep(&state, &in->aspath, in->nexthop); + rde_filterstate_prep(&state, &in->aspath, in->nexthop, + in->nhflags); /* input filter */ action = rde_filter(ribs[i].in_rules, peer, p, &state); @@ -2100,7 +2101,8 @@ rde_dump_filterout(struct rde_peer *peer, struct prefix *p, if (up_test_update(peer, p) != 1) return; - rde_filterstate_prep(&state, prefix_aspath(p), prefix_nexthop(p)); + rde_filterstate_prep(&state, prefix_aspath(p), prefix_nexthop(p), + prefix_nhflags(p)); a = rde_filter(out_rules, peer, p, &state); if (a == ACTION_ALLOW) @@ -2421,9 +2423,9 @@ rde_send_kroute(struct rib *rib, struct prefix *new, struct prefix *old) bzero(&kr, sizeof(kr)); memcpy(&kr.prefix, &addr, sizeof(kr.prefix)); kr.prefixlen = p->re->prefix->prefixlen; - if (asp->flags & F_NEXTHOP_REJECT) + if (prefix_nhflags(p) == NEXTHOP_REJECT) kr.flags |= F_REJECT; - if (asp->flags & F_NEXTHOP_BLACKHOLE) + if (prefix_nhflags(p) == NEXTHOP_BLACKHOLE) kr.flags |= F_BLACKHOLE; if (type == IMSG_KROUTE_CHANGE) memcpy(&kr.nexthop, &prefix_nexthop(p)->true_nexthop, @@ -2889,7 +2891,8 @@ rde_softreconfig_in(struct rib_entry *re, void *bula) if (*rib->name == '\0') break; - rde_filterstate_prep(&state, asp, prefix_nexthop(p)); + rde_filterstate_prep(&state, asp, prefix_nexthop(p), + prefix_nhflags(p)); action = rde_filter(rib->in_rules, peer, p, &state); if (action == ACTION_ALLOW) { @@ -2922,8 +2925,10 @@ rde_softreconfig_out_peer(struct rib_entry *re, struct rde_peer *peer) if (up_test_update(peer, p) != 1) return; - rde_filterstate_prep(&ostate, prefix_aspath(p), prefix_nexthop(p)); - rde_filterstate_prep(&nstate, prefix_aspath(p), prefix_nexthop(p)); + rde_filterstate_prep(&ostate, prefix_aspath(p), prefix_nexthop(p), + prefix_nhflags(p)); + rde_filterstate_prep(&nstate, prefix_aspath(p), prefix_nexthop(p), + prefix_nhflags(p)); oa = rde_filter(out_rules_tmp, peer, p, &ostate); na = rde_filter(out_rules, peer, p, &nstate); @@ -2937,17 +2942,10 @@ rde_softreconfig_out_peer(struct rib_entry *re, struct rde_peer *peer) /* send withdraw */ up_generate(peer, NULL, &addr, pt->prefixlen); } else if (oa == ACTION_ALLOW && na == ACTION_ALLOW) { - /* XXX update nexthop for now, ugly but will go away */ - nexthop_put(nstate.aspath.nexthop); - nstate.aspath.nexthop = nexthop_ref(nstate.nexthop); - nstate.aspath.flags = (nstate.aspath.flags & ~F_NEXTHOP_MASK) | - (nstate.nhflags & F_NEXTHOP_MASK); - nexthop_put(ostate.aspath.nexthop); - ostate.aspath.nexthop = nexthop_ref(ostate.nexthop); - ostate.aspath.flags = (ostate.aspath.flags & ~F_NEXTHOP_MASK) | - (ostate.nhflags & F_NEXTHOP_MASK); - /* send update if path attributes changed */ - if (path_compare(&nstate.aspath, &ostate.aspath) != 0) + /* send update if anything changed */ + if (nstate.nhflags != ostate.nhflags || + nstate.nexthop != ostate.nexthop || + path_compare(&nstate.aspath, &ostate.aspath) != 0) up_generate(peer, &nstate, &addr, pt->prefixlen); } @@ -2985,7 +2983,8 @@ rde_softreconfig_unload_peer(struct rib_entry *re, void *ptr) if (up_test_update(peer, p) != 1) return; - rde_filterstate_prep(&ostate, prefix_aspath(p), prefix_nexthop(p)); + rde_filterstate_prep(&ostate, prefix_aspath(p), prefix_nexthop(p), + prefix_nhflags(p)); if (rde_filter(out_rules_tmp, peer, p, &ostate) != ACTION_DENY) { /* send withdraw */ up_generate(peer, NULL, &addr, pt->prefixlen); @@ -3461,7 +3460,7 @@ network_add(struct network_config *nc, int flagstatic) } if (!flagstatic) asp->flags |= F_ANN_DYNAMIC; - rde_filterstate_prep(&state, asp, NULL); /* nexthop is not set */ + rde_filterstate_prep(&state, asp, NULL, 0); /* nexthop is not set */ rde_apply_set(&nc->attrset, &state, nc->prefix.aid, peerself, peerself); if (vpnset) rde_apply_set(vpnset, &state, nc->prefix.aid, peerself, diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index aece90bc1de..551beb07b25 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.182 2018/07/31 15:30:04 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.183 2018/08/03 16:31:22 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker and @@ -166,11 +166,6 @@ struct mpattr { #define F_ATTR_LOOP 0x00200 /* path would cause a route loop */ #define F_PREFIX_ANNOUNCED 0x00400 #define F_ANN_DYNAMIC 0x00800 -#define F_NEXTHOP_SELF 0x01000 -#define F_NEXTHOP_REJECT 0x02000 -#define F_NEXTHOP_BLACKHOLE 0x04000 -#define F_NEXTHOP_NOMODIFY 0x08000 -#define F_NEXTHOP_MASK 0x0f000 #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 */ @@ -183,13 +178,12 @@ struct mpattr { #define DEFAULT_LPREF 100 struct rde_aspath { - LIST_ENTRY(rde_aspath) path_l, nexthop_l; + LIST_ENTRY(rde_aspath) path_l; TAILQ_ENTRY(rde_aspath) peer_l, update_l; struct prefix_queue prefixes, updates; struct attr **others; struct rde_peer *peer; struct aspath *aspath; - struct nexthop *nexthop; /* may be NULL */ u_int64_t hash; u_int32_t flags; /* internally used */ u_int32_t med; /* multi exit disc */ @@ -209,7 +203,7 @@ enum nexthop_state { struct nexthop { LIST_ENTRY(nexthop) nexthop_l; - struct aspath_head path_h; + struct prefix_list prefix_h; struct bgpd_addr exit_nexthop; struct bgpd_addr true_nexthop; struct bgpd_addr nexthop_net; @@ -303,21 +297,28 @@ struct rib_desc { #define RIB_LOC_START 2 struct prefix { - LIST_ENTRY(prefix) rib_l; + LIST_ENTRY(prefix) rib_l, nexthop_l; TAILQ_ENTRY(prefix) path_l; struct rib_entry *re; struct rde_aspath *aspath; struct rde_peer *peer; + struct nexthop *nexthop; /* may be NULL */ time_t lastchange; - int flags; + u_int8_t flags; + u_int8_t nhflags; }; #define F_PREFIX_USE_UPDATES 0x01 /* linked onto the updates list */ +#define NEXTHOP_SELF 0x01 +#define NEXTHOP_REJECT 0x02 +#define NEXTHOP_BLACKHOLE 0x04 +#define NEXTHOP_NOMODIFY 0x08 + struct filterstate { - struct rde_aspath aspath; + struct rde_aspath aspath; struct nexthop *nexthop; - unsigned int nhflags; + u_int8_t nhflags; }; extern struct rde_memstats rdemem; @@ -401,7 +402,8 @@ u_char *community_ext_delete_non_trans(u_char *, u_int16_t, void prefix_evaluate(struct prefix *, struct rib_entry *); /* rde_filter.c */ -void rde_filterstate_prep(struct filterstate *, struct rde_aspath *, struct nexthop *); +void rde_filterstate_prep(struct filterstate *, struct rde_aspath *, + struct nexthop *, u_int8_t); void rde_filterstate_clean(struct filterstate *); enum filter_actions rde_filter(struct filter_head *, struct rde_peer *, struct prefix *, struct filterstate *); @@ -490,12 +492,18 @@ int prefix_write(u_char *, int, struct bgpd_addr *, u_int8_t, int); int prefix_writebuf(struct ibuf *, struct bgpd_addr *, u_int8_t); struct prefix *prefix_bypeer(struct rib_entry *, struct rde_peer *, u_int32_t); -void prefix_updateall(struct rde_aspath *, enum nexthop_state, +void prefix_updateall(struct prefix *, 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_peer * +prefix_peer(struct prefix *p) +{ + return (p->peer); +} + static inline struct rde_aspath * prefix_aspath(struct prefix *p) { @@ -505,21 +513,21 @@ prefix_aspath(struct prefix *p) static inline struct nexthop * prefix_nexthop(struct prefix *p) { - return (p->aspath->nexthop); + return (p->nexthop); } -static inline struct rde_peer * -prefix_peer(struct prefix *p) +static inline u_int8_t +prefix_nhflags(struct prefix *p) { - return (p->peer); + return (p->nhflags); } void nexthop_init(u_int32_t); void nexthop_shutdown(void); void nexthop_modify(struct nexthop *, enum action_types, u_int8_t, - struct nexthop **, u_int32_t *); -void nexthop_link(struct rde_aspath *); -void nexthop_unlink(struct rde_aspath *); + struct nexthop **, u_int8_t *); +void nexthop_link(struct prefix *); +void nexthop_unlink(struct prefix *); void nexthop_update(struct kroute_nexthop *); struct nexthop *nexthop_get(struct bgpd_addr *); struct nexthop *nexthop_ref(struct nexthop *); diff --git a/usr.sbin/bgpd/rde_filter.c b/usr.sbin/bgpd/rde_filter.c index c67a19d476c..5d287b63840 100644 --- a/usr.sbin/bgpd/rde_filter.c +++ b/usr.sbin/bgpd/rde_filter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde_filter.c,v 1.98 2018/08/02 14:41:42 claudio Exp $ */ +/* $OpenBSD: rde_filter.c,v 1.99 2018/08/03 16:31:22 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker @@ -640,7 +640,7 @@ rde_filter_equal(struct filter_head *a, struct filter_head *b, void rde_filterstate_prep(struct filterstate *state, struct rde_aspath *asp, - struct nexthop *nh) + struct nexthop *nh, u_int8_t nhflags) { memset(state, 0, sizeof(*state)); @@ -648,9 +648,7 @@ rde_filterstate_prep(struct filterstate *state, struct rde_aspath *asp, if (asp) path_copy(&state->aspath, asp); state->nexthop = nexthop_ref(nh); - /* XXX the flag handling needs improvement */ - if (asp) - state->nhflags |= asp->flags & F_NEXTHOP_MASK; + state->nhflags = nhflags; } void diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index f566017575a..1efcd0fd5bb 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.172 2018/07/22 16:59:08 claudio Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.173 2018/08/03 16:31:22 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker @@ -48,9 +48,11 @@ 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); -int prefix_add(struct rib *, struct rde_aspath *, - struct bgpd_addr *, int, int); -void prefix_move(struct rde_aspath *, struct prefix *, int); +int prefix_add(struct bgpd_addr *, int, struct rib *, + struct rde_peer *, struct rde_aspath *, + struct filterstate *, int); +int prefix_move(struct prefix *, struct rde_peer *, + struct rde_aspath *, struct filterstate *, int); static inline void re_lock(struct rib_entry *re) @@ -423,11 +425,6 @@ path_update(struct rib *rib, struct rde_peer *peer, struct filterstate *state, struct prefix *p; int pflag = 0; - nexthop_put(nasp->nexthop); - nasp->nexthop = nexthop_ref(state->nexthop); - nasp->flags = (nasp->flags & ~F_NEXTHOP_MASK) | - (state->nhflags & F_NEXTHOP_MASK); - if (nasp->pftableid) { rde_send_pftable(nasp->pftableid, prefix, prefixlen, 0); rde_send_pftable_commit(); @@ -437,7 +434,9 @@ path_update(struct rib *rib, struct rde_peer *peer, struct filterstate *state, * First try to find a prefix in the specified RIB. */ if ((p = prefix_get(rib, peer, prefix, prefixlen, 0)) != NULL) { - if (path_compare(nasp, prefix_aspath(p)) == 0) { + if (path_compare(nasp, prefix_aspath(p)) == 0 && + prefix_nexthop(p) == state->nexthop && + prefix_nhflags(p) == state->nhflags) { /* no change, update last change */ p->lastchange = time(NULL); return (0); @@ -457,10 +456,10 @@ path_update(struct rib *rib, struct rde_peer *peer, struct filterstate *state, /* If the prefix was found move it else add it to the aspath. */ if (p != NULL) - prefix_move(asp, p, pflag); + return (prefix_move(p, peer, asp, state, pflag)); else - return (prefix_add(rib, asp, prefix, prefixlen, pflag)); - return (0); + return (prefix_add(prefix, prefixlen, rib, peer, asp, + state, pflag)); } int @@ -506,8 +505,6 @@ path_compare(struct rde_aspath *a, struct rde_aspath *b) return (-1); r = aspath_compare(a->aspath, b->aspath); - if (r == 0) - r = nexthop_compare(a->nexthop, b->nexthop); if (r > 0) return (1); if (r < 0) @@ -658,7 +655,6 @@ path_destroy(struct rde_aspath *asp) if (!TAILQ_EMPTY(&asp->prefixes) || !TAILQ_EMPTY(&asp->updates)) log_warnx("path_destroy: still has prefixes, leaking"); - nexthop_unlink(asp); LIST_REMOVE(asp, path_l); TAILQ_REMOVE(&asp->peer->path_h, asp, peer_l); asp->peer = NULL; @@ -678,7 +674,6 @@ path_empty(struct rde_aspath *asp) * These are peer_l, path_l and nexthop_l. * peer_l: list of all aspaths that belong to that peer * path_l: hash list to find paths quickly - * nexthop_l: list of all aspaths with an equal exit nexthop */ static void path_link(struct rde_aspath *asp, struct rde_peer *peer) @@ -692,7 +687,6 @@ path_link(struct rde_aspath *asp, struct rde_peer *peer) LIST_INSERT_HEAD(head, asp, path_l); TAILQ_INSERT_HEAD(&peer->path_h, asp, peer_l); - nexthop_link(asp); asp->flags |= F_ATTR_LINKED; } @@ -708,7 +702,6 @@ path_copy(struct rde_aspath *dst, const struct rde_aspath *src) dst->aspath->refcnt++; rdemem.aspath_refs++; } - dst->nexthop = nexthop_ref(src->nexthop); dst->hash = 0; dst->med = src->med; dst->lpref = src->lpref; @@ -759,7 +752,6 @@ path_clean(struct rde_aspath *asp) rtlabel_unref(asp->rtlabelid); pftable_unref(asp->pftableid); aspath_put(asp->aspath); - nexthop_put(asp->nexthop); attr_freeall(asp); } @@ -781,7 +773,8 @@ 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 *, int); + struct rde_peer *, struct rde_aspath *, + struct filterstate *, int); static void prefix_unlink(struct prefix *); /* @@ -803,9 +796,9 @@ prefix_get(struct rib *rib, struct rde_peer *peer, struct bgpd_addr *prefix, * Adds or updates a prefix. */ int -prefix_add(struct rib *rib, struct rde_aspath *asp, struct bgpd_addr *prefix, - int prefixlen, int flag) - +prefix_add(struct bgpd_addr *prefix, int prefixlen, struct rib *rib, + struct rde_peer *peer, struct rde_aspath *asp, struct filterstate *state, + int flag) { struct prefix *p; struct rib_entry *re; @@ -817,14 +810,16 @@ 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, flag); + prefix_link(p, re, peer, asp, state, flag); return (1); } else { - if (prefix_aspath(p) != asp) { - /* prefix belongs to a different aspath so move */ - prefix_move(asp, p, flag); - } else - p->lastchange = time(NULL); + if (prefix_aspath(p) != asp || + prefix_nexthop(p) != state->nexthop || + prefix_nhflags(p) != state->nhflags) { + /* prefix metadata changed therefor move */ + return (prefix_move(p, peer, asp, state, flag)); + } + p->lastchange = time(NULL); return (0); } } @@ -832,22 +827,25 @@ 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, int flag) +int +prefix_move(struct prefix *p, struct rde_peer *peer, + struct rde_aspath *asp, struct filterstate *state, int flag) { struct prefix *np; struct rde_aspath *oasp; - if (asp->peer != prefix_peer(p)) + if (peer != prefix_peer(p)) fatalx("prefix_move: cross peer move"); - /* create new prefix node */ np = prefix_alloc(); np->aspath = asp; - np->peer = asp->peer; + np->nexthop = nexthop_ref(state->nexthop); + nexthop_link(np); + np->peer = peer; np->re = p->re; np->lastchange = time(NULL); np->flags = flag; + np->nhflags = state->nhflags; /* add to new as path */ if (np->flags & F_PREFIX_USE_UPDATES) @@ -882,11 +880,16 @@ prefix_move(struct rde_aspath *asp, struct prefix *p, int flag) p->aspath = NULL; p->peer = NULL; p->re = NULL; + nexthop_unlink(p); + nexthop_put(p->nexthop); + p->nexthop = NULL; prefix_free(p); /* destroy old path if empty */ if (path_empty(oasp)) path_destroy(oasp); + + return (0); } /* @@ -1020,47 +1023,43 @@ prefix_bypeer(struct rib_entry *re, struct rde_peer *peer, u_int32_t flags) } void -prefix_updateall(struct rde_aspath *asp, enum nexthop_state state, +prefix_updateall(struct prefix *p, enum nexthop_state state, enum nexthop_state oldstate) { - struct prefix *p; - - TAILQ_FOREACH(p, &asp->prefixes, path_l) { - /* - * Skip non local-RIBs or RIBs that are flagged as noeval. - * There is no need to run over updates since that is only - * used on the Adj-RIB-Out. - */ - if (re_rib(p->re)->flags & F_RIB_NOEVALUATE) - continue; - - if (oldstate == state && state == NEXTHOP_REACH) { - /* - * The state of the nexthop did not change. The only - * thing that may have changed is the true_nexthop - * or other internal infos. This will not change - * the routing decision so shortcut here. - */ - if ((re_rib(p->re)->flags & F_RIB_NOFIB) == 0 && - p == p->re->active) - rde_send_kroute(re_rib(p->re), p, NULL); - continue; - } + /* + * Skip non local-RIBs or RIBs that are flagged as noeval. + * There is no need to run over updates since that is only + * used on the Adj-RIB-Out. + */ + if (re_rib(p->re)->flags & F_RIB_NOEVALUATE) + return; - /* redo the route decision */ - LIST_REMOVE(p, rib_l); + if (oldstate == state && state == NEXTHOP_REACH) { /* - * If the prefix is the active one remove it first, - * this has to be done because we can not detect when - * the active prefix changes its state. In this case - * we know that this is a withdrawal and so the second - * prefix_evaluate() will generate no update because - * the nexthop is unreachable or ineligible. + * The state of the nexthop did not change. The only + * thing that may have changed is the true_nexthop + * or other internal infos. This will not change + * the routing decision so shortcut here. */ - if (p == p->re->active) - prefix_evaluate(NULL, p->re); - prefix_evaluate(p, p->re); + if ((re_rib(p->re)->flags & F_RIB_NOFIB) == 0 && + p == p->re->active) + rde_send_kroute(re_rib(p->re), p, NULL); + return; } + + /* redo the route decision */ + LIST_REMOVE(p, rib_l); + /* + * If the prefix is the active one remove it first, + * this has to be done because we can not detect when + * the active prefix changes its state. In this case + * we know that this is a withdrawal and so the second + * prefix_evaluate() will generate no update because + * the nexthop is unreachable or ineligible. + */ + if (p == p->re->active) + prefix_evaluate(NULL, p->re); + prefix_evaluate(p, p->re); } /* kill a prefix. */ @@ -1107,8 +1106,8 @@ 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, - int flag) +prefix_link(struct prefix *pref, struct rib_entry *re, struct rde_peer *peer, + struct rde_aspath *asp, struct filterstate *state, int flag) { if (flag & F_PREFIX_USE_UPDATES) TAILQ_INSERT_HEAD(&asp->updates, pref, path_l); @@ -1116,10 +1115,13 @@ prefix_link(struct prefix *pref, struct rib_entry *re, struct rde_aspath *asp, TAILQ_INSERT_HEAD(&asp->prefixes, pref, path_l); pref->aspath = asp; - pref->peer = asp->peer; + pref->peer = peer; + pref->nexthop = nexthop_ref(state->nexthop); + nexthop_link(pref); pref->re = re; pref->lastchange = time(NULL); pref->flags = flag; + pref->nhflags = state->nhflags; /* make route decision */ prefix_evaluate(pref, re); @@ -1148,6 +1150,9 @@ prefix_unlink(struct prefix *pref) rib_remove(re); /* destroy all references to other objects */ + nexthop_unlink(pref); + nexthop_put(pref->nexthop); + pref->nexthop = NULL; pref->aspath = NULL; pref->peer = NULL; pref->re = NULL; @@ -1248,7 +1253,7 @@ void nexthop_update(struct kroute_nexthop *msg) { struct nexthop *nh; - struct rde_aspath *asp; + struct prefix *p; enum nexthop_state oldstate; nh = nexthop_lookup(&msg->nexthop); @@ -1289,28 +1294,27 @@ nexthop_update(struct kroute_nexthop *msg) */ return; - LIST_FOREACH(asp, &nh->path_h, nexthop_l) { - prefix_updateall(asp, nh->state, oldstate); + LIST_FOREACH(p, &nh->prefix_h, nexthop_l) { + prefix_updateall(p, nh->state, oldstate); } } void nexthop_modify(struct nexthop *setnh, enum action_types type, u_int8_t aid, - struct nexthop **nexthop, u_int32_t *flags) + struct nexthop **nexthop, u_int8_t *flags) { - *flags &= ~F_NEXTHOP_MASK; switch (type) { case ACTION_SET_NEXTHOP_REJECT: - *flags |= F_NEXTHOP_REJECT; + *flags = NEXTHOP_REJECT; break; case ACTION_SET_NEXTHOP_BLACKHOLE: - *flags |= F_NEXTHOP_BLACKHOLE; + *flags = NEXTHOP_BLACKHOLE; break; case ACTION_SET_NEXTHOP_NOMODIFY: - *flags |= F_NEXTHOP_NOMODIFY; + *flags = NEXTHOP_NOMODIFY; break; case ACTION_SET_NEXTHOP_SELF: - *flags |= F_NEXTHOP_SELF; + *flags = NEXTHOP_SELF; break; case ACTION_SET_NEXTHOP: /* @@ -1321,6 +1325,7 @@ nexthop_modify(struct nexthop *setnh, enum action_types type, u_int8_t aid, break; nexthop_put(*nexthop); *nexthop = nexthop_ref(setnh); + *flags = 0; break; default: break; @@ -1328,29 +1333,21 @@ nexthop_modify(struct nexthop *setnh, enum action_types type, u_int8_t aid, } void -nexthop_link(struct rde_aspath *asp) +nexthop_link(struct prefix *p) { - if (asp->nexthop == NULL) + if (p->nexthop == NULL) return; - LIST_INSERT_HEAD(&asp->nexthop->path_h, asp, nexthop_l); + LIST_INSERT_HEAD(&p->nexthop->prefix_h, p, nexthop_l); } void -nexthop_unlink(struct rde_aspath *asp) +nexthop_unlink(struct prefix *p) { - struct nexthop *nh; - - if (asp->nexthop == NULL) + if (p->nexthop == NULL) return; - LIST_REMOVE(asp, nexthop_l); - - /* remove reference to nexthop */ - nh = asp->nexthop; - asp->nexthop = NULL; - - (void)nexthop_put(nh); + LIST_REMOVE(p, nexthop_l); } struct nexthop * @@ -1365,7 +1362,7 @@ nexthop_get(struct bgpd_addr *nexthop) fatal("nexthop_alloc"); rdemem.nexthop_cnt++; - LIST_INIT(&nh->path_h); + LIST_INIT(&nh->prefix_h); nh->state = NEXTHOP_LOOKUP; nexthop_ref(nh); /* take reference for lookup */ nh->exit_nexthop = *nexthop; @@ -1396,7 +1393,7 @@ nexthop_put(struct nexthop *nh) return (0); /* sanity check */ - if (!LIST_EMPTY(&nh->path_h) || nh->state == NEXTHOP_LOOKUP) + if (!LIST_EMPTY(&nh->prefix_h) || nh->state == NEXTHOP_LOOKUP) fatalx("nexthop_put: refcnt error"); LIST_REMOVE(nh, nexthop_l); diff --git a/usr.sbin/bgpd/rde_update.c b/usr.sbin/bgpd/rde_update.c index c4af0dd75b4..d7270fb0d32 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.95 2018/07/22 16:59:08 claudio Exp $ */ +/* $OpenBSD: rde_update.c,v 1.96 2018/08/03 16:31:22 claudio Exp $ */ /* * Copyright (c) 2004 Claudio Jeker @@ -426,7 +426,7 @@ withdraw: } rde_filterstate_prep(&state, prefix_aspath(new), - prefix_nexthop(new)); + prefix_nexthop(new), prefix_nhflags(new)); if (rde_filter(rules, peer, new, &state) == ACTION_DENY) { rde_filterstate_clean(&state); goto withdraw; @@ -485,7 +485,7 @@ up_generate_default(struct filter_head *rules, struct rde_peer *peer, p.flags = 0; /* filter as usual */ - rde_filterstate_prep(&state, asp, NULL); + rde_filterstate_prep(&state, asp, NULL, 0); if (rde_filter(rules, peer, &p, &state) == ACTION_DENY) { rde_filterstate_clean(&state); return; @@ -547,13 +547,13 @@ up_get_nexthop(struct rde_peer *peer, struct filterstate *state) in_addr_t mask; /* nexthop, already network byte order */ - if (state->nhflags & F_NEXTHOP_NOMODIFY) { + if (state->nhflags & NEXTHOP_NOMODIFY) { /* no modify flag set */ if (state->nexthop == NULL) return (peer->local_v4_addr.v4.s_addr); else return (state->nexthop->exit_nexthop.v4.s_addr); - } else if (state->nhflags & F_NEXTHOP_SELF) + } else if (state->nhflags & NEXTHOP_SELF) return (peer->local_v4_addr.v4.s_addr); else if (!peer->conf.ebgp) { /* @@ -616,7 +616,7 @@ up_generate_mp_reach(struct rde_peer *peer, struct update_attr *upa, upa->mpattr[20] = 0; /* Reserved must be 0 */ /* nexthop dance see also up_get_nexthop() */ - if (state->nhflags & F_NEXTHOP_NOMODIFY) { + if (state->nhflags & NEXTHOP_NOMODIFY) { /* no modify flag set */ if (state->nexthop == NULL) memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, @@ -625,7 +625,7 @@ up_generate_mp_reach(struct rde_peer *peer, struct update_attr *upa, memcpy(&upa->mpattr[4], &state->nexthop->exit_nexthop.v6, sizeof(struct in6_addr)); - } else if (state->nhflags & F_NEXTHOP_SELF) + } else if (state->nhflags & NEXTHOP_SELF) memcpy(&upa->mpattr[4], &peer->local_v6_addr.v6, sizeof(struct in6_addr)); else if (!peer->conf.ebgp) { @@ -675,7 +675,7 @@ up_generate_mp_reach(struct rde_peer *peer, struct update_attr *upa, upa->mpattr[3] = sizeof(u_int64_t) + sizeof(struct in_addr); /* nexthop dance see also up_get_nexthop() */ - if (state->nhflags & F_NEXTHOP_NOMODIFY) { + if (state->nhflags & NEXTHOP_NOMODIFY) { /* no modify flag set */ if (state->nexthop == NULL) memcpy(&upa->mpattr[12], @@ -686,7 +686,7 @@ up_generate_mp_reach(struct rde_peer *peer, struct update_attr *upa, memcpy(&upa->mpattr[12], &state->nexthop->exit_nexthop.v4, sizeof(struct in_addr)); - } else if (state->nhflags & F_NEXTHOP_SELF) + } else if (state->nhflags & NEXTHOP_SELF) memcpy(&upa->mpattr[12], &peer->local_v4_addr.v4, sizeof(struct in_addr)); else if (!peer->conf.ebgp) { -- 2.20.1