This diff changes two things: - First, it move the kroute update into rde_generate_updates() simplifying prefix_evaluate a little bit.
- Second, it changes prefix_evaluate to take an additional argument for the old prefix (to be removed). Instead of doing this outside of prefix_evaluate() with some drawbacks in case the same prefix is removed and readded, the code is now in prefix_evaluate() and does all the magic itself. This is a necessary step to finally fix MED sorting. -- :wq Claudio Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.511 diff -u -p -r1.511 rde.c --- rde.c 9 Jan 2021 16:49:41 -0000 1.511 +++ rde.c 12 Jan 2021 16:17:31 -0000 @@ -2825,6 +2825,9 @@ rde_generate_updates(struct rib *rib, st if (old == NULL && new == NULL) return; + if ((rib->flags & F_RIB_NOFIB) == 0) + rde_send_kroute(rib, new, old); + if (new) aid = new->pt->aid; else @@ -3533,8 +3536,7 @@ rde_softreconfig_sync_reeval(struct rib_ /* need to re-link the nexthop if not already linked */ if ((p->flags & PREFIX_NEXTHOP_LINKED) == 0) nexthop_link(p); - LIST_REMOVE(p, entry.list.rib); - prefix_evaluate(p, re); + prefix_evaluate(re, p, p); } } Index: rde.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v retrieving revision 1.235 diff -u -p -r1.235 rde.h --- rde.h 4 Dec 2020 11:57:13 -0000 1.235 +++ rde.h 12 Jan 2021 16:17:31 -0000 @@ -483,10 +483,10 @@ communities_unref(struct rde_community * communities_unlink(comm); } -int community_to_rd(struct community *, u_int64_t *); +int community_to_rd(struct community *, u_int64_t *); /* rde_decide.c */ -void prefix_evaluate(struct prefix *, struct rib_entry *); +void prefix_evaluate(struct rib_entry *, struct prefix *, struct prefix *); /* rde_filter.c */ void rde_apply_set(struct filter_set_head *, struct rde_peer *, Index: rde_decide.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_decide.c,v retrieving revision 1.78 diff -u -p -r1.78 rde_decide.c --- rde_decide.c 9 Aug 2019 13:44:27 -0000 1.78 +++ rde_decide.c 12 Jan 2021 16:24:36 -0000 @@ -238,14 +238,16 @@ prefix_cmp(struct prefix *p1, struct pre * The to evaluate prefix must not be in the prefix list. */ void -prefix_evaluate(struct prefix *p, struct rib_entry *re) +prefix_evaluate(struct rib_entry *re, struct prefix *new, struct prefix *old) { struct prefix *xp; if (re_rib(re)->flags & F_RIB_NOEVALUATE) { /* decision process is turned off */ - if (p != NULL) - LIST_INSERT_HEAD(&re->prefix_h, p, entry.list.rib); + if (old != NULL) + LIST_REMOVE(old, entry.list.rib); + if (new != NULL) + LIST_INSERT_HEAD(&re->prefix_h, new, entry.list.rib); if (re->active) { /* * During reloads it is possible that the decision @@ -259,19 +261,22 @@ prefix_evaluate(struct prefix *p, struct return; } - if (p != NULL) { + if (old != NULL) + LIST_REMOVE(old, entry.list.rib); + + if (new != NULL) { if (LIST_EMPTY(&re->prefix_h)) - LIST_INSERT_HEAD(&re->prefix_h, p, entry.list.rib); + LIST_INSERT_HEAD(&re->prefix_h, new, entry.list.rib); else { LIST_FOREACH(xp, &re->prefix_h, entry.list.rib) { - if (prefix_cmp(p, xp) > 0) { - LIST_INSERT_BEFORE(xp, p, + if (prefix_cmp(new, xp) > 0) { + LIST_INSERT_BEFORE(xp, new, entry.list.rib); break; } else if (LIST_NEXT(xp, entry.list.rib) == NULL) { /* if xp last element ... */ - LIST_INSERT_AFTER(xp, p, + LIST_INSERT_AFTER(xp, new, entry.list.rib); break; } @@ -290,18 +295,17 @@ prefix_evaluate(struct prefix *p, struct xp = NULL; } - if (re->active != xp) { - /* need to generate an update */ - + /* + * If the active prefix changed or the active prefix was removed + * and added again then generate an update. + */ + if (re->active != xp || (old != NULL && xp == old)) { /* - * Send update with remove for re->active and add for xp + * Send update withdrawing re->active and adding xp * but remember that xp may be NULL aka ineligible. * Additional decision may be made by the called functions. */ rde_generate_updates(re_rib(re), xp, re->active); - if ((re_rib(re)->flags & F_RIB_NOFIB) == 0) - rde_send_kroute(re_rib(re), xp, re->active); - re->active = xp; } } Index: rde_rib.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v retrieving revision 1.218 diff -u -p -r1.218 rde_rib.c --- rde_rib.c 4 Dec 2020 11:57:13 -0000 1.218 +++ rde_rib.c 12 Jan 2021 16:17:31 -0000 @@ -1064,8 +1064,7 @@ prefix_move(struct prefix *p, struct rde * This is safe because we create a new prefix and so the change * is noticed by prefix_evaluate(). */ - LIST_REMOVE(p, entry.list.rib); - prefix_evaluate(np, np->re); + prefix_evaluate(np->re, np, p); /* remove old prefix node */ /* as before peer count needs no update because of move */ @@ -1551,18 +1550,7 @@ prefix_evaluate_all(struct prefix *p, en } /* redo the route decision */ - LIST_REMOVE(p, entry.list.rib); - /* - * If the prefix is the active one remove it first, - * this has to be done because we can not detect when - * the active prefix changes its state. In this case - * we know that this is a withdrawal and so the second - * prefix_evaluate() will generate no update because - * the nexthop is unreachable or ineligible. - */ - if (p == p->re->active) - prefix_evaluate(NULL, p->re); - prefix_evaluate(p, p->re); + prefix_evaluate(p->re, p, p); } /* kill a prefix. */ @@ -1570,8 +1558,7 @@ void prefix_destroy(struct prefix *p) { /* make route decision */ - LIST_REMOVE(p, entry.list.rib); - prefix_evaluate(NULL, p->re); + prefix_evaluate(p->re, NULL, p); prefix_unlink(p); prefix_free(p); @@ -1601,7 +1588,7 @@ prefix_link(struct prefix *p, struct rib rde_pftable_add(asp->pftableid, p); /* make route decision */ - prefix_evaluate(p, re); + prefix_evaluate(re, p, NULL); } /*