When adding the filterstate to rde_filter I also passed a struct prefix pointer to rde_filter instead of passing the 4 values. This resulted in some ugly hacks because in some cases there was no prefix handy to pass in and while working on RIB pipelines I noticed that this is hurting me again. So time to change it and just pass the prefix_peer, prefix_vstate and the prefix addr/len right into rde_filter(). While there I also reordered the args to rde_attr_set() to match rde_filter(). This is mostly a mechanical change.
OK? -- :wq Claudio Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.484 diff -u -p -r1.484 rde.c --- rde.c 9 Aug 2019 13:44:27 -0000 1.484 +++ rde.c 13 Aug 2019 07:50:31 -0000 @@ -1402,7 +1402,6 @@ rde_update_update(struct rde_peer *peer, struct bgpd_addr *prefix, u_int8_t prefixlen) { struct filterstate state; - struct prefix *p; enum filter_actions action; u_int8_t vstate; u_int16_t i; @@ -1428,17 +1427,14 @@ rde_update_update(struct rde_peer *peer, if (in->aspath.flags & F_ATTR_PARSE_ERR) wmsg = "path invalid, withdraw"; - p = prefix_get(&ribs[RIB_ADJ_IN].rib, peer, prefix, prefixlen); - if (p == NULL) - fatalx("rde_update_update: no prefix in Adj-RIB-In"); - for (i = RIB_LOC_START; i < rib_size; i++) { if (!rib_valid(i)) continue; rde_filterstate_prep(&state, &in->aspath, &in->communities, in->nexthop, in->nhflags); /* input filter */ - action = rde_filter(ribs[i].in_rules, peer, p, &state); + action = rde_filter(ribs[i].in_rules, peer, peer, prefix, + prefixlen, vstate, &state); if (action == ACTION_ALLOW) { rde_update_log("update", i, peer, @@ -3327,7 +3323,8 @@ rde_softreconfig_in(struct rib_entry *re rde_filterstate_prep(&state, asp, prefix_communities(p), prefix_nexthop(p), prefix_nhflags(p)); - action = rde_filter(rib->in_rules, peer, p, &state); + action = rde_filter(rib->in_rules, peer, peer, &prefix, + pt->prefixlen, p->validation_state, &state); if (action == ACTION_ALLOW) { /* update Local-RIB */ @@ -3959,10 +3956,10 @@ network_add(struct network_config *nc, s } } - rde_apply_set(&nc->attrset, state, nc->prefix.aid, peerself, peerself); + rde_apply_set(&nc->attrset, peerself, peerself, state, nc->prefix.aid); if (vpnset) - rde_apply_set(vpnset, state, nc->prefix.aid, peerself, - peerself); + rde_apply_set(vpnset, peerself, peerself, state, + nc->prefix.aid); vstate = rde_roa_validity(&conf->rde_roa, &nc->prefix, nc->prefixlen, aspath_origin(state->aspath.aspath)); Index: rde.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v retrieving revision 1.223 diff -u -p -r1.223 rde.h --- rde.h 9 Aug 2019 13:44:27 -0000 1.223 +++ rde.h 12 Aug 2019 14:46:38 -0000 @@ -464,16 +464,17 @@ int community_to_rd(struct community *, void prefix_evaluate(struct prefix *, struct rib_entry *); /* rde_filter.c */ -void rde_filterstate_prep(struct filterstate *, struct rde_aspath *, - struct rde_community *, struct nexthop *, u_int8_t); -void rde_filterstate_clean(struct filterstate *); +void rde_apply_set(struct filter_set_head *, struct rde_peer *, + struct rde_peer *, struct filterstate *, u_int8_t); +void rde_filterstate_prep(struct filterstate *, struct rde_aspath *, + struct rde_community *, struct nexthop *, u_int8_t); +void rde_filterstate_clean(struct filterstate *); +int rde_filter_equal(struct filter_head *, struct filter_head *, + struct rde_peer *); +void rde_filter_calc_skip_steps(struct filter_head *); enum filter_actions rde_filter(struct filter_head *, struct rde_peer *, - struct prefix *, struct filterstate *); -void rde_apply_set(struct filter_set_head *, struct filterstate *, - u_int8_t, struct rde_peer *, struct rde_peer *); -int rde_filter_equal(struct filter_head *, struct filter_head *, - struct rde_peer *); -void rde_filter_calc_skip_steps(struct filter_head *); + struct rde_peer *, struct bgpd_addr *, u_int8_t, u_int8_t, + struct filterstate *); /* rde_prefix.c */ void pt_init(void); Index: rde_filter.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_filter.c,v retrieving revision 1.121 diff -u -p -r1.121 rde_filter.c --- rde_filter.c 1 Jul 2019 07:07:08 -0000 1.121 +++ rde_filter.c 12 Aug 2019 14:43:57 -0000 @@ -29,14 +29,11 @@ #include "rde.h" #include "log.h" -int rde_filter_match(struct filter_rule *, struct rde_peer *, - struct filterstate *, struct prefix *); -int rde_prefix_match(struct filter_prefix *, struct prefix *); int filterset_equal(struct filter_set_head *, struct filter_set_head *); void -rde_apply_set(struct filter_set_head *sh, struct filterstate *state, - u_int8_t aid, struct rde_peer *from, struct rde_peer *peer) +rde_apply_set(struct filter_set_head *sh, struct rde_peer *peer, + struct rde_peer *from, struct filterstate *state, u_int8_t aid) { struct filter_set *set; u_char *np; @@ -178,9 +175,42 @@ rde_apply_set(struct filter_set_head *sh } } -int +/* return 1 when prefix matches filter_prefix, 0 if not */ +static int +rde_prefix_match(struct filter_prefix *fp, struct bgpd_addr *prefix, + u_int8_t plen) +{ + if (fp->addr.aid != prefix->aid) + /* don't use IPv4 rules for IPv6 and vice versa */ + return (0); + + if (prefix_compare(prefix, &fp->addr, fp->len)) + return (0); + + /* test prefixlen stuff too */ + switch (fp->op) { + case OP_NONE: /* perfect match */ + return (plen == fp->len); + case OP_EQ: + return (plen == fp->len_min); + case OP_NE: + return (plen != fp->len_min); + case OP_RANGE: + return ((plen >= fp->len_min) && + (plen <= fp->len_max)); + case OP_XRANGE: + return ((plen < fp->len_min) || + (plen > fp->len_max)); + default: + log_warnx("%s: unsupported prefix operation", __func__); + return (0); + } +} + +static int rde_filter_match(struct filter_rule *f, struct rde_peer *peer, - struct filterstate *state, struct prefix *p) + struct rde_peer *from, struct filterstate *state, + struct bgpd_addr *prefix, u_int8_t plen, u_int8_t vstate) { struct rde_aspath *asp = &state->aspath; int i; @@ -191,7 +221,7 @@ rde_filter_match(struct filter_rule *f, return (0); if (f->match.ovs.is_set) { - if (prefix_vstate(p) != f->match.ovs.validity) + if (vstate != f->match.ovs.validity) return (0); } @@ -223,7 +253,7 @@ rde_filter_match(struct filter_rule *f, if (f->match.nexthop.flags == FILTER_NEXTHOP_ADDR) cmpaddr = &f->match.nexthop.addr; else - cmpaddr = &prefix_peer(p)->remote_addr; + cmpaddr = &from->remote_addr; if (cmpaddr->aid != nexthop->aid) /* don't use IPv4 rules for IPv6 and vice versa */ return (0); @@ -245,11 +275,6 @@ rde_filter_match(struct filter_rule *f, /* origin-set lookups match only on ROA_VALID */ if (asp != NULL && f->match.originset.ps != NULL) { - struct bgpd_addr addr, *prefix = &addr; - u_int8_t plen; - - pt_getaddr(p->pt, prefix); - plen = p->pt->prefixlen; if (trie_roa_check(&f->match.originset.ps->th, prefix, plen, aspath_origin(asp->aspath)) != ROA_VALID) return (0); @@ -259,59 +284,17 @@ rde_filter_match(struct filter_rule *f, * prefixset and prefix filter rules are mutual exclusive */ if (f->match.prefixset.flags != 0) { - struct bgpd_addr addr, *prefix = &addr; - u_int8_t plen; - - pt_getaddr(p->pt, prefix); - plen = p->pt->prefixlen; if (f->match.prefixset.ps == NULL || !trie_match(&f->match.prefixset.ps->th, prefix, plen, (f->match.prefixset.flags & PREFIXSET_FLAG_LONGER))) return (0); } else if (f->match.prefix.addr.aid != 0) - return (rde_prefix_match(&f->match.prefix, p)); + return (rde_prefix_match(&f->match.prefix, prefix, plen)); /* matched somewhen or is anymatch rule */ return (1); } -/* return 1 when prefix matches filter_prefix, 0 if not */ -int -rde_prefix_match(struct filter_prefix *fp, struct prefix *p) -{ - struct bgpd_addr addr, *prefix = &addr; - u_int8_t plen; - - pt_getaddr(p->pt, prefix); - plen = p->pt->prefixlen; - - if (fp->addr.aid != prefix->aid) - /* don't use IPv4 rules for IPv6 and vice versa */ - return (0); - - if (prefix_compare(prefix, &fp->addr, fp->len)) - return (0); - - /* test prefixlen stuff too */ - switch (fp->op) { - case OP_NONE: /* perfect match */ - return (plen == fp->len); - case OP_EQ: - return (plen == fp->len_min); - case OP_NE: - return (plen != fp->len_min); - case OP_RANGE: - return ((plen >= fp->len_min) && - (plen <= fp->len_max)); - case OP_XRANGE: - return ((plen < fp->len_min) || - (plen > fp->len_max)); - default: - log_warnx("%s: unsupported prefix operation", __func__); - return (0); - } -} - /* return true when the rule f can never match for this peer */ static int rde_filter_skip_rule(struct rde_peer *peer, struct filter_rule *f) @@ -753,7 +736,8 @@ rde_filter_calc_skip_steps(struct filter enum filter_actions rde_filter(struct filter_head *rules, struct rde_peer *peer, - struct prefix *p, struct filterstate *state) + struct rde_peer *from, struct bgpd_addr *prefix, u_int8_t plen, + u_int8_t vstate, struct filterstate *state) { struct filter_rule *f; enum filter_actions action = ACTION_DENY; /* default deny */ @@ -783,9 +767,9 @@ rde_filter(struct filter_head *rules, st f->peer.peerid != peer->conf.id), f->skip[RDE_FILTER_SKIP_PEERID]); - if (rde_filter_match(f, peer, state, p)) { - rde_apply_set(&f->set, state, p->pt->aid, - prefix_peer(p), peer); + if (rde_filter_match(f, peer, from, state, prefix, plen, + vstate)) { + rde_apply_set(&f->set, peer, from, state, prefix->aid); if (f->action != ACTION_NONE) action = f->action; if (f->quick) Index: rde_update.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_update.c,v retrieving revision 1.121 diff -u -p -r1.121 rde_update.c --- rde_update.c 9 Aug 2019 13:44:27 -0000 1.121 +++ rde_update.c 12 Aug 2019 14:56:44 -0000 @@ -159,13 +159,14 @@ withdraw: rde_filterstate_prep(&state, prefix_aspath(new), prefix_communities(new), prefix_nexthop(new), prefix_nhflags(new)); - if (rde_filter(rules, peer, new, &state) == ACTION_DENY) { + pt_getaddr(new->pt, &addr); + if (rde_filter(rules, peer, prefix_peer(new), &addr, + new->pt->prefixlen, prefix_vstate(new), &state) == + ACTION_DENY) { rde_filterstate_clean(&state); goto withdraw; } - pt_getaddr(new->pt, &addr); - /* only send update if path changed */ if (prefix_adjout_update(peer, &state, &addr, new->pt->prefixlen, prefix_vstate(new)) == 1) @@ -184,10 +185,9 @@ void up_generate_default(struct filter_head *rules, struct rde_peer *peer, u_int8_t aid) { + extern struct rde_peer *peerself; struct filterstate state; struct rde_aspath *asp; - struct prefix p; - struct pt_entry *pte; struct bgpd_addr addr; if (peer->capa.mp[aid] == 0) @@ -203,26 +203,13 @@ up_generate_default(struct filter_head * * XXX apply default overrides. Not yet possible, mainly a parse.y * problem. */ - /* rde_apply_set(asp, set, af, &state, DIR_IN); */ + /* rde_apply_set(asp, peerself, peerself, set, af); */ - /* - * XXX this is ugly because we need to have a prefix for rde_filter() - * but it will be added after filtering. So fake it till we make it. - * rde_filter() only accesses prefix_peer(), prefix_vstate() and the - * pt pointer. - */ - bzero(&p, sizeof(p)); bzero(&addr, sizeof(addr)); addr.aid = aid; - pte = pt_get(&addr, 0); - if (pte == NULL) - pte = pt_add(&addr, 0); - p.pt = pt_ref(pte); - p.validation_state = ROA_NOTFOUND; - p.peer = peer; /* XXX should be peerself */ - /* outbound filter as usual */ - if (rde_filter(rules, peer, &p, &state) == ACTION_DENY) { + if (rde_filter(rules, peer, peerself, &addr, 0, ROA_NOTFOUND, + &state) == ACTION_DENY) { rde_filterstate_clean(&state); return; } @@ -232,8 +219,6 @@ up_generate_default(struct filter_head * /* no longer needed */ rde_filterstate_clean(&state); - - pt_unref(pte); } /* only for IPv4 */