aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2021-12-26 12:39:26 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2022-03-28 15:25:02 +0000
commitfdd84c3608425e769e478ff18759f8a6870e160a (patch)
treed5e4fc899445cef74a4bd27ea34d259b22fcd95d
parent3e624dfad1c3dbbca711da6fb79caffb8dcc4d91 (diff)
downloadsrc-fdd84c3608425e769e478ff18759f8a6870e160a.tar.gz
src-fdd84c3608425e769e478ff18759f8a6870e160a.zip
[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 Approved by: re(gjb) MFC after: 2 weeks (cherry picked from commit ff3a85d32411cdd7894f932b1d3d7ce01ec7a648) (cherry picked from commit ffcca53561ed0b3d4755dbd2ce1d9942ea4a468e)
-rw-r--r--sys/net/if_llatbl.c26
-rw-r--r--sys/net/if_llatbl.h4
-rw-r--r--sys/netinet/in.c11
-rw-r--r--sys/netinet6/in6.c11
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
@@ -713,6 +713,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 5448c3b5fccd..2303a8f10aa4 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1695,6 +1695,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 d54aba58edb6..41b05ae2ca53 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2462,6 +2462,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)
{