Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Aug 2018 16:17:50 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r337462 - in stable/11/sys: net netinet netinet6
Message-ID:  <201808081617.w78GHoch061371@repo.freebsd.org>

next 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.

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);



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