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);
 }
 
 /*

Reply via email to