[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
This commit is contained in:
parent
cd2401cdd5
commit
f3a3b06121
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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 *);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user