cxgbe(4): support for the kernel RSS option.

You need PCBGROUP and RSS in the kernel config to use this.

Relnotes:	Yes
Sponsored by:	Chelsio Communications
This commit is contained in:
Navdeep Parhar 2015-10-16 01:19:55 +00:00
parent b7a581eaa6
commit 07d684f712
2 changed files with 181 additions and 5 deletions

View File

@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_rss.h"
#include <sys/param.h>
#include <sys/conf.h>
@ -55,6 +56,9 @@ __FBSDID("$FreeBSD$");
#include <net/if_types.h>
#include <net/if_dl.h>
#include <net/if_vlan_var.h>
#ifdef RSS
#include <net/rss_config.h>
#endif
#if defined(__i386__) || defined(__amd64__)
#include <vm/vm.h>
#include <vm/pmap.h>
@ -3464,6 +3468,71 @@ adapter_full_uninit(struct adapter *sc)
return (0);
}
#ifdef RSS
#define SUPPORTED_RSS_HASHTYPES (RSS_HASHTYPE_RSS_IPV4 | \
RSS_HASHTYPE_RSS_TCP_IPV4 | RSS_HASHTYPE_RSS_IPV6 | \
RSS_HASHTYPE_RSS_TCP_IPV6 | RSS_HASHTYPE_RSS_UDP_IPV4 | \
RSS_HASHTYPE_RSS_UDP_IPV6)
/* Translates kernel hash types to hardware. */
static int
hashconfig_to_hashen(int hashconfig)
{
int hashen = 0;
if (hashconfig & RSS_HASHTYPE_RSS_IPV4)
hashen |= F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN;
if (hashconfig & RSS_HASHTYPE_RSS_IPV6)
hashen |= F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN;
if (hashconfig & RSS_HASHTYPE_RSS_UDP_IPV4) {
hashen |= F_FW_RSS_VI_CONFIG_CMD_UDPEN |
F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN;
}
if (hashconfig & RSS_HASHTYPE_RSS_UDP_IPV6) {
hashen |= F_FW_RSS_VI_CONFIG_CMD_UDPEN |
F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN;
}
if (hashconfig & RSS_HASHTYPE_RSS_TCP_IPV4)
hashen |= F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN;
if (hashconfig & RSS_HASHTYPE_RSS_TCP_IPV6)
hashen |= F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN;
return (hashen);
}
/* Translates hardware hash types to kernel. */
static int
hashen_to_hashconfig(int hashen)
{
int hashconfig = 0;
if (hashen & F_FW_RSS_VI_CONFIG_CMD_UDPEN) {
/*
* If UDP hashing was enabled it must have been enabled for
* either IPv4 or IPv6 (inclusive or). Enabling UDP without
* enabling any 4-tuple hash is nonsense configuration.
*/
MPASS(hashen & (F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN |
F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN));
if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN)
hashconfig |= RSS_HASHTYPE_RSS_UDP_IPV4;
if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN)
hashconfig |= RSS_HASHTYPE_RSS_UDP_IPV6;
}
if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN)
hashconfig |= RSS_HASHTYPE_RSS_TCP_IPV4;
if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN)
hashconfig |= RSS_HASHTYPE_RSS_TCP_IPV6;
if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN)
hashconfig |= RSS_HASHTYPE_RSS_IPV4;
if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN)
hashconfig |= RSS_HASHTYPE_RSS_IPV6;
return (hashconfig);
}
#endif
int
port_full_init(struct port_info *pi)
{
@ -3471,7 +3540,14 @@ port_full_init(struct port_info *pi)
struct ifnet *ifp = pi->ifp;
uint16_t *rss;
struct sge_rxq *rxq;
int rc, i, j;
int rc, i, j, hashen;
#ifdef RSS
int nbuckets = rss_getnumbuckets();
int hashconfig = rss_gethashconfig();
int extra;
uint32_t raw_rss_key[RSS_KEYSIZE / sizeof(uint32_t)];
uint32_t rss_key[RSS_KEYSIZE / sizeof(uint32_t)];
#endif
ASSERT_SYNCHRONIZED_OP(sc);
KASSERT((pi->flags & PORT_INIT_DONE) == 0,
@ -3490,13 +3566,42 @@ port_full_init(struct port_info *pi)
/*
* Setup RSS for this port. Save a copy of the RSS table for later use.
*/
if (pi->nrxq > pi->rss_size) {
if_printf(ifp, "nrxq (%d) > hw RSS table size (%d); "
"some queues will never receive traffic.\n", pi->nrxq,
pi->rss_size);
} else if (pi->rss_size % pi->nrxq) {
if_printf(ifp, "nrxq (%d), hw RSS table size (%d); "
"expect uneven traffic distribution.\n", pi->nrxq,
pi->rss_size);
}
#ifdef RSS
MPASS(RSS_KEYSIZE == 40);
if (pi->nrxq != nbuckets) {
if_printf(ifp, "nrxq (%d) != kernel RSS buckets (%d);"
"performance will be impacted.\n", pi->nrxq, nbuckets);
}
rss_getkey((void *)&raw_rss_key[0]);
for (i = 0; i < nitems(rss_key); i++) {
rss_key[i] = htobe32(raw_rss_key[nitems(rss_key) - 1 - i]);
}
t4_write_rss_key(sc, (void *)&rss_key[0], -1);
#endif
rss = malloc(pi->rss_size * sizeof (*rss), M_CXGBE, M_ZERO | M_WAITOK);
for (i = 0; i < pi->rss_size;) {
#ifdef RSS
j = rss_get_indirection_to_bucket(i);
j %= pi->nrxq;
rxq = &sc->sge.rxq[pi->first_rxq + j];
rss[i++] = rxq->iq.abs_id;
#else
for_each_rxq(pi, j, rxq) {
rss[i++] = rxq->iq.abs_id;
if (i == pi->rss_size)
break;
}
#endif
}
rc = -t4_config_rss_range(sc, sc->mbox, pi->viid, 0, pi->rss_size, rss,
@ -3506,6 +3611,54 @@ port_full_init(struct port_info *pi)
goto done;
}
#ifdef RSS
hashen = hashconfig_to_hashen(hashconfig);
/*
* We may have had to enable some hashes even though the global config
* wants them disabled. This is a potential problem that must be
* reported to the user.
*/
extra = hashen_to_hashconfig(hashen) ^ hashconfig;
/*
* If we consider only the supported hash types, then the enabled hashes
* are a superset of the requested hashes. In other words, there cannot
* be any supported hash that was requested but not enabled, but there
* can be hashes that were not requested but had to be enabled.
*/
extra &= SUPPORTED_RSS_HASHTYPES;
MPASS((extra & hashconfig) == 0);
if (extra) {
if_printf(ifp,
"global RSS config (0x%x) cannot be accomodated.\n",
hashconfig);
}
if (extra & RSS_HASHTYPE_RSS_IPV4)
if_printf(ifp, "IPv4 2-tuple hashing forced on.\n");
if (extra & RSS_HASHTYPE_RSS_TCP_IPV4)
if_printf(ifp, "TCP/IPv4 4-tuple hashing forced on.\n");
if (extra & RSS_HASHTYPE_RSS_IPV6)
if_printf(ifp, "IPv6 2-tuple hashing forced on.\n");
if (extra & RSS_HASHTYPE_RSS_TCP_IPV6)
if_printf(ifp, "TCP/IPv6 4-tuple hashing forced on.\n");
if (extra & RSS_HASHTYPE_RSS_UDP_IPV4)
if_printf(ifp, "UDP/IPv4 4-tuple hashing forced on.\n");
if (extra & RSS_HASHTYPE_RSS_UDP_IPV6)
if_printf(ifp, "UDP/IPv6 4-tuple hashing forced on.\n");
#else
hashen = F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN |
F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN |
F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN |
F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN | F_FW_RSS_VI_CONFIG_CMD_UDPEN;
#endif
rc = -t4_config_vi_rss(sc, sc->mbox, pi->viid, hashen, rss[0]);
if (rc != 0) {
if_printf(ifp, "rss hash/defaultq config failed: %d\n", rc);
goto done;
}
pi->rss = rss;
pi->flags |= PORT_INIT_DONE;
done:
@ -8380,17 +8533,39 @@ tweak_tunables(void)
{
int nc = mp_ncpus; /* our snapshot of the number of CPUs */
if (t4_ntxq10g < 1)
if (t4_ntxq10g < 1) {
#ifdef RSS
t4_ntxq10g = rss_getnumbuckets();
#else
t4_ntxq10g = min(nc, NTXQ_10G);
#endif
}
if (t4_ntxq1g < 1)
if (t4_ntxq1g < 1) {
#ifdef RSS
/* XXX: way too many for 1GbE? */
t4_ntxq1g = rss_getnumbuckets();
#else
t4_ntxq1g = min(nc, NTXQ_1G);
#endif
}
if (t4_nrxq10g < 1)
if (t4_nrxq10g < 1) {
#ifdef RSS
t4_nrxq10g = rss_getnumbuckets();
#else
t4_nrxq10g = min(nc, NRXQ_10G);
#endif
}
if (t4_nrxq1g < 1)
if (t4_nrxq1g < 1) {
#ifdef RSS
/* XXX: way too many for 1GbE? */
t4_nrxq1g = rss_getnumbuckets();
#else
t4_nrxq1g = min(nc, NRXQ_1G);
#endif
}
#ifdef TCP_OFFLOAD
if (t4_nofldtxq10g < 1)

View File

@ -11,6 +11,7 @@ SRCS+= device_if.h
SRCS+= opt_inet.h
SRCS+= opt_inet6.h
SRCS+= opt_ofed.h
SRCS+= opt_rss.h
SRCS+= pci_if.h
SRCS+= t4_hw.c
SRCS+= t4_l2t.c