Track device's NUMA domain in ifnet & alloc ifnet from NUMA local memory
This commit adds new if_alloc_domain() and if_alloc_dev() methods to allocate ifnets. When called with a domain on a NUMA machine, ifalloc_domain() will record the NUMA domain in the ifnet, and it will allocate the ifnet struct from memory which is local to that NUMA node. Similarly, if_alloc_dev() is a wrapper for if_alloc_domain which uses a driver supplied device_t to call ifalloc_domain() with the appropriate domain. Note that the new if_numa_domain field fits in an alignment pad in struct ifnet, and so does not alter the size of the structure. Reviewed by: glebius, kib, markj Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D19930
This commit is contained in:
parent
613d28127b
commit
7687707dd4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=346579
@ -1175,6 +1175,8 @@ MLINKS+=iflibtxrx.9 isc_rxd_available.9 \
|
||||
iflibtxrx.9 isc_txd_flush.9
|
||||
MLINKS+=ifnet.9 if_addmulti.9 \
|
||||
ifnet.9 if_alloc.9 \
|
||||
ifnet.9 if_alloc_dev.9 \
|
||||
ifnet.9 if_alloc_domain.9 \
|
||||
ifnet.9 if_allmulti.9 \
|
||||
ifnet.9 if_attach.9 \
|
||||
ifnet.9 if_data.9 \
|
||||
|
@ -48,6 +48,10 @@
|
||||
.Ss "Interface Manipulation Functions"
|
||||
.Ft "struct ifnet *"
|
||||
.Fn if_alloc "u_char type"
|
||||
.Ft "struct ifnet *"
|
||||
.Fn if_alloc_dev "u_char type" "device_t dev"
|
||||
.Ft "struct ifnet *"
|
||||
.Fn if_alloc_domain "u_char type" "int numa_domain"
|
||||
.Ft void
|
||||
.Fn if_attach "struct ifnet *ifp"
|
||||
.Ft void
|
||||
@ -440,6 +444,15 @@ It is used to cache the type passed to
|
||||
but unlike
|
||||
.Va if_type ,
|
||||
it would not be changed by drivers.
|
||||
.It Va if_numa_domain
|
||||
.Pq Vt uint8_t
|
||||
The NUMA domain of the hardware device associated with the interface.
|
||||
This is filled in with a wildcard value unless the kernel is NUMA
|
||||
aware, the system is a NUMA system, and the ifnet is allocated
|
||||
using
|
||||
.Fn if_alloc_dev
|
||||
or
|
||||
.Fn if_alloc_domain .
|
||||
.El
|
||||
.Pp
|
||||
References to
|
||||
@ -1151,6 +1164,24 @@ include the allocation of a
|
||||
.Fa type
|
||||
specific structure in
|
||||
.Va if_l2com .
|
||||
.It Fn if_alloc_dev
|
||||
Allocate and initialize
|
||||
.Vt "struct ifnet"
|
||||
as
|
||||
.Fn if_alloc
|
||||
does, with the addition that the ifnet can be tagged with the
|
||||
appropriate NUMA domain derived from the
|
||||
.Fa dev
|
||||
argument passed by the caller.
|
||||
.It Fn if_alloc_domain
|
||||
Allocate and initialize
|
||||
.Vt "struct ifnet"
|
||||
as
|
||||
.Fn if_alloc
|
||||
does, with the addition that the ifnet will be tagged with the NUMA
|
||||
domain via the
|
||||
.Fa numa_domain
|
||||
argument passed by the caller.
|
||||
.It Fn if_attach
|
||||
Link the specified interface
|
||||
.Fa ifp
|
||||
@ -1168,7 +1199,10 @@ function.)
|
||||
The
|
||||
.Fa ifp
|
||||
must have been allocated by
|
||||
.Fn if_alloc .
|
||||
.Fn if_alloc ,
|
||||
.Fn if_alloc_dev
|
||||
or
|
||||
.Fn if_alloc_domain .
|
||||
.It Fn if_detach
|
||||
Shut down and unlink the specified
|
||||
.Fa ifp
|
||||
|
@ -1636,7 +1636,7 @@ cxgbe_vi_attach(device_t dev, struct vi_info *vi)
|
||||
callout_init(&vi->tick, 1);
|
||||
|
||||
/* Allocate an ifnet and set it up */
|
||||
ifp = if_alloc(IFT_ETHER);
|
||||
ifp = if_alloc_dev(IFT_ETHER, dev);
|
||||
if (ifp == NULL) {
|
||||
device_printf(dev, "Cannot allocate ifnet\n");
|
||||
return (ENOMEM);
|
||||
|
@ -3682,7 +3682,7 @@ mlx5e_create_ifp(struct mlx5_core_dev *mdev)
|
||||
M_MLX5EN, M_WAITOK | M_ZERO);
|
||||
mlx5e_priv_mtx_init(priv);
|
||||
|
||||
ifp = priv->ifp = if_alloc(IFT_ETHER);
|
||||
ifp = priv->ifp = if_alloc_dev(IFT_ETHER, mdev->pdev->dev.bsddev);
|
||||
if (ifp == NULL) {
|
||||
mlx5_core_err(mdev, "if_alloc() failed\n");
|
||||
goto err_free_priv;
|
||||
|
31
sys/net/if.c
31
sys/net/if.c
@ -39,6 +39,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/domainset.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/epoch.h>
|
||||
@ -526,13 +527,19 @@ if_grow(void)
|
||||
* registered for the passed type.
|
||||
*/
|
||||
struct ifnet *
|
||||
if_alloc(u_char type)
|
||||
if_alloc_domain(u_char type, int numa_domain)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
u_short idx;
|
||||
void *old;
|
||||
|
||||
ifp = malloc(sizeof(struct ifnet), M_IFNET, M_WAITOK|M_ZERO);
|
||||
KASSERT(numa_domain <= IF_NODOM, ("numa_domain too large"));
|
||||
if (numa_domain == IF_NODOM)
|
||||
ifp = malloc(sizeof(struct ifnet), M_IFNET,
|
||||
M_WAITOK | M_ZERO);
|
||||
else
|
||||
ifp = malloc_domainset(sizeof(struct ifnet), M_IFNET,
|
||||
DOMAINSET_PREF(numa_domain), M_WAITOK | M_ZERO);
|
||||
restart:
|
||||
IFNET_WLOCK();
|
||||
idx = ifindex_alloc(&old);
|
||||
@ -547,6 +554,7 @@ if_alloc(u_char type)
|
||||
ifp->if_index = idx;
|
||||
ifp->if_type = type;
|
||||
ifp->if_alloctype = type;
|
||||
ifp->if_numa_domain = numa_domain;
|
||||
#ifdef VIMAGE
|
||||
ifp->if_vnet = curvnet;
|
||||
#endif
|
||||
@ -580,6 +588,22 @@ if_alloc(u_char type)
|
||||
return (ifp);
|
||||
}
|
||||
|
||||
struct ifnet *
|
||||
if_alloc_dev(u_char type, device_t dev)
|
||||
{
|
||||
int numa_domain;
|
||||
|
||||
if (dev == NULL || bus_get_domain(dev, &numa_domain) != 0)
|
||||
return (if_alloc_domain(type, IF_NODOM));
|
||||
return (if_alloc_domain(type, numa_domain));
|
||||
}
|
||||
|
||||
struct ifnet *
|
||||
if_alloc(u_char type)
|
||||
{
|
||||
|
||||
return (if_alloc_domain(type, IF_NODOM));
|
||||
}
|
||||
/*
|
||||
* Do the actual work of freeing a struct ifnet, and layer 2 common
|
||||
* structure. This call is made when the last reference to an
|
||||
@ -608,7 +632,10 @@ if_free_internal(struct ifnet *ifp)
|
||||
|
||||
free(ifp->if_description, M_IFDESCR);
|
||||
free(ifp->if_hw_addr, M_IFADDR);
|
||||
if (ifp->if_numa_domain == IF_NODOM)
|
||||
free(ifp, M_IFNET);
|
||||
else
|
||||
free_domain(ifp, M_IFNET);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -244,7 +244,7 @@ struct ifnet {
|
||||
CK_STAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if (CK_) */
|
||||
/* protected by if_addr_lock */
|
||||
u_char if_alloctype; /* if_type at time of allocation */
|
||||
|
||||
uint8_t if_numa_domain; /* NUMA domain of device */
|
||||
/* Driver and protocol specific information that remains stable. */
|
||||
void *if_softc; /* pointer to driver state */
|
||||
void *if_llsoftc; /* link layer softc */
|
||||
@ -394,6 +394,7 @@ struct ifnet {
|
||||
/* for compatibility with other BSDs */
|
||||
#define if_name(ifp) ((ifp)->if_xname)
|
||||
|
||||
#define IF_NODOM 255
|
||||
/*
|
||||
* Locks for address lists on the network interface.
|
||||
*/
|
||||
@ -622,6 +623,8 @@ int if_delgroup(struct ifnet *, const char *);
|
||||
int if_addmulti(struct ifnet *, struct sockaddr *, struct ifmultiaddr **);
|
||||
int if_allmulti(struct ifnet *, int);
|
||||
struct ifnet* if_alloc(u_char);
|
||||
struct ifnet* if_alloc_dev(u_char, device_t dev);
|
||||
struct ifnet* if_alloc_domain(u_char, int numa_domain);
|
||||
void if_attach(struct ifnet *);
|
||||
void if_dead(struct ifnet *);
|
||||
int if_delmulti(struct ifnet *, struct sockaddr *);
|
||||
|
Loading…
Reference in New Issue
Block a user