From 89ee02f7f35d33f55336ac46ffa1bfe24de4cc54 Mon Sep 17 00:00:00 2001 From: claudio Date: Wed, 14 Aug 2024 19:09:51 +0000 Subject: [PATCH] Introduce 'rde rib Loc-RIB include filtered' a feature that includes filtered prefixes in the Loc-RIB This includes filtered prefixes into the Loc-RIB but they are marked ineligible so nothing will select them but it is possible to show them in bgpctl. So 'bppctl show rib filtered' will return all prefixes filtered out by the input filters. OK tb@ --- usr.sbin/bgpd/bgpd.conf.5 | 11 +++++-- usr.sbin/bgpd/bgpd.h | 5 ++- usr.sbin/bgpd/config.c | 3 +- usr.sbin/bgpd/parse.y | 13 ++++++-- usr.sbin/bgpd/printconf.c | 4 ++- usr.sbin/bgpd/rde.c | 64 +++++++++++++++++++++++++++----------- usr.sbin/bgpd/rde.h | 34 ++++++++++++-------- usr.sbin/bgpd/rde_decide.c | 6 +++- usr.sbin/bgpd/rde_rib.c | 28 +++++++++++------ 9 files changed, 119 insertions(+), 49 deletions(-) diff --git a/usr.sbin/bgpd/bgpd.conf.5 b/usr.sbin/bgpd/bgpd.conf.5 index e01abf88b76..d4b3fb71cf5 100644 --- a/usr.sbin/bgpd/bgpd.conf.5 +++ b/usr.sbin/bgpd/bgpd.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bgpd.conf.5,v 1.241 2024/08/12 09:04:23 claudio Exp $ +.\" $OpenBSD: bgpd.conf.5,v 1.242 2024/08/14 19:09:51 claudio Exp $ .\" .\" Copyright (c) 2004 Claudio Jeker .\" Copyright (c) 2003, 2004 Henning Brauer @@ -16,7 +16,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: August 12 2024 $ +.Dd $Mdocdate: August 14 2024 $ .Dt BGPD.CONF 5 .Os .Sh NAME @@ -325,6 +325,13 @@ and .Ic Loc-RIB , which are created automatically and used by default. .Pp +.It Ic rde rib Loc-RIB include filtered +Include filtered prefixes in the +.Ic Loc-RIB . +Filtered prefixes are not eligible by the decision process but can be +displayed by +.Xr bgpctl 8 . +.Pp .It Xo .Ic rde .Ic route-age diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index a4d2a106b7d..78e245b5d26 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bgpd.h,v 1.494 2024/08/12 09:04:23 claudio Exp $ */ +/* $OpenBSD: bgpd.h,v 1.495 2024/08/14 19:09:51 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -101,6 +101,7 @@ #define F_CTL_AVS_VALID 0x1000000 #define F_CTL_AVS_INVALID 0x2000000 #define F_CTL_AVS_UNKNOWN 0x4000000 +#define F_CTL_FILTERED 0x8000000 /* only set on requests */ #define F_CTL_SSV 0x80000000 /* only used by bgpctl */ #define CTASSERT(x) extern char _ctassert[(x) ? 1 : -1 ] \ @@ -317,6 +318,7 @@ struct bgpd_config { uint16_t min_holdtime; uint16_t connectretry; uint8_t fib_priority; + uint8_t filtered_in_locrib; }; extern int cmd_opts; @@ -888,6 +890,7 @@ struct ctl_neighbor { #define F_PREF_OTC_LEAK 0x080 #define F_PREF_ECMP 0x100 #define F_PREF_AS_WIDE 0x200 +#define F_PREF_FILTERED 0x400 struct ctl_show_rib { struct bgpd_addr true_nexthop; diff --git a/usr.sbin/bgpd/config.c b/usr.sbin/bgpd/config.c index 789431986b6..bf93a521beb 100644 --- a/usr.sbin/bgpd/config.c +++ b/usr.sbin/bgpd/config.c @@ -1,4 +1,4 @@ -/* $OpenBSD: config.c,v 1.109 2024/05/22 08:41:14 claudio Exp $ */ +/* $OpenBSD: config.c,v 1.110 2024/08/14 19:09:51 claudio Exp $ */ /* * Copyright (c) 2003, 2004, 2005 Henning Brauer @@ -87,6 +87,7 @@ copy_config(struct bgpd_config *to, struct bgpd_config *from) to->min_holdtime = from->min_holdtime; to->connectretry = from->connectretry; to->fib_priority = from->fib_priority; + to->filtered_in_locrib = from->filtered_in_locrib; } void diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index bffd40948ed..1621c8a1dff 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.464 2024/08/12 09:04:23 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.465 2024/08/14 19:09:51 claudio Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer @@ -250,7 +250,7 @@ typedef struct { %token SEND RECV PLUS POLICY ROLE %token DEMOTE ENFORCE NEIGHBORAS ASOVERRIDE REFLECTOR DEPEND DOWN %token DUMP IN OUT SOCKET RESTRICTED -%token LOG TRANSPARENT +%token LOG TRANSPARENT FILTERED %token TCP MD5SIG PASSWORD KEY TTLSECURITY %token ALLOW DENY MATCH %token QUICK @@ -941,6 +941,14 @@ conf_main : AS as4number { } free($3); } + | RDE RIB STRING INCLUDE FILTERED { + if (strcmp($3, "Loc-RIB") != 0) { + yyerror("include filtered only supported in " + "Loc-RIB"); + YYERROR; + } + conf->filtered_in_locrib = 1; + } | NEXTHOP QUALIFY VIA STRING { if (!strcmp($4, "bgp")) conf->flags |= BGPD_FLAG_NEXTHOP_BGP; @@ -3551,6 +3559,7 @@ lookup(char *s) { "ext-community", EXTCOMMUNITY}, { "fib-priority", FIBPRIORITY}, { "fib-update", FIBUPDATE}, + { "filtered", FILTERED}, { "flags", FLAGS}, { "flowspec", FLOWSPEC}, { "fragment", FRAGMENT}, diff --git a/usr.sbin/bgpd/printconf.c b/usr.sbin/bgpd/printconf.c index 13a73208cb4..8aeeeeeee65 100644 --- a/usr.sbin/bgpd/printconf.c +++ b/usr.sbin/bgpd/printconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: printconf.c,v 1.173 2024/05/22 08:41:14 claudio Exp $ */ +/* $OpenBSD: printconf.c,v 1.174 2024/08/14 19:09:51 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -1276,6 +1276,8 @@ print_config(struct bgpd_config *conf, struct rib_names *rib_l) SIMPLEQ_FOREACH(vpn, &conf->l3vpns, entry) print_l3vpn(vpn); printf("\n"); + if (conf->filtered_in_locrib) + printf("rde rib Loc-RIB include filtered\n"); SIMPLEQ_FOREACH(rr, rib_l, entry) { if (rr->flags & F_RIB_NOEVALUATE) printf("rde rib %s no evaluate\n", rr->name); diff --git a/usr.sbin/bgpd/rde.c b/usr.sbin/bgpd/rde.c index 558d851f581..c4c286e4f29 100644 --- a/usr.sbin/bgpd/rde.c +++ b/usr.sbin/bgpd/rde.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.c,v 1.625 2024/05/22 08:41:14 claudio Exp $ */ +/* $OpenBSD: rde.c,v 1.626 2024/08/14 19:09:51 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -1854,7 +1854,7 @@ rde_update_update(struct rde_peer *peer, uint32_t path_id, path_id_tx = pathid_assign(peer, path_id, prefix, prefixlen); /* add original path to the Adj-RIB-In */ if (prefix_update(rib_byid(RIB_ADJ_IN), peer, path_id, path_id_tx, - in, prefix, prefixlen) == 1) + in, 0, prefix, prefixlen) == 1) peer->stats.prefix_cnt++; /* max prefix checker */ @@ -1883,11 +1883,16 @@ rde_update_update(struct rde_peer *peer, uint32_t path_id, &state.nexthop->exit_nexthop, prefix, prefixlen); prefix_update(rib, peer, path_id, path_id_tx, &state, - prefix, prefixlen); - } else if (prefix_withdraw(rib, peer, path_id, prefix, - prefixlen)) { - rde_update_log(wmsg, i, peer, - NULL, prefix, prefixlen); + 0, prefix, prefixlen); + } else if (conf->filtered_in_locrib && i == RIB_LOC_START) { + rde_update_log(wmsg, i, peer, NULL, prefix, prefixlen); + prefix_update(rib, peer, path_id, path_id_tx, &state, + 1, prefix, prefixlen); + } else { + if (prefix_withdraw(rib, peer, path_id, prefix, + prefixlen)) + rde_update_log(wmsg, i, peer, + NULL, prefix, prefixlen); } rde_filterstate_clean(&state); @@ -2738,7 +2743,7 @@ rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags, rib.aspa_validation_state = prefix_aspa_vstate(p); rib.dmetric = p->dmetric; rib.flags = 0; - if (!adjout) { + if (!adjout && prefix_eligible(p)) { re = prefix_re(p); TAILQ_FOREACH(xp, &re->prefix_h, entry.list.rib) { switch (xp->dmetric) { @@ -2768,6 +2773,8 @@ rde_dump_rib_as(struct prefix *p, struct rde_aspath *asp, pid_t pid, int flags, rib.flags |= F_PREF_ANNOUNCE; if (prefix_eligible(p)) rib.flags |= F_PREF_ELIGIBLE; + if (prefix_filtered(p)) + rib.flags |= F_PREF_FILTERED; /* otc loop includes parse err so skip the latter if the first is set */ if (asp->flags & F_ATTR_OTC_LEAK) rib.flags |= F_PREF_OTC_LEAK; @@ -2854,6 +2861,8 @@ rde_dump_filter(struct prefix *p, struct ctl_show_rib_request *req, int adjout) if ((req->flags & F_CTL_INVALID) && (asp->flags & F_ATTR_PARSE_ERR) == 0) return; + if ((req->flags & F_CTL_FILTERED) && !prefix_filtered(p)) + return; if ((req->flags & F_CTL_INELIGIBLE) && prefix_eligible(p)) return; if ((req->flags & F_CTL_LEAKED) && @@ -3557,7 +3566,7 @@ rde_reload_done(void) struct rde_prefixset_head originsets_old; struct as_set_head as_sets_old; uint16_t rid; - int reload = 0; + int reload = 0, force_locrib = 0; softreconfig = 0; @@ -3568,6 +3577,12 @@ rde_reload_done(void) SIMPLEQ_CONCAT(&originsets_old, &conf->rde_originsets); SIMPLEQ_CONCAT(&as_sets_old, &conf->as_sets); + /* run softreconfig in if filter mode changed */ + if (conf->filtered_in_locrib != nconf->filtered_in_locrib) { + log_debug("filter mode changed, reloading Loc-Rib"); + force_locrib = 1; + } + /* merge the main config */ copy_config(conf, nconf); @@ -3688,7 +3703,7 @@ rde_reload_done(void) } /* bring ribs in sync */ - for (rid = 0; rid < rib_size; rid++) { + for (rid = RIB_LOC_START; rid < rib_size; rid++) { struct rib *rib = rib_byid(rid); if (rib == NULL) continue; @@ -3734,10 +3749,11 @@ rde_reload_done(void) rib->state = RECONF_KEEP; /* FALLTHROUGH */ case RECONF_KEEP: - if (rde_filter_equal(rib->in_rules, rib->in_rules_tmp)) + if (!(force_locrib && rid == RIB_LOC_START) && + rde_filter_equal(rib->in_rules, rib->in_rules_tmp)) /* rib is in sync */ break; - log_debug("in filter change: reloading RIB %s", + log_debug("filter change: reloading RIB %s", rib->name); rib->state = RECONF_RELOAD; reload++; @@ -3935,9 +3951,14 @@ rde_softreconfig_in(struct rib_entry *re, void *bula) if (action == ACTION_ALLOW) { /* update Local-RIB */ prefix_update(rib, peer, p->path_id, - p->path_id_tx, &state, + p->path_id_tx, &state, 0, &prefix, pt->prefixlen); - } else if (action == ACTION_DENY) { + } else if (conf->filtered_in_locrib && + i == RIB_LOC_START) { + prefix_update(rib, peer, p->path_id, + p->path_id_tx, &state, 1, + &prefix, pt->prefixlen); + } else { /* remove from Local-RIB */ prefix_withdraw(rib, peer, p->path_id, &prefix, pt->prefixlen); @@ -4084,9 +4105,14 @@ rde_rpki_softreload(struct rib_entry *re, void *bula) if (action == ACTION_ALLOW) { /* update Local-RIB */ prefix_update(rib, peer, p->path_id, - p->path_id_tx, &state, + p->path_id_tx, &state, 0, + &prefix, pt->prefixlen); + } else if (conf->filtered_in_locrib && + i == RIB_LOC_START) { + prefix_update(rib, peer, p->path_id, + p->path_id_tx, &state, 1, &prefix, pt->prefixlen); - } else if (action == ACTION_DENY) { + } else { /* remove from Local-RIB */ prefix_withdraw(rib, peer, p->path_id, &prefix, pt->prefixlen); @@ -4365,7 +4391,7 @@ network_add(struct network_config *nc, struct filterstate *state) path_id_tx = pathid_assign(peerself, 0, &nc->prefix, nc->prefixlen); if (prefix_update(rib_byid(RIB_ADJ_IN), peerself, 0, path_id_tx, - state, &nc->prefix, nc->prefixlen) == 1) + state, 0, &nc->prefix, nc->prefixlen) == 1) peerself->stats.prefix_cnt++; for (i = RIB_LOC_START; i < rib_size; i++) { struct rib *rib = rib_byid(i); @@ -4374,8 +4400,8 @@ network_add(struct network_config *nc, struct filterstate *state) rde_update_log("announce", i, peerself, state->nexthop ? &state->nexthop->exit_nexthop : NULL, &nc->prefix, nc->prefixlen); - prefix_update(rib, peerself, 0, path_id_tx, state, &nc->prefix, - nc->prefixlen); + prefix_update(rib, peerself, 0, path_id_tx, state, 0, + &nc->prefix, nc->prefixlen); } filterset_free(&nc->attrset); } diff --git a/usr.sbin/bgpd/rde.h b/usr.sbin/bgpd/rde.h index 5be48fd4cf6..899833da05f 100644 --- a/usr.sbin/bgpd/rde.h +++ b/usr.sbin/bgpd/rde.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rde.h,v 1.303 2024/05/29 10:36:32 claudio Exp $ */ +/* $OpenBSD: rde.h,v 1.304 2024/08/14 19:09:51 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker and @@ -281,19 +281,21 @@ struct prefix { time_t lastchange; uint32_t path_id; uint32_t path_id_tx; + uint16_t flags; uint8_t validation_state; uint8_t nhflags; int8_t dmetric; /* decision metric */ - uint8_t flags; -#define PREFIX_FLAG_WITHDRAW 0x01 /* enqueued on withdraw queue */ -#define PREFIX_FLAG_UPDATE 0x02 /* enqueued on update queue */ -#define PREFIX_FLAG_DEAD 0x04 /* locked but removed */ -#define PREFIX_FLAG_STALE 0x08 /* stale entry (graceful reload) */ -#define PREFIX_FLAG_MASK 0x0f /* mask for the prefix types */ -#define PREFIX_FLAG_ADJOUT 0x10 /* prefix is in the adj-out rib */ -#define PREFIX_FLAG_EOR 0x20 /* prefix is EoR */ -#define PREFIX_NEXTHOP_LINKED 0x40 /* prefix is linked onto nexthop list */ -#define PREFIX_FLAG_LOCKED 0x80 /* locked by rib walker */ +}; +#define PREFIX_FLAG_WITHDRAW 0x0001 /* enqueued on withdraw queue */ +#define PREFIX_FLAG_UPDATE 0x0002 /* enqueued on update queue */ +#define PREFIX_FLAG_DEAD 0x0004 /* locked but removed */ +#define PREFIX_FLAG_STALE 0x0008 /* stale entry (graceful reload) */ +#define PREFIX_FLAG_MASK 0x000f /* mask for the prefix types */ +#define PREFIX_FLAG_ADJOUT 0x0010 /* prefix is in the adj-out rib */ +#define PREFIX_FLAG_EOR 0x0020 /* prefix is EoR */ +#define PREFIX_NEXTHOP_LINKED 0x0040 /* prefix is linked onto nexthop list */ +#define PREFIX_FLAG_LOCKED 0x0080 /* locked by rib walker */ +#define PREFIX_FLAG_FILTERED 0x0100 /* prefix is filtered (ineligible) */ #define PREFIX_DMETRIC_NONE 0 #define PREFIX_DMETRIC_INVALID 1 @@ -301,7 +303,6 @@ struct prefix { #define PREFIX_DMETRIC_AS_WIDE 3 #define PREFIX_DMETRIC_ECMP 4 #define PREFIX_DMETRIC_BEST 5 -}; /* possible states for nhflags */ #define NEXTHOP_SELF 0x01 @@ -579,7 +580,8 @@ struct prefix *prefix_adjout_lookup(struct rde_peer *, struct bgpd_addr *, int); struct prefix *prefix_adjout_match(struct rde_peer *, struct bgpd_addr *); int prefix_update(struct rib *, struct rde_peer *, uint32_t, - uint32_t, struct filterstate *, struct bgpd_addr *, int); + uint32_t, struct filterstate *, int, struct bgpd_addr *, + int); int prefix_withdraw(struct rib *, struct rde_peer *, uint32_t, struct bgpd_addr *, int); int prefix_flowspec_update(struct rde_peer *, struct filterstate *, @@ -669,6 +671,12 @@ prefix_re(struct prefix *p) return (p->entry.list.re); } +static inline int +prefix_filtered(struct prefix *p) +{ + return ((p->flags & PREFIX_FLAG_FILTERED) != 0); +} + void nexthop_shutdown(void); int nexthop_pending(void); void nexthop_runner(void); diff --git a/usr.sbin/bgpd/rde_decide.c b/usr.sbin/bgpd/rde_decide.c index 5ebe4050d08..2697f06dfc5 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.102 2023/10/12 14:22:08 claudio Exp $ */ +/* $OpenBSD: rde_decide.c,v 1.103 2024/08/14 19:09:51 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker @@ -486,6 +486,10 @@ prefix_eligible(struct prefix *p) { struct rde_aspath *asp = prefix_aspath(p); + /* prefix itself is marked ineligible */ + if (prefix_filtered(p)) + return 0; + /* The aspath needs to be loop and error free */ if (asp == NULL || asp->flags & (F_ATTR_LOOP|F_ATTR_OTC_LEAK|F_ATTR_PARSE_ERR)) diff --git a/usr.sbin/bgpd/rde_rib.c b/usr.sbin/bgpd/rde_rib.c index 3caaa3e9e65..d595a0e2f1a 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.262 2024/05/29 10:34:56 claudio Exp $ */ +/* $OpenBSD: rde_rib.c,v 1.263 2024/08/14 19:09:51 claudio Exp $ */ /* * Copyright (c) 2003, 2004 Claudio Jeker @@ -801,10 +801,10 @@ path_put(struct rde_aspath *asp) static int prefix_add(struct bgpd_addr *, int, struct rib *, struct rde_peer *, uint32_t, uint32_t, struct rde_aspath *, struct rde_community *, struct nexthop *, - uint8_t, uint8_t); + uint8_t, uint8_t, int); static int prefix_move(struct prefix *, struct rde_peer *, struct rde_aspath *, struct rde_community *, - struct nexthop *, uint8_t, uint8_t); + struct nexthop *, uint8_t, uint8_t, int); static void prefix_link(struct prefix *, struct rib_entry *, struct pt_entry *, struct rde_peer *, uint32_t, uint32_t, @@ -967,8 +967,8 @@ prefix_adjout_match(struct rde_peer *peer, struct bgpd_addr *addr) */ int prefix_update(struct rib *rib, struct rde_peer *peer, uint32_t path_id, - uint32_t path_id_tx, struct filterstate *state, struct bgpd_addr *prefix, - int prefixlen) + uint32_t path_id_tx, struct filterstate *state, int filtered, + struct bgpd_addr *prefix, int prefixlen) { struct rde_aspath *asp, *nasp = &state->aspath; struct rde_community *comm, *ncomm = &state->communities; @@ -987,6 +987,10 @@ prefix_update(struct rib *rib, struct rde_peer *peer, uint32_t path_id, /* no change, update last change */ p->lastchange = getmonotime(); p->validation_state = state->vstate; + if (filtered) + p->flags |= PREFIX_FLAG_FILTERED; + else + p->flags &= ~PREFIX_FLAG_FILTERED; return (0); } } @@ -1010,11 +1014,11 @@ prefix_update(struct rib *rib, struct rde_peer *peer, uint32_t path_id, /* If the prefix was found move it else add it to the RIB. */ if (p != NULL) return (prefix_move(p, peer, asp, comm, state->nexthop, - state->nhflags, state->vstate)); + state->nhflags, state->vstate, filtered)); else return (prefix_add(prefix, prefixlen, rib, peer, path_id, path_id_tx, asp, comm, state->nexthop, state->nhflags, - state->vstate)); + state->vstate, filtered)); } /* @@ -1024,7 +1028,7 @@ static int prefix_add(struct bgpd_addr *prefix, int prefixlen, struct rib *rib, struct rde_peer *peer, uint32_t path_id, uint32_t path_id_tx, struct rde_aspath *asp, struct rde_community *comm, - struct nexthop *nexthop, uint8_t nhflags, uint8_t vstate) + struct nexthop *nexthop, uint8_t nhflags, uint8_t vstate, int filtered) { struct pt_entry *pte; struct prefix *p; @@ -1041,6 +1045,9 @@ prefix_add(struct bgpd_addr *prefix, int prefixlen, struct rib *rib, prefix_link(p, re, re->prefix, peer, path_id, path_id_tx, asp, comm, nexthop, nhflags, vstate); + if (filtered) + p->flags |= PREFIX_FLAG_FILTERED; + /* add possible pftable reference form aspath */ if (asp && asp->pftableid) rde_pftable_add(asp->pftableid, p); @@ -1055,7 +1062,7 @@ prefix_add(struct bgpd_addr *prefix, int prefixlen, struct rib *rib, static int prefix_move(struct prefix *p, struct rde_peer *peer, struct rde_aspath *asp, struct rde_community *comm, - struct nexthop *nexthop, uint8_t nhflags, uint8_t vstate) + struct nexthop *nexthop, uint8_t nhflags, uint8_t vstate, int filtered) { struct prefix *np; @@ -1070,6 +1077,9 @@ prefix_move(struct prefix *p, struct rde_peer *peer, prefix_link(np, prefix_re(p), p->pt, peer, p->path_id, p->path_id_tx, asp, comm, nexthop, nhflags, vstate); + if (filtered) + np->flags |= PREFIX_FLAG_FILTERED; + /* add possible pftable reference from new aspath */ if (asp && asp->pftableid) rde_pftable_add(asp->pftableid, np); -- 2.20.1