Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Aug 2018 09:40:42 -0700 (PDT)
From:      "Rodney W. Grimes" <freebsd@pdx.rh.CN85.dnsmgr.net>
To:        "Andrey V. Elsukov" <ae@freebsd.org>
Cc:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   Re: svn commit: r337462 - in stable/11/sys: net netinet netinet6
Message-ID:  <201808081640.w78Gegho012855@pdx.rh.CN85.dnsmgr.net>
In-Reply-To: <201808081617.w78GHoch061371@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
> 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@freebsd.org



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808081640.w78Gegho012855>