This changes the way filtersets are passed on config reloads (and also for
bgpctl network commands). Now the sets are sent first and then moved into
the object that follows the filter_set with TAILQ_CONCAT().
The benefit of this is that IMSG_RECONF_FILTER will have the full rule
ready when inserting it, allowing to build a per peer output filter.

The integration tests still pass and bgpctl network also works :)

OK?
-- 
:wq Claudio

Index: bgpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.c,v
retrieving revision 1.222
diff -u -p -r1.222 bgpd.c
--- bgpd.c      24 Jul 2019 20:25:27 -0000      1.222
+++ bgpd.c      24 Jul 2019 21:15:29 -0000
@@ -644,11 +644,11 @@ reconfigure(char *conffile, struct bgpd_
        /* filters for the RDE */
        while ((r = TAILQ_FIRST(conf->filters)) != NULL) {
                TAILQ_REMOVE(conf->filters, r, entry);
+               if (send_filterset(ibuf_rde, &r->set) == -1)
+                       return (-1);
                if (imsg_compose(ibuf_rde, IMSG_RECONF_FILTER, 0, 0, -1,
                    r, sizeof(struct filter_rule)) == -1)
                        return (-1);
-               if (send_filterset(ibuf_rde, &r->set) == -1)
-                       return (-1);
                filterset_free(&r->set);
                free(r);
        }
@@ -669,18 +669,18 @@ reconfigure(char *conffile, struct bgpd_
                        return (-1);
 
                /* export targets */
+               if (send_filterset(ibuf_rde, &vpn->export) == -1)
+                       return (-1);
                if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_EXPORT, 0, 0,
                    -1, NULL, 0) == -1)
                        return (-1);
-               if (send_filterset(ibuf_rde, &vpn->export) == -1)
-                       return (-1);
                filterset_free(&vpn->export);
 
                /* import targets */
+               if (send_filterset(ibuf_rde, &vpn->import) == -1)
+                       return (-1);
                if (imsg_compose(ibuf_rde, IMSG_RECONF_VPN_IMPORT, 0, 0,
                    -1, NULL, 0) == -1)
-                       return (-1);
-               if (send_filterset(ibuf_rde, &vpn->import) == -1)
                        return (-1);
                filterset_free(&vpn->import);
 
Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.479
diff -u -p -r1.479 rde.c
--- rde.c       24 Jul 2019 20:25:27 -0000      1.479
+++ rde.c       25 Jul 2019 10:16:31 -0000
@@ -354,9 +354,10 @@ rde_main(int debug, int verbose)
        exit(0);
 }
 
-struct network_config   netconf_s, netconf_p;
-struct filterstate      netconf_state;
-struct filter_set_head *session_set, *parent_set;
+struct network_config  netconf_s, netconf_p;
+struct filterstate     netconf_state;
+struct filter_set_head session_set = TAILQ_HEAD_INITIALIZER(session_set);
+struct filter_set_head parent_set = TAILQ_HEAD_INITIALIZER(parent_set);
 
 void
 rde_dispatch_imsg_session(struct imsgbuf *ibuf)
@@ -461,7 +462,6 @@ rde_dispatch_imsg_session(struct imsgbuf
                        }
                        memcpy(&netconf_s, imsg.data, sizeof(netconf_s));
                        TAILQ_INIT(&netconf_s.attrset);
-                       session_set = &netconf_s.attrset;
                        rde_filterstate_prep(&netconf_state, NULL, NULL, NULL,
                            0);
                        asp = &netconf_state.aspath;
@@ -518,7 +518,7 @@ rde_dispatch_imsg_session(struct imsgbuf
                                log_warnx("rde_dispatch: wrong imsg len");
                                break;
                        }
-                       session_set = NULL;
+                       TAILQ_CONCAT(&netconf_s.attrset, &session_set, entry);
                        switch (netconf_s.prefix.aid) {
                        case AID_INET:
                                if (netconf_s.prefixlen > 32)
@@ -582,17 +582,12 @@ badnetdel:
                                log_warnx("rde_dispatch: wrong imsg len");
                                break;
                        }
