Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Aug 2021 22:56:47 GMT
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: f3a3b0612169 - main - [lltable] Unify datapath feedback mechamism.
Message-ID:  <202108042256.174Mulvd062086@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by melifaro:

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

commit f3a3b061216936b6233d1624dfdba03240d7c045
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2021-08-02 22:39:00 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2021-08-04 22:52:43 +0000

    [lltable] Unify datapath feedback mechamism.
    
    Use newly-create llentry_request_feedback(),
     llentry_mark_used() and llentry_get_hittime() to
     request datapatch usage check and fetch the results
     in the same fashion both in IPv4 and IPv6.
    
    While here, simplify llentry_provide_feedback() wrapper
     by eliminating 1 condition check.
    
    MFC after:      2 weeks
    Differential Revision: https://reviews.freebsd.org/D31390
---
 sys/net/if_ethersubr.c  |  2 +-
 sys/net/if_infiniband.c |  2 +-
 sys/net/if_llatbl.c     | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 sys/net/if_llatbl.h     | 11 +++++++----
 sys/netinet/if_ether.c  | 25 +++++++------------------
 sys/netinet/in.c        | 15 +--------------
 sys/netinet6/in6.c      | 21 +--------------------
 sys/netinet6/nd6.c      | 32 ++++++++------------------------
 8 files changed, 72 insertions(+), 82 deletions(-)

diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 7eb46df8281a..718de9625044 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -315,7 +315,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
 					 * the entry was used
 					 * by datapath.
 					 */
