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>