bgpd rde_filter() change

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

bgpd rde_filter() change

Claudio Jeker
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 */