aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2021-08-02 22:39:00 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2021-09-07 21:02:58 +0000
commit280201438072f6800af1bdf77edc334e4cdf42cb (patch)
tree710bee9eb3dd9854d50929fa386e9b8bc93530ff
parent0f7162e0cd46784442b44f44e9303dc29705dc6b (diff)
downloadsrc-280201438072f6800af1bdf77edc334e4cdf42cb.tar.gz
src-280201438072f6800af1bdf77edc334e4cdf42cb.zip
[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. Differential Revision: https://reviews.freebsd.org/D31390 (cherry picked from commit f3a3b061216936b6233d1624dfdba03240d7c045)
-rw-r--r--sys/net/if_ethersubr.c2
-rw-r--r--sys/net/if_infiniband.c2
-rw-r--r--sys/net/if_llatbl.c46
-rw-r--r--sys/net/if_llatbl.h11
-rw-r--r--sys/netinet/if_ether.c25
-rw-r--r--sys/netinet/in.c15
-rw-r--r--sys/netinet6/in6.c21
-rw-r--r--sys/netinet6/nd6.c32
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
@@ -387,6 +387,52 @@ lltable_calc_llheader(struct ifnet *ifp, int family, char *lladdr,
}
/*
+ * 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
@@ -1265,19 +1265,6 @@ in_lltable_destroy_lle_unlocked(epoch_context_t ctx)
}
/*
- * 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 465426d719b0..7ae77c5c6604 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;