diff --git a/sys/dev/netmap/netmap.c b/sys/dev/netmap/netmap.c --- a/sys/dev/netmap/netmap.c +++ b/sys/dev/netmap/netmap.c @@ -1621,6 +1621,35 @@ if (*na != NULL) /* valid match in netmap_get_bdg_na() */ goto out; + /* did the user ask for specific NUMA affinity? */ + if (nmd == NULL) { + struct nmreq_option *opt; + + opt = nmreq_getoption(hdr, NETMAP_REQ_OPT_NUMA_DOMAIN); + if (opt != NULL) { + struct nmreq_opt_numa_domain *numa; + int32_t domain; + + numa = (struct nmreq_opt_numa_domain *)opt; + domain = numa->nro_numa_domain; + if (domain < -1 || domain >= vm_ndomains) { + error = EINVAL; + goto out; + } + if (domain != -1) { + nmd = netmap_mem_get_allocator(-1, domain); + if (nmd == NULL) { + /* + * Failed to honour the + * REQ_OPT_NUMA_DOMAIN request. + */ + error = ENXIO; + goto out; + } + } + } + } + /* * This must be a hardware na, lookup the name in the system. * Note that by hardware we actually mean "it shows up in ifconfig". @@ -2818,6 +2847,7 @@ break; } } + /* find the interface and a reference */ error = netmap_get_na(hdr, &na, &ifp, nmd, 1 /* create */); /* keep reference */ @@ -4011,7 +4041,7 @@ if (na->nm_mem == NULL) { /* select an allocator based on IOMMU and NUMA affinity */ - na->nm_mem = netmap_mem_get_allocator(na); + na->nm_mem = netmap_mem_get_na_allocator(na); } if (na->nm_bdg_attach == NULL) /* no special nm_bdg_attach callback. On VALE diff --git a/sys/dev/netmap/netmap_kern.h b/sys/dev/netmap/netmap_kern.h --- a/sys/dev/netmap/netmap_kern.h +++ b/sys/dev/netmap/netmap_kern.h @@ -903,6 +903,7 @@ struct netmap_mem_d *nm_mem; struct netmap_mem_d *nm_mem_prev; struct netmap_lut na_lut; + int32_t na_numa_domain; /* additional information attached to this adapter * by other netmap subsystems. Currently used by diff --git a/sys/dev/netmap/netmap_mem2.h b/sys/dev/netmap/netmap_mem2.h --- a/sys/dev/netmap/netmap_mem2.h +++ b/sys/dev/netmap/netmap_mem2.h @@ -146,7 +146,8 @@ #define netmap_mem_get(d) __netmap_mem_get(d, __FUNCTION__, __LINE__) #define netmap_mem_put(d) __netmap_mem_put(d, __FUNCTION__, __LINE__) struct netmap_mem_d* __netmap_mem_get(struct netmap_mem_d *, const char *, int); -struct netmap_mem_d* netmap_mem_get_allocator(struct netmap_adapter *); +struct netmap_mem_d* netmap_mem_get_allocator(int, int); +struct netmap_mem_d* netmap_mem_get_na_allocator(struct netmap_adapter *); void __netmap_mem_put(struct netmap_mem_d *, const char *, int); struct netmap_mem_d* netmap_mem_find(nm_memid_t); unsigned netmap_mem_bufsize(struct netmap_mem_d *nmd); diff --git a/sys/dev/netmap/netmap_mem2.c b/sys/dev/netmap/netmap_mem2.c --- a/sys/dev/netmap/netmap_mem2.c +++ b/sys/dev/netmap/netmap_mem2.c @@ -1818,20 +1818,27 @@ return d; } -/* Reference IOMMU and NUMA local allocator - find existing or create new, - * for non-hw adapters, fall back to global allocator. - */ struct netmap_mem_d * -netmap_mem_get_allocator(struct netmap_adapter *na) +netmap_mem_get_na_allocator(struct netmap_adapter *na) { - int i, domain, err, grp_id; - struct netmap_mem_d *nmd; + int domain, grp_id; if (na == NULL || na->pdev == NULL) return netmap_mem_get(&nm_mem); domain = nm_numa_domain(na->pdev); grp_id = nm_iommu_group_id(na->pdev); + return (netmap_mem_get_allocator(grp_id, domain)); +} + +/* Reference IOMMU and NUMA local allocator - find existing or create new, + * for non-hw adapters, fall back to global allocator. + */ +struct netmap_mem_d * +netmap_mem_get_allocator(int grp_id, int domain) +{ + int i, err; + struct netmap_mem_d *nmd; NM_MTX_LOCK(nm_mem_list_lock); nmd = netmap_last_mem_d; diff --git a/sys/net/netmap.h b/sys/net/netmap.h --- a/sys/net/netmap.h +++ b/sys/net/netmap.h @@ -586,6 +586,11 @@ */ NETMAP_REQ_OPT_OFFSETS, + /* On NETMAP_REQ_REGISTER, override the NUMA affinity of the memory + * pool used for a hardware port. Ignored for other port types. + */ + NETMAP_REQ_OPT_NUMA_DOMAIN, + /* This is a marker to count the number of available options. * New options must be added above it. */ NETMAP_REQ_OPT_MAX, @@ -992,4 +997,14 @@ uint64_t nro_min_gap; }; +struct nmreq_opt_numa_domain { + struct nmreq_option nro_opt; + + /* the ID of the NUMA domain to use for memory allocations. A value of + * -1 means that the system will try to use the port's NUMA affinity + * info to select the domain. + */ + int32_t nro_numa_domain; +}; + #endif /* _NET_NETMAP_H_ */