The users of RSS shouldn't be directly concerned about hash -> CPU ID
mappings. Instead, they should be first mapping to an RSS bucket and then querying the RSS bucket -> CPU ID mapping to figure out the target CPU. When (if?) RSS rebalancing is implemented or some other (non round-robin) distribution of work from buckets to CPU IDs, various bits of code - both userland and kernel - will need to know how this mapping works. So, to support this: * Add a new function rss_m2bucket() - this maps an mbuf to a given bucket. Anything which is currently doing hash -> CPU work may instead wish to do hash -> bucket, and then query the bucket->cpuid map for which CPU it belongs on. Or, map it to a bucket, then re-pin that bucket -> CPU during a rebalance operation. * For userland applications which wish to exploit affinity to RSS buckets, the bucket -> CPU ID mapping is now available via a sysctl. net.inet.rss.bucket_mapping lists the bucket to CPU ID mapping via a list of bucket:cpu pairs.
This commit is contained in:
parent
b924fc0363
commit
8bde802a2b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=266737
@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/smp.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/sbuf.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
@ -424,6 +425,24 @@ rss_hash2cpuid(uint32_t hash_val, uint32_t hash_type)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Query the RSS bucket associated with the given hash value and
|
||||
* type.
|
||||
*/
|
||||
int
|
||||
rss_hash2bucket(uint32_t hash_val, uint32_t hash_type, uint32_t *bucket_id)
|
||||
{
|
||||
|
||||
switch (hash_type) {
|
||||
case M_HASHTYPE_RSS_IPV4:
|
||||
case M_HASHTYPE_RSS_TCP_IPV4:
|
||||
*bucket_id = rss_getbucket(hash_val);
|
||||
return (0);
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* netisr CPU affinity lookup routine for use by protocols.
|
||||
*/
|
||||
@ -436,6 +455,16 @@ rss_m2cpuid(struct mbuf *m, uintptr_t source, u_int *cpuid)
|
||||
return (m);
|
||||
}
|
||||
|
||||
int
|
||||
rss_m2bucket(struct mbuf *m, uint32_t *bucket_id)
|
||||
{
|
||||
|
||||
M_ASSERTPKTHDR(m);
|
||||
|
||||
return(rss_hash2bucket(m->m_pkthdr.flowid, M_HASHTYPE_GET(m),
|
||||
bucket_id));
|
||||
}
|
||||
|
||||
/*
|
||||
* Query the RSS hash algorithm.
|
||||
*/
|
||||
@ -512,3 +541,31 @@ sysctl_rss_key(SYSCTL_HANDLER_ARGS)
|
||||
SYSCTL_PROC(_net_inet_rss, OID_AUTO, key,
|
||||
CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, sysctl_rss_key,
|
||||
"", "RSS keying material");
|
||||
|
||||
static int
|
||||
sysctl_rss_bucket_mapping(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct sbuf *sb;
|
||||
int error;
|
||||
int i;
|
||||
|
||||
error = 0;
|
||||
error = sysctl_wire_old_buffer(req, 0);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
sb = sbuf_new_for_sysctl(NULL, NULL, 512, req);
|
||||
if (sb == NULL)
|
||||
return (ENOMEM);
|
||||
for (i = 0; i < rss_buckets; i++) {
|
||||
sbuf_printf(sb, "%s%d:%d", i == 0 ? "" : " ",
|
||||
i,
|
||||
rss_getcpu(i));
|
||||
}
|
||||
error = sbuf_finish(sb);
|
||||
sbuf_delete(sb);
|
||||
|
||||
return (error);
|
||||
}
|
||||
SYSCTL_PROC(_net_inet_rss, OID_AUTO, bucket_mapping,
|
||||
CTLTYPE_STRING | CTLFLAG_RD, NULL, 0,
|
||||
sysctl_rss_bucket_mapping, "", "RSS bucket -> CPU mapping");
|
||||
|
@ -91,5 +91,8 @@ uint32_t rss_hash_ip6_2tuple(struct in6_addr src,
|
||||
*/
|
||||
struct mbuf *rss_m2cpuid(struct mbuf *m, uintptr_t source, u_int *cpuid);
|
||||
u_int rss_hash2cpuid(uint32_t hash_val, uint32_t hash_type);
|
||||
int rss_hash2bucket(uint32_t hash_val, uint32_t hash_type,
|
||||
uint32_t *bucket_id);
|
||||
int rss_m2bucket(struct mbuf *m, uint32_t *bucket_id);
|
||||
|
||||
#endif /* !_NETINET_IN_RSS_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user