git: 7b40b00fad16 - main - ifnet: merge ifindex_alloc(), ifnet_setbyindex(), if_grow() and call magic
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 06 Dec 2021 17:32:48 UTC
The branch main has been updated by glebius:
URL: https://cgit.FreeBSD.org/src/commit/?id=7b40b00fad1606eaa98a7b116ba8651221d55f62
commit 7b40b00fad1606eaa98a7b116ba8651221d55f62
Author: Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2021-12-04 17:49:35 +0000
Commit: Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2021-12-06 17:32:31 +0000
ifnet: merge ifindex_alloc(), ifnet_setbyindex(), if_grow() and call magic
Now it is possible to just merge all this complexity into single
linear function. Note that IFNET_WLOCK() is a sleepable lock, so
we can M_WAITOK and epoch_wait_preempt().
Reviewed by: melifaro, bz, kp
Differential revision: https://reviews.freebsd.org/D33262
---
sys/net/if.c | 95 ++++++++++++++----------------------------------------------
1 file changed, 21 insertions(+), 74 deletions(-)
diff --git a/sys/net/if.c b/sys/net/if.c
index 079ad734812b..ad6d0bcf827a 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -273,7 +273,6 @@ struct mbuf *(*tbr_dequeue_ptr)(struct ifaltq *, int) = NULL;
static void if_attachdomain(void *);
static void if_attachdomain1(struct ifnet *);
static int ifconf(u_long, caddr_t);
-static void *if_grow(void);
static void if_input_default(struct ifnet *, struct mbuf *);
static int if_requestencap_default(struct ifnet *, struct if_encap_req *);
static void if_route(struct ifnet *, int flag, int fam);
@@ -369,15 +368,14 @@ ifnet_byindex_ref(u_short idx)
}
/*
- * Allocate an ifindex array entry; return 0 on success or an error on
- * failure.
+ * Allocate an ifindex array entry.
*/
-static u_short
-ifindex_alloc(void **old)
+static void
+ifindex_alloc(struct ifnet *ifp)
{
u_short idx;
- IFNET_WLOCK_ASSERT();
+ IFNET_WLOCK();
/*
* Try to find an empty slot below V_if_index. If we fail, take the
* next slot.
@@ -389,12 +387,24 @@ ifindex_alloc(void **old)
/* Catch if_index overflow. */
if (idx >= V_if_indexlim) {
- *old = if_grow();
- return (USHRT_MAX);
+ struct ifnet **new, **old;
+ int newlim;
+
+ newlim = V_if_indexlim * 2;
+ new = malloc(newlim * sizeof(*new), M_IFNET, M_WAITOK | M_ZERO);
+ memcpy(new, V_ifindex_table, V_if_indexlim * sizeof(*new));
+ old = V_ifindex_table;
+ ck_pr_store_ptr(&V_ifindex_table, new);
+ V_if_indexlim = newlim;
+ epoch_wait_preempt(net_epoch_preempt);
+ free(old, M_IFNET);
}
if (idx > V_if_index)
V_if_index = idx;
- return (idx);
+
+ ifp->if_index = idx;
+ ck_pr_store_ptr(&V_ifindex_table[idx], ifp);
+ IFNET_WUNLOCK();
}
static void
@@ -409,14 +419,6 @@ ifindex_free(u_short idx)
V_if_index--;
}
-static void
-ifnet_setbyindex(u_short idx, struct ifnet *ifp)
-{
-
- ifp->if_index = idx;
- ck_pr_store_ptr(&V_ifindex_table[idx], ifp);
-}
-
struct ifaddr *
ifaddr_byindex(u_short idx)
{
@@ -549,34 +551,6 @@ VNET_SYSUNINIT(vnet_if_return, SI_SUB_VNET_DONE, SI_ORDER_ANY,
vnet_if_return, NULL);
#endif
-static void *
-if_grow(void)
-{
- int oldlim;
- u_int n;
- struct ifnet **e;
- void *old;
-
- old = NULL;
- IFNET_WLOCK_ASSERT();
- oldlim = V_if_indexlim;
- IFNET_WUNLOCK();
- n = (oldlim << 1) * sizeof(*e);
- e = malloc(n, M_IFNET, M_WAITOK | M_ZERO);
- IFNET_WLOCK();
- if (V_if_indexlim != oldlim) {
- free(e, M_IFNET);
- return (NULL);
- }
- if (V_ifindex_table != NULL) {
- memcpy((caddr_t)e, (caddr_t)V_ifindex_table, n/2);
- old = V_ifindex_table;
- }
- V_if_indexlim <<= 1;
- V_ifindex_table = e;
- return (old);
-}
-
/*
* Allocate a struct ifnet and an index for an interface. A layer 2
* common structure will also be allocated if an allocation routine is
@@ -586,8 +560,6 @@ static struct ifnet *
if_alloc_domain(u_char type, int numa_domain)
{
struct ifnet *ifp;
- u_short idx;
- void *old;
KASSERT(numa_domain <= IF_NODOM, ("numa_domain too large"));
if (numa_domain == IF_NODOM)
@@ -627,17 +599,7 @@ if_alloc_domain(u_char type, int numa_domain)
ifp->if_get_counter = if_get_counter_default;
ifp->if_pcp = IFNET_PCP_NONE;
-restart:
- IFNET_WLOCK();
- idx = ifindex_alloc(&old);
- if (__predict_false(idx == USHRT_MAX)) {
- IFNET_WUNLOCK();
- epoch_wait_preempt(net_epoch_preempt);
- free(old, M_IFNET);
- goto restart;
- }
- ifnet_setbyindex(idx, ifp);
- IFNET_WUNLOCK();
+ ifindex_alloc(ifp);
return (ifp);
}
@@ -1301,9 +1263,6 @@ finish_vnet_shutdown:
/*
* if_vmove() performs a limited version of if_detach() in current
* vnet and if_attach()es the ifnet to the vnet specified as 2nd arg.
- * An attempt is made to shrink if_index in current vnet, find an
- * unused if_index in target vnet and calls if_grow() if necessary,
- * and finally find an unused if_xname for the target vnet.
*/
static int
if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
@@ -1312,7 +1271,6 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
#ifdef DEV_BPF
u_int bif_dlt, bif_hdrlen;
#endif
- void *old;
int rc;
#ifdef DEV_BPF
@@ -1355,18 +1313,7 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
* Switch to the context of the target vnet.
*/
CURVNET_SET_QUIET(new_vnet);
- restart:
- IFNET_WLOCK();
- ifp->if_index = ifindex_alloc(&old);
- if (__predict_false(ifp->if_index == USHRT_MAX)) {
- IFNET_WUNLOCK();
- epoch_wait_preempt(net_epoch_preempt);
- free(old, M_IFNET);
- goto restart;
- }
- ifnet_setbyindex(ifp->if_index, ifp);
- IFNET_WUNLOCK();
-
+ ifindex_alloc(ifp);
if_attach_internal(ifp, 1, ifc);
#ifdef DEV_BPF