git: ff3a85d32411 - main - [lltable] Add per-family lltable getters.

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Wed, 29 Dec 2021 21:30:32 UTC
The branch main has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=ff3a85d32411cdd7894f932b1d3d7ce01ec7a648

commit ff3a85d32411cdd7894f932b1d3d7ce01ec7a648
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2021-12-26 12:39:26 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2021-12-29 20:57:15 +0000

    [lltable] Add per-family lltable getters.
    
    Introduce a new function, lltable_get(), to retrieve lltable pointer
     for the specified interface and family.
    Use it to avoid all-iftable list traversal when adding or deleting
     ARP/ND records.
    
    Differential Revision: https://reviews.freebsd.org/D33660
    MFC after:      2 weeks
---
 sys/net/if_llatbl.c | 26 ++++++++++++++++++--------
 sys/net/if_llatbl.h |  4 ++++
 sys/netinet/in.c    | 11 +++++++++++
 sys/netinet6/in6.c  | 11 +++++++++++
 4 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
index e4dfc45705a8..10d555b1bd86 100644
--- a/sys/net/if_llatbl.c
+++ b/sys/net/if_llatbl.c
@@ -712,6 +712,22 @@ lltable_unlink(struct lltable *llt)
 
 }
 
+/*
+ * Gets interface @ifp lltable for the specified @family
+ */
+struct lltable *
+lltable_get(struct ifnet *ifp, int family)
+{
+	switch (family) {
+	case AF_INET:
+		return (in_lltable_get(ifp));
+	case AF_INET6:
+		return (in6_lltable_get(ifp));
+	}
+
+	return (NULL);
+}
+
 /*
  * External methods used by lltable consumers
  */
@@ -823,14 +839,8 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
 		return EINVAL;
 	}
 
-	/* XXX linked list may be too expensive */
-	LLTABLE_LIST_RLOCK();
-	SLIST_FOREACH(llt, &V_lltables, llt_link) {
-		if (llt->llt_af == dst->sa_family &&
-		    llt->llt_ifp == ifp)
-			break;
-	}
-	LLTABLE_LIST_RUNLOCK();
+	llt = lltable_get(ifp, dst->sa_family);
+
 	if (llt == NULL)
 		return (ESRCH);
 
diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h
index 7ad9d59a1a0e..dfb5e13a9436 100644
--- a/sys/net/if_llatbl.h
+++ b/sys/net/if_llatbl.h
@@ -222,6 +222,10 @@ void		lltable_prefix_free(int, struct sockaddr *,
 		    struct sockaddr *, u_int);
 int		lltable_sysctl_dumparp(int, struct sysctl_req *);
 
+struct lltable *in_lltable_get(struct ifnet *ifp);
+struct lltable *in6_lltable_get(struct ifnet *ifp);
+struct lltable *lltable_get(struct ifnet *ifp, int family);
+
 size_t		llentry_free(struct llentry *);
 
 /* helper functions */
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 914ca57dee38..a504f54a026e 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1704,6 +1704,17 @@ in_lltattach(struct ifnet *ifp)
 	return (llt);
 }
 
+struct lltable *
+in_lltable_get(struct ifnet *ifp)
+{
+	struct lltable *llt = NULL;
+
+	void *afdata_ptr = ifp->if_afdata[AF_INET];
+	if (afdata_ptr != NULL)
+		llt = ((struct in_ifinfo *)afdata_ptr)->ii_llt;
+	return (llt);
+}
+
 void *
 in_domifattach(struct ifnet *ifp)
 {
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index feee4f3f64a5..3c03c2996d9b 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2483,6 +2483,17 @@ in6_lltattach(struct ifnet *ifp)
 	return (llt);
 }
 
+struct lltable *
+in6_lltable_get(struct ifnet *ifp)
+{
+	struct lltable *llt = NULL;
+
+	void *afdata_ptr = ifp->if_afdata[AF_INET6];
+	if (afdata_ptr != NULL)
+		llt = ((struct in6_ifextra *)afdata_ptr)->lltable;
+	return (llt);
+}
+
 void *
 in6_domifattach(struct ifnet *ifp)
 {