svn commit: r337462 - in stable/11/sys: net netinet netinet6
Rodney W. Grimes
freebsd at pdx.rh.CN85.dnsmgr.net
Wed Aug 8 16:40:54 UTC 2018
> Author: ae
> Date: Wed Aug 8 16:17:50 2018
> New Revision: 337462
> URL: https://svnweb.freebsd.org/changeset/base/337462
>
> Log:
> MFC r331098 (by melifaro):
> Fix outgoing TCP/UDP packet drop on arp/ndp entry expiration.
>
> Current arp/nd code relies on the feedback from the datapath indicating
> that the entry is still used. This mechanism is incorporated into the
> arpresolve()/nd6_resolve() routines. After the inpcb route cache
> introduction, the packet path for the locally-originated packets changed,
> passing cached lle pointer to the ether_output() directly. This resulted
> in the arp/ndp entry expire each time exactly after the configured max_age
> interval. During the small window between the ARP/NDP request and reply
> from the router, most of the packets got lost.
>
> Fix this behaviour by plugging datapath notification code to the packet
> path used by route cache. Unify the notification code by using single
> inlined function with the per-AF callbacks.
Is this worthy of an EN for 11.2?
This is a rather annoying problem for some people.
> Modified:
> stable/11/sys/net/if_ethersubr.c
> stable/11/sys/net/if_llatbl.h
> stable/11/sys/netinet/if_ether.c
> stable/11/sys/netinet/in.c
> stable/11/sys/netinet6/in6.c
> Directory Properties:
> stable/11/ (props changed)
>
> Modified: stable/11/sys/net/if_ethersubr.c
> ==============================================================================
> --- stable/11/sys/net/if_ethersubr.c Wed Aug 8 16:11:46 2018 (r337461)
> +++ stable/11/sys/net/if_ethersubr.c Wed Aug 8 16:17:50 2018 (r337462)
> @@ -313,7 +313,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;
>
> Modified: stable/11/sys/net/if_llatbl.h
> ==============================================================================
> --- stable/11/sys/net/if_llatbl.h Wed Aug 8 16:11:46 2018 (r337461)
> +++ stable/11/sys/net/if_llatbl.h Wed Aug 8 16:17:50 2018 (r337462)
> @@ -155,6 +155,7 @@ typedef void (llt_fill_sa_entry_t)(const struct llentr
> 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 *);
> @@ -179,6 +180,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);
> @@ -251,6 +253,19 @@ lla_lookup(struct lltable *llt, u_int flags, const str
> {
>
> 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 *);
>
> Modified: stable/11/sys/netinet/if_ether.c
> ==============================================================================
> --- stable/11/sys/netinet/if_ether.c Wed Aug 8 16:11:46 2018 (r337461)
> +++ stable/11/sys/netinet/if_ether.c Wed Aug 8 16:17:50 2018 (r337462)
> @@ -502,12 +502,8 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int flag
> }
> 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) {
> @@ -638,12 +634,8 @@ arpresolve(struct ifnet *ifp, int is_gw, struct mbuf *
> 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;
>
> Modified: stable/11/sys/netinet/in.c
> ==============================================================================
> --- stable/11/sys/netinet/in.c Wed Aug 8 16:11:46 2018 (r337461)
> +++ stable/11/sys/netinet/in.c Wed Aug 8 16:17:50 2018 (r337462)
> @@ -1056,6 +1056,19 @@ in_lltable_destroy_lle_unlocked(struct llentry *lle)
> }
>
> /*
> + * 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.
> */
> @@ -1454,6 +1467,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);
>
> Modified: stable/11/sys/netinet6/in6.c
> ==============================================================================
> --- stable/11/sys/netinet6/in6.c Wed Aug 8 16:11:46 2018 (r337461)
> +++ stable/11/sys/netinet6/in6.c Wed Aug 8 16:17:50 2018 (r337462)
> @@ -2145,6 +2145,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)
> {
> @@ -2377,6 +2396,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);
>
>
--
Rod Grimes rgrimes at freebsd.org
More information about the svn-src-all
mailing list