This diff changes various loops which call into up_generate_update() so that all these loops call the same function peer_generate_update() which then calls up_generate_update(). This is a step to add an alternative path to generate updates for add-path send support without altering many code-paths.
If I did not fool myself this should not alter current behaviour. rde_up_dump_upcall() gets a few more checks but all those checks should be false in this case (e.g. peer_dump checks the export_type already). -- :wq Claudio Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.547 diff -u -p -r1.547 rde.c --- rde.c 27 Jun 2022 13:26:51 -0000 1.547 +++ rde.c 28 Jun 2022 19:38:42 -0000 @@ -3037,59 +3037,6 @@ rde_evaluate_all(void) return rde_eval_all; } -static int -rde_skip_peer(struct rde_peer *peer, uint16_t rib_id, uint8_t aid) -{ - /* skip ourself */ - if (peer == peerself) - return 1; - if (peer->state != PEER_UP) - return 1; - /* skip peers using a different rib */ - if (peer->loc_rib_id != rib_id) - return 1; - /* check if peer actually supports the address family */ - if (peer->capa.mp[aid] == 0) - return 1; - /* skip peers with special export types */ - if (peer->export_type == EXPORT_NONE || - peer->export_type == EXPORT_DEFAULT_ROUTE) - return 1; - - return 0; -} - -void -rde_generate_updates(struct rib *rib, struct prefix *new, struct prefix *old, - int eval_all) -{ - struct rde_peer *peer; - uint8_t aid; - - /* - * If old is != NULL we know it was active and should be removed. - * If new is != NULL we know it is reachable and then we should - * generate an update. - */ - if (old == NULL && new == NULL) - return; - - if (new) - aid = new->pt->aid; - else - aid = old->pt->aid; - - LIST_FOREACH(peer, &peerlist, peer_l) { - if (rde_skip_peer(peer, rib->id, aid)) - continue; - /* skip regular peers if the best path didn't change */ - if ((peer->flags & PEERFLAG_EVALUATE_ALL) == 0 && eval_all) - continue; - - up_generate_updates(out_rules, peer, new, old); - } -} - /* flush Adj-RIB-Out by withdrawing all prefixes */ static void rde_up_flush_upcall(struct prefix *p, void *ptr) @@ -3760,26 +3707,16 @@ rde_softreconfig_in(struct rib_entry *re } static void -rde_softreconfig_out(struct rib_entry *re, void *bula) +rde_softreconfig_out(struct rib_entry *re, void *arg) { - struct prefix *p; - struct rde_peer *peer; - uint8_t aid = re->prefix->aid; + struct rib *rib = arg; + struct prefix *p; if ((p = prefix_best(re)) == NULL) /* no valid path for prefix */ return; - LIST_FOREACH(peer, &peerlist, peer_l) { - if (rde_skip_peer(peer, re->rib_id, aid)) - continue; - /* skip peers which don't need to reconfigure */ - if (peer->reconf_out == 0) - continue; - - /* Regenerate all updates. */ - up_generate_updates(out_rules, peer, p, p); - } + rde_generate_updates(rib, p, NULL, EVAL_RECONF); } static void Index: rde.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v retrieving revision 1.254 diff -u -p -r1.254 rde.h --- rde.h 27 Jun 2022 13:26:51 -0000 1.254 +++ rde.h 6 Jul 2022 14:53:36 -0000 @@ -362,6 +362,12 @@ struct filterstate { uint8_t nhflags; }; +enum eval_mode { + EVAL_DEFAULT, + EVAL_ALL, + EVAL_RECONF, +}; + extern struct rde_memstats rdemem; /* prototypes */ @@ -384,7 +390,7 @@ void rde_pftable_del(uint16_t, struct p int rde_evaluate_all(void); void rde_generate_updates(struct rib *, struct prefix *, - struct prefix *, int); + struct prefix *, enum eval_mode); uint32_t rde_local_as(void); int rde_decisionflags(void); void rde_peer_send_rrefresh(struct rde_peer *, uint8_t, uint8_t); Index: rde_decide.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_decide.c,v retrieving revision 1.91 diff -u -p -r1.91 rde_decide.c --- rde_decide.c 22 Mar 2022 10:53:08 -0000 1.91 +++ rde_decide.c 6 Jul 2022 14:54:58 -0000 @@ -493,7 +493,7 @@ prefix_evaluate(struct rib_entry *re, st * but remember that xp may be NULL aka ineligible. * Additional decision may be made by the called functions. */ - rde_generate_updates(rib, xp, active, 0); + rde_generate_updates(rib, xp, active, EVAL_DEFAULT); if ((rib->flags & F_RIB_NOFIB) == 0) rde_send_kroute(rib, xp, active); return; @@ -506,5 +506,6 @@ prefix_evaluate(struct rib_entry *re, st */ if (rde_evaluate_all()) if ((new != NULL && prefix_eligible(new)) || old != NULL) - rde_generate_updates(rib, prefix_best(re), NULL, 1); + rde_generate_updates(rib, prefix_best(re), NULL, + EVAL_ALL); } Index: rde_peer.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_peer.c,v retrieving revision 1.17 diff -u -p -r1.17 rde_peer.c --- rde_peer.c 27 Jun 2022 13:26:51 -0000 1.17 +++ rde_peer.c 6 Jul 2022 14:58:21 -0000 @@ -212,6 +212,63 @@ peer_add(uint32_t id, struct peer_config return (peer); } +static void +peer_generate_update(struct rde_peer *peer, uint16_t rib_id, + struct prefix *new, struct prefix *old, enum eval_mode mode) +{ + uint8_t aid; + + if (new != NULL) + aid = new->pt->aid; + else if (old != NULL) + aid = old->pt->aid; + else + return; + + /* skip ourself */ + if (peer == peerself) + return; + if (peer->state != PEER_UP) + return; + /* skip peers using a different rib */ + if (peer->loc_rib_id != rib_id) + return; + /* check if peer actually supports the address family */ + if (peer->capa.mp[aid] == 0) + return; + /* skip peers with special export types */ + if (peer->export_type == EXPORT_NONE || + peer->export_type == EXPORT_DEFAULT_ROUTE) + return; + + /* if reconf skip peers which don't need to reconfigure */ + if (mode == EVAL_RECONF && peer->reconf_out == 0) + return; + /* skip regular peers if the best path didn't change */ + if (mode == EVAL_ALL && (peer->flags & PEERFLAG_EVALUATE_ALL) == 0) + return; + + up_generate_updates(out_rules, peer, new, old); +} + +void +rde_generate_updates(struct rib *rib, struct prefix *new, struct prefix *old, + enum eval_mode mode) +{ + struct rde_peer *peer; + + /* + * If old is != NULL we know it was active and should be removed. + * If new is != NULL we know it is reachable and then we should + * generate an update. + */ + if (old == NULL && new == NULL) + return; + + LIST_FOREACH(peer, &peerlist, peer_l) + peer_generate_update(peer, rib->id, new, old, mode); +} + /* * Various RIB walker callbacks. */ @@ -317,20 +374,10 @@ rde_up_dump_upcall(struct rib_entry *re, struct rde_peer *peer = ptr; struct prefix *p; - if (peer->state != PEER_UP) - return; - if (re->rib_id != peer->loc_rib_id) - fatalx("%s: Unexpected RIB %u != %u.", __func__, re->rib_id, - peer->loc_rib_id); - if (peer->capa.mp[re->prefix->aid] == 0) - fatalx("%s: Unexpected %s prefix", __func__, - aid2str(re->prefix->aid)); - /* no eligible prefix, not even for 'evaluate all' */ if ((p = prefix_best(re)) == NULL) return; - - up_generate_updates(out_rules, peer, p, NULL); + peer_generate_update(peer, re->rib_id, p, NULL, 0); } static void @@ -461,6 +508,7 @@ peer_stale(struct rde_peer *peer, uint8_ peer->staletime[aid] = now = getmonotime(); peer->state = PEER_DOWN; + /* XXX this is not quite correct */ /* mark Adj-RIB-Out stale for this peer */ if (prefix_dump_new(peer, AID_UNSPEC, 0, NULL, peer_adjout_stale_upcall, NULL, NULL) == -1)