-					llentry_mark_used(lle);
+					llentry_provide_feedback(lle);
 			}
 			if (lle != NULL) {
 				phdr = lle->r_linkdata;
diff --git a/sys/net/if_infiniband.c b/sys/net/if_infiniband.c
index 3e7daeed4da3..528f20b7c98d 100644
--- a/sys/net/if_infiniband.c
+++ b/sys/net/if_infiniband.c
@@ -329,7 +329,7 @@ infiniband_output(struct ifnet *ifp, struct mbuf *m,
 					 * the entry was used
 					 * by datapath.
 					 */
-					llentry_mark_used(lle);
+					llentry_provide_feedback(lle);
 			}
 			if (lle != NULL) {
 				phdr = lle->r_linkdata;
diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
index 7225869a07d0..70baf58c2778 100644
--- a/sys/net/if_llatbl.c
+++ b/sys/net/if_llatbl.c
@@ -386,6 +386,52 @@ lltable_calc_llheader(struct ifnet *ifp, int family, char *lladdr,
 	return (error);
 }
 
+/*
+ * Requests feedback from the datapath.
+ * First packet using @lle should result in
+ * setting r_skip_req back to 0 and updating
+ * lle_hittime to the current time_uptime.
+ */
+void
+llentry_request_feedback(struct llentry *lle)
+{
+	LLE_REQ_LOCK(lle);
+	lle->r_skip_req = 1;
+	LLE_REQ_UNLOCK(lle);
+}
+
+/*
+ * Updates the lle state to mark it has been used
+ * and record the time.
+ * Used by the llentry_provide_feedback() wrapper.
+ */
+void
+llentry_mark_used(struct llentry *lle)
+{
+	LLE_REQ_LOCK(lle);
+	lle->r_skip_req = 0;
+	lle->lle_hittime = time_uptime;
+	LLE_REQ_UNLOCK(lle);
+}
+
+/*
+ * Fetches the time when lle was used.
+ * Return 0 if the entry was not used, relevant time_uptime
+ *  otherwise.
+ */
+time_t
+llentry_get_hittime(struct llentry *lle)
+{
+	time_t lle_hittime = 0;
+
+	LLE_REQ_LOCK(lle);
+	if ((lle->r_skip_req == 0) && (lle_hittime < lle->lle_hittime))
+		lle_hittime = lle->lle_hittime;
+	LLE_REQ_UNLOCK(lle);
+
+	return (lle_hittime);
+}
+
 /*
  * Update link-layer header for given @lle after
  * interface lladdr was changed.
diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h
index 1081b7cdf2cd..488f8b006315 100644
--- a/sys/net/if_llatbl.h
+++ b/sys/net/if_llatbl.h
@@ -250,17 +250,20 @@ lla_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
 	return (llt->llt_lookup(llt, flags, l3addr));
 }
 
+void llentry_request_feedback(struct llentry *lle);
+void llentry_mark_used(struct llentry *lle);
+time_t llentry_get_hittime(struct llentry *lle);
+
 /*
  * Notify the LLE code that the entry was used by datapath.
  */
 static __inline void
-llentry_mark_used(struct llentry *lle)
+llentry_provide_feedback(struct llentry *lle)
 {
 
-	if (lle->r_skip_req == 0)
+	if (__predict_true(lle->r_skip_req == 0))
 		return;
-	if ((lle->r_flags & RLLE_VALID) != 0)
-		lle->lle_tbl->llt_mark_used(lle);
+	llentry_mark_used(lle);
 }
 
 int		lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *);
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index ef50ec9ca964..3eb9d7210afb 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -207,7 +207,6 @@ arptimer(void *arg)
 {
 	struct llentry *lle = (struct llentry *)arg;
 	struct ifnet *ifp;
-	int r_skip_req;
 
 	if (lle->la_flags & LLE_STATIC) {
 		return;
@@ -240,27 +239,17 @@ arptimer(void *arg)
 
 		/*
 		 * Expiration time is approaching.
-		 * Let's try to refresh entry if it is still
-		 * in use.
-		 *
-		 * Set r_skip_req to get feedback from
-		 * fast path. Change state and re-schedule
-		 * ourselves.
+		 * Request usage feedback from the datapath.
+		 * Change state and re-schedule ourselves.
 		 */
-		LLE_REQ_LOCK(lle);
-		lle->r_skip_req = 1;
-		LLE_REQ_UNLOCK(lle);
+		llentry_request_feedback(lle);
 		lle->ln_state = ARP_LLINFO_VERIFY;
 		callout_schedule(&lle->lle_timer, hz * V_arpt_rexmit);
 		LLE_WUNLOCK(lle);
 		CURVNET_RESTORE();
 		return;
 	case ARP_LLINFO_VERIFY:
-		LLE_REQ_LOCK(lle);
-		r_skip_req = lle->r_skip_req;
-		LLE_REQ_UNLOCK(lle);
-
-		if (r_skip_req == 0 && lle->la_preempt > 0) {
+		if (llentry_get_hittime(lle) > 0 && lle->la_preempt > 0) {
 			/* Entry was used, issue refresh request */
 			struct epoch_tracker et;
 			struct in_addr dst;
@@ -532,7 +521,7 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int flags, struct mbuf *m,
 		bcopy(lladdr, desten, ll_len);
 
 		/* Notify LLE code that the entry was used by datapath */
-		llentry_mark_used(la);
+		llentry_provide_feedback(la);
 		if (pflags != NULL)
 			*pflags = la->la_flags & (LLE_VALID|LLE_IFADDR);
 		if (plle) {
@@ -656,7 +645,7 @@ arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
 		if (pflags != NULL)
 			*pflags = LLE_VALID | (la->r_flags & RLLE_IFADDR);
 		/* Notify the LLE handling code that the entry was used. */
-		llentry_mark_used(la);
+		llentry_provide_feedback(la);
 		if (plle) {
 			LLE_ADDREF(la);
 			*plle = la;
@@ -1225,7 +1214,7 @@ arp_check_update_lle(struct arphdr *ah, struct in_addr isaddr, struct ifnet *ifp
 			return;
 
 		/* Clear fast path feedback request if set */
-		la->r_skip_req = 0;
+		llentry_mark_used(la);
 	}
 
 	arp_mark_lle_reachable(la);
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index bcf071a81e0e..d1dd2b31b6ef 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1264,19 +1264,6 @@ in_lltable_destroy_lle_unlocked(epoch_context_t ctx)
 	free(lle, M_LLTABLE);
 }
 
-/*
- * Called by the datapath to indicate that
- * the entry was used.
- */
-static void
-in_lltable_mark_used(struct llentry *lle)
-{
-
-	LLE_REQ_LOCK(lle);
-	lle->r_skip_req = 0;
-	LLE_REQ_UNLOCK(lle);
-}
-
 /*
  * Called by LLE_FREE_LOCKED when number of references
  * drops to zero.
@@ -1681,7 +1668,7 @@ in_lltattach(struct ifnet *ifp)
 	llt->llt_fill_sa_entry = in_lltable_fill_sa_entry;
 	llt->llt_free_entry = in_lltable_free_entry;
 	llt->llt_match_prefix = in_lltable_match_prefix;
-	llt->llt_mark_used = in_lltable_mark_used;
+	llt->llt_mark_used = llentry_mark_used;
  	lltable_link(llt);
 
 	return (llt);
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 02cb9df7da3a..d5b3452c0b06 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2214,25 +2214,6 @@ in6_lltable_rtcheck(struct ifnet *ifp,
 	return 0;
 }
 
-/*
- * Called by the datapath to indicate that the entry was used.
- */
-static void
-in6_lltable_mark_used(struct llentry *lle)
-{
-
-	LLE_REQ_LOCK(lle);
-	lle->r_skip_req = 0;
-
-	/*
-	 * Set the hit time so the callback function
-	 * can determine the remaining time before
-	 * transiting to the DELAY state.
-	 */
-	lle->lle_hittime = time_uptime;
-	LLE_REQ_UNLOCK(lle);
-}
-
 static inline uint32_t
 in6_lltable_hash_dst(const struct in6_addr *dst, uint32_t hsize)
 {
@@ -2469,7 +2450,7 @@ in6_lltattach(struct ifnet *ifp)
 	llt->llt_fill_sa_entry = in6_lltable_fill_sa_entry;
 	llt->llt_free_entry = in6_lltable_free_entry;
 	llt->llt_match_prefix = in6_lltable_match_prefix;
-	llt->llt_mark_used = in6_lltable_mark_used;
+	llt->llt_mark_used = llentry_mark_used;
  	lltable_link(llt);
 
 	return (llt);
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 62f0ac733a23..60610462f4d7 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -617,7 +617,7 @@ nd6_llinfo_get_holdsrc(struct llentry *ln, struct in6_addr *src)
 static int
 nd6_is_stale(struct llentry *lle, long *pdelay, int *do_switch)
 {
-	int nd_delay, nd_gctimer, r_skip_req;
+	int nd_delay, nd_gctimer;
 	time_t lle_hittime;
 	long delay;
 
@@ -625,17 +625,13 @@ nd6_is_stale(struct llentry *lle, long *pdelay, int *do_switch)
 	nd_gctimer = V_nd6_gctimer;
 	nd_delay = V_nd6_delay;
 
-	LLE_REQ_LOCK(lle);
-	r_skip_req = lle->r_skip_req;
-	lle_hittime = lle->lle_hittime;
-	LLE_REQ_UNLOCK(lle);
+	lle_hittime = llentry_get_hittime(lle);
 
-	if (r_skip_req > 0) {
+	if (lle_hittime == 0) {
 		/*
-		 * Nonzero r_skip_req value was set upon entering
-		 * STALE state. Since value was not changed, no
-		 * packets were passed using this lle. Ask for
-		 * timer reschedule and keep STALE state.
+		 * Datapath feedback has been requested upon entering
+		 * STALE state. No packets has been passed using this lle.
+		 * Ask for the timer reschedule and keep STALE state.
 		 */
 		delay = (long)(MIN(nd_gctimer, nd_delay));
 		delay *= hz;
@@ -705,13 +701,7 @@ nd6_llinfo_setstate(struct llentry *lle, int newstate)
 		break;
 	case ND6_LLINFO_STALE:
 
-		/*
-		 * Notify fast path that we want to know if any packet
-		 * is transmitted by setting r_skip_req.
-		 */
-		LLE_REQ_LOCK(lle);
-		lle->r_skip_req = 1;
-		LLE_REQ_UNLOCK(lle);
+		llentry_request_feedback(lle);
 		nd_delay = V_nd6_delay;
 		nd_gctimer = V_nd6_gctimer;
 
@@ -2254,13 +2244,7 @@ nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
 		bcopy(ln->r_linkdata, desten, ln->r_hdrlen);
 		if (pflags != NULL)
 			*pflags = LLE_VALID | (ln->r_flags & RLLE_IFADDR);
-		/* Check if we have feedback request from nd6 timer */
-		if (ln->r_skip_req != 0) {
-			LLE_REQ_LOCK(ln);
-			ln->r_skip_req = 0; /* Notify that entry was used */
-			ln->lle_hittime = time_uptime;
-			LLE_REQ_UNLOCK(ln);
-		}
+		llentry_provide_feedback(ln);
 		if (plle) {
 			LLE_ADDREF(ln);
 			*plle = ln;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202108042256.174Mulvd062086>