The branch main has been updated by melifaro:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=33cb3cb2e3212705b10e7885b37f70a3c2987c9e

commit 33cb3cb2e3212705b10e7885b37f70a3c2987c9e
Author:     Alexander V. Chernikov <[email protected]>
AuthorDate: 2021-04-17 18:58:12 +0000
Commit:     Alexander V. Chernikov <[email protected]>
CommitDate: 2021-04-20 22:02:41 +0000

    Fix rib generation count for fib algo.
    
    Currently, PCB caching mechanism relies on the rib generation
     counter (rnh_gen) to invalidate cached nhops/LLE entries.
    
    With certain fib algorithms, it is now possible that the
     datapath lookup state applies RIB changes with some delay.
    In that scenario, PCB cache will invalidate on the RIB change,
     but the new lookup may result in the same nexthop being returned.
    When fib algo finally gets in sync with the RIB changes, PCB cache
     will not receive any notification and will end up caching the stale data.
    
    To fix this, introduce additional counter, rnh_gen_rib, which is used
     only when FIB_ALGO is enabled.
    This counter is incremented by the control plane. Each time when fib algo
     synchronises with the RIB, it updates rnh_gen to the current rnh_gen_rib 
value.
    
    Differential Revision: https://reviews.freebsd.org/D29812
    Reviewed by:    donner
    MFC after:      2 weeks
---
 sys/net/route/fib_algo.c  | 13 ++++++++++++-
 sys/net/route/route_ctl.c |  6 +++---
 sys/net/route/route_var.h | 15 ++++++++++++++-
 3 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/sys/net/route/fib_algo.c b/sys/net/route/fib_algo.c
index 30e715e1e1ef..91565d727a9c 100644
--- a/sys/net/route/fib_algo.c
+++ b/sys/net/route/fib_algo.c
@@ -525,6 +525,13 @@ schedule_fd_rebuild(struct fib_data *fd, const char 
*reason)
        }
 }
 
+static void
+sync_rib_gen(struct fib_data *fd)
+{
+       FD_PRINTF(LOG_DEBUG, fd, "Sync gen %u -> %u", fd->fd_rh->rnh_gen, 
fd->fd_rh->rnh_gen_rib);
+       fd->fd_rh->rnh_gen = fd->fd_rh->rnh_gen_rib;
+}
+
 static int64_t
 get_tv_diff_ms(const struct timeval *old_tv, const struct timeval *new_tv)
 {
@@ -680,6 +687,7 @@ apply_rtable_changes(struct fib_data *fd)
        result = fd->fd_flm->flm_change_rib_items_cb(fd->fd_rh, q, 
fd->fd_algo_data);
 
        if (result == FLM_SUCCESS) {
+               sync_rib_gen(fd);
                for (int i = 0; i < q->count; i++)
                        if (q->entries[i].nh_old)
                                fib_unref_nhop(fd, q->entries[i].nh_old);
@@ -811,6 +819,7 @@ handle_rtable_change_cb(struct rib_head *rnh, struct 
rib_cmd_info *rc,
 
        switch (result) {
        case FLM_SUCCESS:
+               sync_rib_gen(fd);
                /* Unref old nexthop on success */
                if (rc->rc_nh_old != NULL)
                        fib_unref_nhop(fd, rc->rc_nh_old);
@@ -1236,7 +1245,9 @@ setup_fd_instance(struct fib_lookup_module *flm, struct 
rib_head *rh,
                result = try_setup_fd_instance(flm, rh, prev_fd, &new_fd);
 
                if ((result == FLM_SUCCESS) && attach) {
-                       if (!fib_set_datapath_ptr(new_fd, &new_fd->fd_dp))
+                       if (fib_set_datapath_ptr(new_fd, &new_fd->fd_dp))
+                               sync_rib_gen(new_fd);
+                       else
                                result = FLM_REBUILD;
                }
 
diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c
index fb3dfff87019..a0c4a2283a00 100644
--- a/sys/net/route/route_ctl.c
+++ b/sys/net/route/route_ctl.c
@@ -808,7 +808,7 @@ rt_unlinkrte(struct rib_head *rnh, struct rt_addrinfo 
*info, struct rib_cmd_info
        rt->rte_flags &= ~RTF_UP;
 
        /* Finalize notification */
-       rnh->rnh_gen++;
+       rib_bump_gen(rnh);
        rnh->rnh_prefixes--;
 
        rc->rc_cmd = RTM_DELETE;
@@ -1060,7 +1060,7 @@ add_route_nhop(struct rib_head *rnh, struct rtentry *rt,
                        tmproutes_update(rnh, rt);
 
                /* Finalize notification */
-               rnh->rnh_gen++;
+               rib_bump_gen(rnh);
                rnh->rnh_prefixes++;
 
                rc->rc_cmd = RTM_ADD;
@@ -1116,7 +1116,7 @@ change_route_nhop(struct rib_head *rnh, struct rtentry 
*rt,
        }
 
        /* Finalize notification */
-       rnh->rnh_gen++;
+       rib_bump_gen(rnh);
        if (rnd->rnd_nhop == NULL)
                rnh->rnh_prefixes--;
 
diff --git a/sys/net/route/route_var.h b/sys/net/route/route_var.h
index 427c286a5090..f12931476fd3 100644
--- a/sys/net/route/route_var.h
+++ b/sys/net/route/route_var.h
@@ -60,7 +60,7 @@ struct rib_head {
        rn_walktree_t           *rnh_walktree;  /* traverse tree */
        rn_walktree_from_t      *rnh_walktree_from; /* traverse tree below a */
        rnh_preadd_entry_f_t    *rnh_preadd;    /* hook to alter record prior 
to insertion */
-       rt_gen_t                rnh_gen;        /* generation counter */
+       rt_gen_t                rnh_gen;        /* datapath generation counter 
*/
        int                     rnh_multipath;  /* multipath capable ? */
        struct radix_node       rnh_nodes[3];   /* empty tree for common case */
        struct rmlock           rib_lock;       /* config/data path lock */
@@ -71,6 +71,9 @@ struct rib_head {
        struct callout          expire_callout; /* Callout for expiring dynamic 
routes */
        time_t                  next_expire;    /* Next expire run ts */
        uint32_t                rnh_prefixes;   /* Number of prefixes */
+#ifdef FIB_ALGO
+       rt_gen_t                rnh_gen_rib;    /* rib generation counter */
+#endif
        uint32_t                rib_dying:1;    /* rib is detaching */
        uint32_t                rib_algo_fixed:1;/* fixed algorithm */
        struct nh_control       *nh_control;    /* nexthop subsystem data */
@@ -116,6 +119,16 @@ CHK_STRUCT_ROUTE_FIELDS(_ro_new);                          
                \
 _Static_assert(__offsetof(struct route, ro_dst) == __offsetof(_ro_new, 
_dst_new),\
                "ro_dst and " #_dst_new " are at different offset")
 
+static inline void
+rib_bump_gen(struct rib_head *rnh)
+{
+#ifdef FIB_ALGO
+       rnh->rnh_gen_rib++;
+#else
+       rnh->rnh_gen++;
+#endif
+}
+
 struct rib_head *rt_tables_get_rnh(uint32_t table, sa_family_t family);
 int rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum);
 struct rib_cmd_info;
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to