diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 8f280055da8..c8cd6d3411a 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -311,7 +311,13 @@ ether_output(struct ifnet *ifp, struct mbuf *m, if (lle == NULL) { /* if we lookup, keep cache */ addref = 1; - } + } else + /* + * Notify LLE code that + * the entry was used + * by datapath. + */ + llentry_mark_used(lle); } if (lle != NULL) { phdr = lle->r_linkdata; diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h index fcf93883154..9cec4ac75e5 100644 --- a/sys/net/if_llatbl.h +++ b/sys/net/if_llatbl.h @@ -149,6 +149,7 @@ typedef void (llt_fill_sa_entry_t)(const struct llentry *, struct sockaddr *); typedef void (llt_free_tbl_t)(struct lltable *); typedef void (llt_link_entry_t)(struct lltable *, struct llentry *); typedef void (llt_unlink_entry_t)(struct llentry *); +typedef void (llt_mark_used_t)(struct llentry *); typedef int (llt_foreach_cb_t)(struct lltable *, struct llentry *, void *); typedef int (llt_foreach_entry_t)(struct lltable *, llt_foreach_cb_t *, void *); @@ -173,6 +174,7 @@ struct lltable { llt_unlink_entry_t *llt_unlink_entry; llt_fill_sa_entry_t *llt_fill_sa_entry; llt_free_tbl_t *llt_free_tbl; + llt_mark_used_t *llt_mark_used; }; MALLOC_DECLARE(M_LLTABLE); @@ -247,6 +249,19 @@ lla_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr) return (llt->llt_lookup(llt, flags, l3addr)); } +/* + * Notify the LLE code that the entry was used by datapath. + */ +static __inline void +llentry_mark_used(struct llentry *lle) +{ + + if (lle->r_skip_req == 0) + return; + if ((lle->r_flags & RLLE_VALID) != 0) + lle->lle_tbl->llt_mark_used(lle); +} + int lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *); #include diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 800b51e599e..8b072503914 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -504,12 +504,8 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int flags, struct mbuf *m, } bcopy(lladdr, desten, ll_len); - /* Check if we have feedback request from arptimer() */ - if (la->r_skip_req != 0) { - LLE_REQ_LOCK(la); - la->r_skip_req = 0; /* Notify that entry was used */ - LLE_REQ_UNLOCK(la); - } + /* Notify LLE code that the entry was used by datapath */ + llentry_mark_used(la); if (pflags != NULL) *pflags = la->la_flags & (LLE_VALID|LLE_IFADDR); if (plle) { @@ -640,12 +636,8 @@ arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *m, bcopy(la->r_linkdata, desten, la->r_hdrlen); if (pflags != NULL) *pflags = LLE_VALID | (la->r_flags & RLLE_IFADDR); - /* Check if we have feedback request from arptimer() */ - if (la->r_skip_req != 0) { - LLE_REQ_LOCK(la); - la->r_skip_req = 0; /* Notify that entry was used */ - LLE_REQ_UNLOCK(la); - } + /* Notify the LLE handling code that the entry was used. */ + llentry_mark_used(la); if (plle) { LLE_ADDREF(la); *plle = la; diff --git a/sys/netinet/in.c b/sys/netinet/in.c index f4f87491182..6ecef6c0a44 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -1067,6 +1067,19 @@ in_lltable_destroy_lle_unlocked(struct llentry *lle) 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. @@ -1470,6 +1483,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; lltable_link(llt); return (llt); diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index fa8f77f6729..8a26e736d62 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -2148,6 +2148,25 @@ 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) { @@ -2380,6 +2399,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; lltable_link(llt); return (llt);