mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-13 01:39:06 +08:00
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:
committed by
Jakub Kicinski
parent
58f244b256
commit
2556f80a6a
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user