net: wangxun: add RSS reta and rxfh fields support

Add ethtool ops for Rx flow hashing, query and set RSS indirection table
and hash key. Disable UDP RSS by default, and support to configure L4
header fields with TCP/UDP/SCTP for flow hasing.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Link: https://patch.msgid.link/20250926023843.34340-4-jiawenwu@trustnetic.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jiawen Wu
2025-09-26 10:38:42 +08:00
committed by Jakub Kicinski
parent 58f244b256
commit 2556f80a6a
6 changed files with 167 additions and 2 deletions

View File

@@ -481,6 +481,142 @@ int wx_set_channels(struct net_device *dev,
}
EXPORT_SYMBOL(wx_set_channels);
u32 wx_rss_indir_size(struct net_device *netdev)
{
struct wx *wx = netdev_priv(netdev);
return wx_rss_indir_tbl_entries(wx);
}
EXPORT_SYMBOL(wx_rss_indir_size);
u32 wx_get_rxfh_key_size(struct net_device *netdev)
{
return WX_RSS_KEY_SIZE;
}
EXPORT_SYMBOL(wx_get_rxfh_key_size);
static void wx_get_reta(struct wx *wx, u32 *indir)
{
u32 reta_size = wx_rss_indir_tbl_entries(wx);
u16 rss_m = wx->ring_feature[RING_F_RSS].mask;
if (test_bit(WX_FLAG_SRIOV_ENABLED, wx->flags))
rss_m = wx->ring_feature[RING_F_RSS].indices - 1;
for (u32 i = 0; i < reta_size; i++)
indir[i] = wx->rss_indir_tbl[i] & rss_m;
}
int wx_get_rxfh(struct net_device *netdev,
struct ethtool_rxfh_param *rxfh)
{
struct wx *wx = netdev_priv(netdev);
rxfh->hfunc = ETH_RSS_HASH_TOP;
if (rxfh->indir)
wx_get_reta(wx, rxfh->indir);
if (rxfh->key)
memcpy(rxfh->key, wx->rss_key, WX_RSS_KEY_SIZE);
return 0;
}
EXPORT_SYMBOL(wx_get_rxfh);
int wx_set_rxfh(struct net_device *netdev,
struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack)
{
struct wx *wx = netdev_priv(netdev);
u32 reta_entries, i;
if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
rxfh->hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP;
reta_entries = wx_rss_indir_tbl_entries(wx);
/* Fill out the redirection table */
if (rxfh->indir) {
for (i = 0; i < reta_entries; i++)
wx->rss_indir_tbl[i] = rxfh->indir[i];
wx_store_reta(wx);
}
/* Fill out the rss hash key */
if (rxfh->key) {
memcpy(wx->rss_key, rxfh->key, WX_RSS_KEY_SIZE);
wx_store_rsskey(wx);
}
return 0;
}
EXPORT_SYMBOL(wx_set_rxfh);
static const struct wx_rss_flow_map rss_flow_table[] = {
{ TCP_V4_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV4_TCP },
{ TCP_V6_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV6_TCP },
{ UDP_V4_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV4_UDP },
{ UDP_V6_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV6_UDP },
{ SCTP_V4_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV4_SCTP },
{ SCTP_V6_FLOW, RXH_L4_B_0_1 | RXH_L4_B_2_3, WX_RSS_FIELD_IPV6_SCTP },
};
int wx_get_rxfh_fields(struct net_device *dev,
struct ethtool_rxfh_fields *nfc)
{
struct wx *wx = netdev_priv(dev);
nfc->data = RXH_IP_SRC | RXH_IP_DST;
for (u32 i = 0; i < ARRAY_SIZE(rss_flow_table); i++) {
const struct wx_rss_flow_map *entry = &rss_flow_table[i];
if (entry->flow_type == nfc->flow_type) {
if (wx->rss_flags & entry->flag)
nfc->data |= entry->data;
break;
}
}
return 0;
}
EXPORT_SYMBOL(wx_get_rxfh_fields);
int wx_set_rxfh_fields(struct net_device *dev,
const struct ethtool_rxfh_fields *nfc,
struct netlink_ext_ack *extack)
{
struct wx *wx = netdev_priv(dev);
u8 flags = wx->rss_flags;
if (!(nfc->data & RXH_IP_SRC) ||
!(nfc->data & RXH_IP_DST))
return -EINVAL;
for (u32 i = 0; i < ARRAY_SIZE(rss_flow_table); i++) {
const struct wx_rss_flow_map *entry = &rss_flow_table[i];
if (entry->flow_type == nfc->flow_type) {
if (nfc->data & entry->data)
flags |= entry->flag;
else
flags &= ~entry->flag;
if (flags != wx->rss_flags) {
wx->rss_flags = flags;
wx_config_rss_field(wx);
}
return 0;
}
}
return -EINVAL;
}
EXPORT_SYMBOL(wx_set_rxfh_fields);
u32 wx_get_msglevel(struct net_device *netdev)
{
struct wx *wx = netdev_priv(netdev);

View File

@@ -38,6 +38,18 @@ void wx_get_channels(struct net_device *dev,
struct ethtool_channels *ch);
int wx_set_channels(struct net_device *dev,
struct ethtool_channels *ch);
u32 wx_rss_indir_size(struct net_device *netdev);
u32 wx_get_rxfh_key_size(struct net_device *netdev);
int wx_get_rxfh(struct net_device *netdev,
struct ethtool_rxfh_param *rxfh);
int wx_set_rxfh(struct net_device *netdev,
struct ethtool_rxfh_param *rxfh,
struct netlink_ext_ack *extack);
int wx_get_rxfh_fields(struct net_device *dev,
struct ethtool_rxfh_fields *cmd);
int wx_set_rxfh_fields(struct net_device *dev,
const struct ethtool_rxfh_fields *nfc,
struct netlink_ext_ack *extack);
u32 wx_get_msglevel(struct net_device *netdev);
void wx_set_msglevel(struct net_device *netdev, u32 data);
int wx_get_ts_info(struct net_device *dev,

View File

@@ -2449,8 +2449,7 @@ int wx_sw_init(struct wx *wx)
return err;
}
wx->rss_flags = WX_RSS_FIELD_IPV4 | WX_RSS_FIELD_IPV4_TCP |
WX_RSS_FIELD_IPV6 | WX_RSS_FIELD_IPV6_TCP |
WX_RSS_FIELD_IPV4_UDP | WX_RSS_FIELD_IPV6_UDP;
WX_RSS_FIELD_IPV6 | WX_RSS_FIELD_IPV6_TCP;
wx->mac_table = kcalloc(wx->mac.num_rar_entries,
sizeof(struct wx_mac_addr),

View File

@@ -1208,6 +1208,12 @@ struct vf_macvlans {
#define WX_RSS_FIELD_IPV4_UDP BIT(6)
#define WX_RSS_FIELD_IPV6_UDP BIT(7)
struct wx_rss_flow_map {
u8 flow_type;
u32 data;
u8 flag;
};
enum wx_pf_flags {
WX_FLAG_MULTI_64_FUNC,
WX_FLAG_SWFW_RING,

View File

@@ -137,6 +137,12 @@ static const struct ethtool_ops ngbe_ethtool_ops = {
.set_coalesce = wx_set_coalesce,
.get_channels = wx_get_channels,
.set_channels = ngbe_set_channels,
.get_rxfh_fields = wx_get_rxfh_fields,
.set_rxfh_fields = wx_set_rxfh_fields,
.get_rxfh_indir_size = wx_rss_indir_size,
.get_rxfh_key_size = wx_get_rxfh_key_size,
.get_rxfh = wx_get_rxfh,
.set_rxfh = wx_set_rxfh,
.get_msglevel = wx_get_msglevel,
.set_msglevel = wx_set_msglevel,
.get_ts_info = wx_get_ts_info,

View File

@@ -560,6 +560,12 @@ static const struct ethtool_ops txgbe_ethtool_ops = {
.set_channels = txgbe_set_channels,
.get_rxnfc = txgbe_get_rxnfc,
.set_rxnfc = txgbe_set_rxnfc,
.get_rxfh_fields = wx_get_rxfh_fields,
.set_rxfh_fields = wx_set_rxfh_fields,
.get_rxfh_indir_size = wx_rss_indir_size,
.get_rxfh_key_size = wx_get_rxfh_key_size,
.get_rxfh = wx_get_rxfh,
.set_rxfh = wx_set_rxfh,
.get_msglevel = wx_get_msglevel,
.set_msglevel = wx_set_msglevel,
.get_ts_info = wx_get_ts_info,