My plan is to make struct prefix the main object that holds references to
aspath, nexthop and rib. This diff is the next little step towards that.

Pass a struct prefix to rde_filter and remove some of the arguments which
are now fetched from struct prefix. Currently some trickery is needed
for export default-route but this will get better once Adj-RIB-Out comes.

Please test and review
-- 
:wq Claudio

Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.381
diff -u -p -r1.381 rde.c
--- rde.c       25 Jun 2018 14:28:33 -0000      1.381
+++ rde.c       27 Jun 2018 13:18:01 -0000
@@ -1364,6 +1364,7 @@ rde_update_update(struct rde_peer *peer,
     struct bgpd_addr *prefix, u_int8_t prefixlen)
 {
        struct rde_aspath       *fasp;
+       struct prefix           *p;
        enum filter_actions      action;
        u_int16_t                i;
 
@@ -1372,12 +1373,15 @@ rde_update_update(struct rde_peer *peer,
        if (path_update(&ribs[RIB_ADJ_IN].rib, peer, asp, prefix, prefixlen, 0))
                peer->prefix_cnt++;
 
+       p = prefix_get(&ribs[RIB_ADJ_IN].rib, peer, prefix, prefixlen, 0);
+       if (p == NULL)
+               fatalx("rde_update_update: no prefix in Adj-RIB-In");
+
        for (i = RIB_LOC_START; i < rib_size; i++) {
                if (*ribs[i].name == '\0')
                        break;
                /* input filter */
-               action = rde_filter(ribs[i].in_rules, &fasp, peer, asp, prefix,
-                   prefixlen, peer);
+               action = rde_filter(ribs[i].in_rules, peer, &fasp, p, asp);
 
                if (fasp == NULL)
                        fasp = asp;
@@ -2303,8 +2307,7 @@ rde_dump_filterout(struct rde_peer *peer
 
        pt_getaddr(p->re->prefix, &addr);
        asp = prefix_aspath(p);
-       a = rde_filter(out_rules, &fasp, peer, asp, &addr,
-           p->re->prefix->prefixlen, asp->peer);
+       a = rde_filter(out_rules, peer, &fasp, p, asp);
        if (fasp)
                fasp->peer = asp->peer;
        else
@@ -3064,16 +3067,14 @@ rde_softreconfig_in(struct rib_entry *re
 
                /* check if prefix changed */
                if (rib->state == RECONF_RELOAD) {
-                       oa = rde_filter(rib->in_rules_tmp, &oasp, peer,
-                           asp, &addr, pt->prefixlen, peer);
+                       oa = rde_filter(rib->in_rules_tmp, peer, &oasp, p, asp);
                        oasp = oasp != NULL ? oasp : asp;
                } else {
                        /* make sure we update everything for RECONF_REINIT */
                        oa = ACTION_DENY;
                        oasp = asp;
                }
-               na = rde_filter(rib->in_rules, &nasp, peer, asp,
-                   &addr, pt->prefixlen, peer);
+               na = rde_filter(rib->in_rules, peer, &nasp, p, asp);
                nasp = nasp != NULL ? nasp : asp;
 
                /* go through all 4 possible combinations */
@@ -3122,10 +3123,8 @@ rde_softreconfig_out(struct rib_entry *r
        if (up_test_update(peer, p) != 1)
                return;
 
-       oa = rde_filter(out_rules_tmp, &oasp, peer, prefix_aspath(p),
-           &addr, pt->prefixlen, prefix_peer(p));
-       na = rde_filter(out_rules, &nasp, peer, prefix_aspath(p),
-           &addr, pt->prefixlen, prefix_peer(p));
+       oa = rde_filter(out_rules_tmp, peer, &oasp, p, prefix_aspath(p));
+       na = rde_filter(out_rules, peer, &nasp, p, prefix_aspath(p));
        oasp = oasp != NULL ? oasp : prefix_aspath(p);
        nasp = nasp != NULL ? nasp : prefix_aspath(p);
 
@@ -3167,8 +3166,7 @@ rde_softreconfig_unload_peer(struct rib_
        if (up_test_update(peer, p) != 1)
                return;
 
-       oa = rde_filter(out_rules_tmp, &oasp, peer, prefix_aspath(p),
-           &addr, pt->prefixlen, prefix_peer(p));
+       oa = rde_filter(out_rules_tmp, peer, &oasp, p, prefix_aspath(p));
        oasp = oasp != NULL ? oasp : prefix_aspath(p);
 
        if (oa == ACTION_DENY)
@@ -3648,9 +3646,9 @@ network_add(struct network_config *nc, i
        }
        if (!flagstatic)
                asp->flags |= F_ANN_DYNAMIC;
-       rde_apply_set(asp, &nc->attrset, nc->prefix.aid, peerself, peerself);
+       rde_apply_set(&nc->attrset, asp, nc->prefix.aid, peerself, peerself);
        if (vpnset)
-               rde_apply_set(asp, vpnset, nc->prefix.aid, peerself, peerself);
+               rde_apply_set(vpnset, asp, nc->prefix.aid, peerself, peerself);
        for (i = RIB_LOC_START; i < rib_size; i++) {
                if (*ribs[i].name == '\0')
                        break;
Index: rde.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
retrieving revision 1.171
diff -u -p -r1.171 rde.h
--- rde.h       27 Jun 2018 13:14:44 -0000      1.171
+++ rde.h       27 Jun 2018 13:20:17 -0000
@@ -402,10 +402,10 @@ u_char            *community_ext_delete_non_trans(
 void            prefix_evaluate(struct prefix *, struct rib_entry *);
 
 /* rde_filter.c */
-enum filter_actions rde_filter(struct filter_head *, struct rde_aspath **,
-                    struct rde_peer *, struct rde_aspath *,
-                    struct bgpd_addr *, u_int8_t, struct rde_peer *);
-void            rde_apply_set(struct rde_aspath *, struct filter_set_head *,
+enum filter_actions rde_filter(struct filter_head *, struct rde_peer *,
+                    struct rde_aspath **, struct prefix *,
+                    struct rde_aspath *);
+void            rde_apply_set(struct filter_set_head *, struct rde_aspath *,
                     u_int8_t, struct rde_peer *, struct rde_peer *);
 int             rde_filter_equal(struct filter_head *, struct filter_head *,
                     struct rde_peer *, struct prefixset_head *);
@@ -479,6 +479,8 @@ 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_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, int);
Index: rde_filter.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_filter.c,v
retrieving revision 1.90
diff -u -p -r1.90 rde_filter.c
--- rde_filter.c        27 Jun 2018 11:06:49 -0000      1.90
+++ rde_filter.c        27 Jun 2018 11:34:07 -0000
@@ -29,13 +29,13 @@
 #include "rde.h"
 #include "log.h"
 
-int    rde_filter_match(struct filter_rule *, struct rde_aspath *,
-           struct bgpd_addr *, u_int8_t, struct rde_peer *, struct rde_peer *);
+int    rde_filter_match(struct filter_rule *, struct rde_peer *,
+           struct rde_aspath *, struct prefix *);
+int    rde_prefix_match(struct filter_prefix *, struct prefix *);
 int    filterset_equal(struct filter_set_head *, struct filter_set_head *);
-int    rde_test_prefix(struct filter_prefix *, struct bgpd_addr *, u_int8_t);
 
 void
-rde_apply_set(struct rde_aspath *asp, struct filter_set_head *sh,
+rde_apply_set(struct filter_set_head *sh, struct rde_aspath *asp,
     u_int8_t aid, struct rde_peer *from, struct rde_peer *peer)
 {
        struct filter_set       *set;
@@ -330,9 +330,8 @@ rde_apply_set(struct rde_aspath *asp, st
 }
 
 int
-rde_filter_match(struct filter_rule *f, struct rde_aspath *asp,
-    struct bgpd_addr *prefix, u_int8_t plen, struct rde_peer *peer,
-    struct rde_peer *from)
+rde_filter_match(struct filter_rule *f, struct rde_peer *peer,
+    struct rde_aspath *asp, struct prefix *p)
 {
        u_int32_t       pas;
        int             cas, type;
@@ -453,7 +452,7 @@ rde_filter_match(struct filter_rule *f, 
                if (f->match.nexthop.flags == FILTER_NEXTHOP_ADDR)
                        cmpaddr = &f->match.nexthop.addr;
                else
-                       cmpaddr = &from->remote_addr;
+                       cmpaddr = &prefix_peer(p)->remote_addr;
                if (cmpaddr->aid != nexthop->aid)
                        /* don't use IPv4 rules for IPv6 and vice versa */
                        return (0);
@@ -481,7 +480,7 @@ rde_filter_match(struct filter_rule *f, 
                log_debug("%s: processing filter for prefixset %s",
                    __func__, f->match.prefixset.name);
                SIMPLEQ_FOREACH(psi, &f->match.prefixset.ps->psitems, entry) {
-                       if (rde_test_prefix(&psi->p, prefix, plen)) {
+                       if (rde_prefix_match(&psi->p, p)) {
                                log_debug("%s: prefixset %s matched %s",
                                    __func__, f->match.prefixset.ps->name,
                                    log_addr(&psi->p.addr));
@@ -490,7 +489,7 @@ rde_filter_match(struct filter_rule *f, 
                }
                return (0);
        } else if (f->match.prefix.addr.aid != 0)
-               return (rde_test_prefix(&f->match.prefix, prefix, plen));
+               return (rde_prefix_match(&f->match.prefix, p));
 
        /* matched somewhen or is anymatch rule  */
        return (1);
@@ -498,9 +497,14 @@ rde_filter_match(struct filter_rule *f, 
 
 /* return 1 when prefix matches filter_prefix, 0 if not */
 int
-rde_test_prefix(struct filter_prefix *fp, struct bgpd_addr *prefix,
-    u_int8_t plen)
+rde_prefix_match(struct filter_prefix *fp, struct prefix *p)
 {
+       struct bgpd_addr addr, *prefix = &addr;
+       u_int8_t plen;
+
+       pt_getaddr(p->re->prefix, prefix);
+       plen = p->re->prefix->prefixlen;
+
        if (fp->addr.aid != prefix->aid)
                /* don't use IPv4 rules for IPv6 and vice versa */
                return (0);
@@ -976,9 +980,8 @@ rde_filter_calc_skip_steps(struct filter
        } while (0)
 
 enum filter_actions
-rde_filter(struct filter_head *rules, struct rde_aspath **new,
-    struct rde_peer *peer, struct rde_aspath *asp, struct bgpd_addr *prefix,
-    u_int8_t prefixlen, struct rde_peer *from)
+rde_filter(struct filter_head *rules, struct rde_peer *peer,
+    struct rde_aspath **new, struct prefix *p, struct rde_aspath *asp)
 {
        struct filter_rule      *f;
        enum filter_actions      action = ACTION_DENY; /* default deny */
@@ -1010,7 +1013,8 @@ rde_filter(struct filter_head *rules, st
                    (f->peer.peerid &&
                     f->peer.peerid != peer->conf.id),
                     f->skip[RDE_FILTER_SKIP_PEERID].ptr);
-               if (rde_filter_match(f, asp, prefix, prefixlen, peer, from)) {
+
+               if (rde_filter_match(f, peer, asp, p)) {
                        if (asp != NULL && new != NULL) {
                                /* asp may get modified so create a copy */
                                if (*new == NULL) {
@@ -1018,8 +1022,8 @@ rde_filter(struct filter_head *rules, st
                                        /* ... and use the copy from now on */
                                        asp = *new;
                                }
-                               rde_apply_set(asp, &f->set, prefix->aid,
-                                   from, peer);
+                               rde_apply_set(&f->set, asp, p->re->prefix->aid,
+                                   prefix_peer(p), peer);
                        }
                        if (f->action != ACTION_NONE)
                                action = f->action;
Index: rde_rib.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
retrieving revision 1.162
diff -u -p -r1.162 rde_rib.c
--- rde_rib.c   27 Jun 2018 13:14:44 -0000      1.162
+++ rde_rib.c   27 Jun 2018 13:19:44 -0000
@@ -47,8 +47,6 @@ struct rib_entry *rib_restart(struct rib
 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);
Index: rde_update.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_update.c,v
retrieving revision 1.91
diff -u -p -r1.91 rde_update.c
--- rde_update.c        26 Jun 2018 13:34:26 -0000      1.91
+++ rde_update.c        27 Jun 2018 14:46:31 -0000
@@ -411,8 +411,7 @@ withdraw:
 
                asp = prefix_aspath(old);
                pt_getaddr(old->re->prefix, &addr);
-               if (rde_filter(rules, NULL, peer, asp, &addr,
-                   old->re->prefix->prefixlen, asp->peer) == ACTION_DENY)
+               if (rde_filter(rules, peer, NULL, old, asp) == ACTION_DENY)
                        return;
 
                /* withdraw prefix */
@@ -429,8 +428,7 @@ withdraw:
 
                asp = prefix_aspath(new);
                pt_getaddr(new->re->prefix, &addr);
-               if (rde_filter(rules, &fasp, peer, asp, &addr,
-                   new->re->prefix->prefixlen, asp->peer) == ACTION_DENY) {
+               if (rde_filter(rules, peer, &fasp, new, asp) == ACTION_DENY) {
                        path_put(fasp);
                        goto withdraw;
                }
@@ -445,12 +443,18 @@ withdraw:
        }
 }
 
+struct rib_entry *rib_add(struct rib *, struct bgpd_addr *, int);
+void rib_remove(struct rib_entry *);
+int rib_empty(struct rib_entry *);
+
 /* send a default route to the specified peer */
 void
 up_generate_default(struct filter_head *rules, struct rde_peer *peer,
     u_int8_t aid)
 {
        struct rde_aspath       *asp, *fasp;
+       struct prefix            p;
+       struct rib_entry        *re;
        struct bgpd_addr         addr;
 
        if (peer->capa.mp[aid] == 0)
@@ -467,12 +471,23 @@ up_generate_default(struct filter_head *
         */
        /* rde_apply_set(asp, set, af, NULL ???, DIR_IN); */
 
-       /* filter as usual */
+       /*
+        * XXX this is ugly but it will get better once we have a proper
+        * Adj-RIB-Out. Since then this will be just inserted there.
+        */
+       bzero(&p, sizeof(p));
        bzero(&addr, sizeof(addr));
        addr.aid = aid;
+       re = rib_get(peer->rib, &addr, 0);
+       if (re == NULL)
+               re = rib_add(peer->rib, &addr, 0);
+       p.re = re;
+       p.aspath = asp;
+       p.peer = peer;
+       p.flags = 0;
 
-       if (rde_filter(rules, &fasp, peer, asp, &addr, 0, NULL) ==
-           ACTION_DENY) {
+       /* filter as usual */
+       if (rde_filter(rules, peer, &fasp, &p, asp) == ACTION_DENY) {
                path_put(fasp);
                path_put(asp);
                return;
@@ -487,6 +502,9 @@ up_generate_default(struct filter_head *
        if (fasp != asp)
                path_put(fasp);
        path_put(asp);
+
+       if (rib_empty(re))
+               rib_remove(re);
 }
 
 /* generate a EoR marker in the update list. This is a horrible hack. */

Reply via email to