-                       if (session_set == NULL) {
-                               log_warnx("rde_dispatch: "
-                                   "IMSG_FILTER_SET unexpected");
-                               break;
-                       }
                        if ((s = malloc(sizeof(struct filter_set))) == NULL)
                                fatal(NULL);
                        memcpy(s, imsg.data, sizeof(struct filter_set));
                        if (s->type == ACTION_SET_NEXTHOP)
                                s->action.nh = nexthop_get(&s->action.nexthop);
-                       TAILQ_INSERT_TAIL(session_set, s, entry);
+                       TAILQ_INSERT_TAIL(&session_set, s, entry);
                        break;
                case IMSG_CTL_SHOW_NETWORK:
                case IMSG_CTL_SHOW_RIB:
@@ -752,10 +747,9 @@ rde_dispatch_imsg_parent(struct imsgbuf 
                        }
                        memcpy(&netconf_p, imsg.data, sizeof(netconf_p));
                        TAILQ_INIT(&netconf_p.attrset);
-                       parent_set = &netconf_p.attrset;
                        break;
                case IMSG_NETWORK_DONE:
-                       parent_set = NULL;
+                       TAILQ_CONCAT(&netconf_p.attrset, &parent_set, entry);
 
                        rde_filterstate_prep(&state, NULL, NULL, NULL, 0);
                        asp = &state.aspath;
@@ -871,15 +865,14 @@ rde_dispatch_imsg_parent(struct imsgbuf 
                                }
                        }
                        TAILQ_INIT(&r->set);
+                       TAILQ_CONCAT(&r->set, &parent_set, entry);
                        if ((rib = rib_byid(rib_find(r->rib))) == NULL) {
                                log_warnx("IMSG_RECONF_FILTER: filter rule "
                                    "for nonexistent rib %s", r->rib);
-                               parent_set = NULL;
                                free(r);
                                break;
                        }
                        r->peer.ribid = rib->id;
-                       parent_set = &r->set;
                        if (r->dir == DIR_IN) {
                                nr = rib_desc(rib)->in_rules_tmp;
                                if (nr == NULL) {
@@ -990,7 +983,7 @@ rde_dispatch_imsg_parent(struct imsgbuf 
                                    "IMSG_RECONF_VPN_EXPORT unexpected");
                                break;
                        }
-                       parent_set = &vpn->export;
+                       TAILQ_CONCAT(&vpn->export, &parent_set, entry);
                        break;
                case IMSG_RECONF_VPN_IMPORT:
                        if (vpn == NULL) {
@@ -998,10 +991,9 @@ rde_dispatch_imsg_parent(struct imsgbuf 
                                    "IMSG_RECONF_VPN_IMPORT unexpected");
                                break;
                        }
-                       parent_set = &vpn->import;
+                       TAILQ_CONCAT(&vpn->import, &parent_set, entry);
                        break;
                case IMSG_RECONF_VPN_DONE:
-                       parent_set = NULL;
                        break;
                case IMSG_RECONF_DRAIN:
                        imsg_compose(ibuf_main, IMSG_RECONF_DRAIN, 0, 0,
@@ -1010,7 +1002,6 @@ rde_dispatch_imsg_parent(struct imsgbuf 
                case IMSG_RECONF_DONE:
                        if (nconf == NULL)
                                fatalx("got IMSG_RECONF_DONE but no config");
-                       parent_set = NULL;
                        last_prefixset = NULL;
 
                        rde_reload_done();
@@ -1022,17 +1013,12 @@ rde_dispatch_imsg_parent(struct imsgbuf 
                        if (imsg.hdr.len > IMSG_HEADER_SIZE +
                            sizeof(struct filter_set))
                                fatalx("IMSG_FILTER_SET bad len");
-                       if (parent_set == NULL) {
-                               log_warnx("rde_dispatch_imsg_parent: "
-                                   "IMSG_FILTER_SET unexpected");
-                               break;
-                       }
                        if ((s = malloc(sizeof(struct filter_set))) == NULL)
                                fatal(NULL);
                        memcpy(s, imsg.data, sizeof(struct filter_set));
                        if (s->type == ACTION_SET_NEXTHOP)
                                s->action.nh = nexthop_get(&s->action.nexthop);
-                       TAILQ_INSERT_TAIL(parent_set, s, entry);
+                       TAILQ_INSERT_TAIL(&parent_set, s, entry);
                        break;
                case IMSG_MRT_OPEN:
                case IMSG_MRT_REOPEN:

Reply via email to