In one case (when a peer changes RIB) the RDE needs to withdraw all prefixes of that peer and then during softreconfig it will load the prefixes freshly form the new RIB. Since we now have a list of all prefixes that have been sent to the peer use that one instead of doing a full table walk over the old RIB.
-- :wq Claudio Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.433 diff -u -p -r1.433 rde.c --- rde.c 3 Oct 2018 11:36:39 -0000 1.433 +++ rde.c 3 Oct 2018 12:37:28 -0000 @@ -96,7 +96,6 @@ static void rde_softreconfig_out_done(v static void rde_softreconfig_done(void); static void rde_softreconfig_out(struct rib_entry *, void *); static void rde_softreconfig_in(struct rib_entry *, void *); -static void rde_softreconfig_unload_peer(struct rib_entry *, void *); void rde_up_dump_upcall(struct rib_entry *, void *); void rde_update_queue_runner(void); void rde_update6_queue_runner(u_int8_t); @@ -2929,8 +2928,7 @@ rde_reload_done(void) peer->reconf_out = 0; peer->reconf_rib = 0; if (peer->rib != rib_find(peer->conf.rib)) { - rib_dump(peer->rib, rde_softreconfig_unload_peer, peer, - AID_UNSPEC); + up_withdraw_all(peer); peer->rib = rib_find(peer->conf.rib); if (peer->rib == NULL) fatalx("King Bula's peer met an unknown RIB"); @@ -3226,32 +3224,6 @@ rde_softreconfig_out(struct rib_entry *r if (peer->rib == re_rib(re) && peer->reconf_out) rde_softreconfig_out_peer(re, peer); } -} - -static void -rde_softreconfig_unload_peer(struct rib_entry *re, void *ptr) -{ - struct filterstate ostate; - struct rde_peer *peer = ptr; - struct prefix *p = re->active; - struct pt_entry *pt; - struct bgpd_addr addr; - - pt = re->prefix; - pt_getaddr(pt, &addr); - - /* check if prefix was announced */ - if (up_test_update(peer, p) != 1) - return; - - rde_filterstate_prep(&ostate, prefix_aspath(p), prefix_nexthop(p), - prefix_nhflags(p)); - if (rde_filter(out_rules_tmp, peer, p, &ostate) != ACTION_DENY) { - /* send withdraw */ - up_rib_remove(peer, re); - up_generate(peer, NULL, &addr, pt->prefixlen); - } - rde_filterstate_clean(&ostate); } /* Index: rde.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v retrieving revision 1.196 diff -u -p -r1.196 rde.h --- rde.h 1 Oct 2018 23:09:53 -0000 1.196 +++ rde.h 3 Oct 2018 12:37:15 -0000 @@ -555,6 +555,7 @@ void up_init(struct rde_peer *); void up_down(struct rde_peer *); int up_rib_remove(struct rde_peer *, struct rib_entry *); void up_rib_add(struct rde_peer *, struct rib_entry *); +void up_withdraw_all(struct rde_peer *); int up_test_update(struct rde_peer *, struct prefix *); int up_generate(struct rde_peer *, struct filterstate *, struct bgpd_addr *, u_int8_t); Index: rde_update.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_update.c,v retrieving revision 1.100 diff -u -p -r1.100 rde_update.c --- rde_update.c 29 Sep 2018 07:43:36 -0000 1.100 +++ rde_update.c 3 Oct 2018 12:38:28 -0000 @@ -245,6 +245,22 @@ up_rib_add(struct rde_peer *peer, struct free(ur); } +void +up_withdraw_all(struct rde_peer *peer) +{ + struct bgpd_addr addr; + struct update_rib *ur, *nur; + + RB_FOREACH_SAFE(ur, uptree_rib, &peer->up_rib, nur) { + RB_REMOVE(uptree_rib, &peer->up_rib, ur); + + /* withdraw prefix */ + pt_getaddr(ur->re->prefix, &addr); + up_generate(peer, NULL, &addr, ur->re->prefix->prefixlen); + free(ur); + } +} + int up_add(struct rde_peer *peer, struct update_prefix *p, struct update_attr *a) {