mirror of https://gitee.com/openkylin/linux.git
bnx2x: Add support for 4-tupple UDP RSS
This change enables to control via ethtool whether to do UDP RSS on 2-tupple (IP source / destination only) or on 4-tupple (include UDP source / destination port). It also enables to read back the RSS configuration. Signed-off-by: Merav Sicron <meravs@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
cf2c1df62e
commit
5d317c6a95
|
@ -1666,14 +1666,13 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp)
|
|||
static int bnx2x_init_rss_pf(struct bnx2x *bp)
|
||||
{
|
||||
int i;
|
||||
u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
|
||||
u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
|
||||
|
||||
/* Prepare the initial contents fo the indirection table if RSS is
|
||||
* enabled
|
||||
*/
|
||||
for (i = 0; i < sizeof(ind_table); i++)
|
||||
ind_table[i] =
|
||||
for (i = 0; i < sizeof(bp->rss_conf_obj.ind_table); i++)
|
||||
bp->rss_conf_obj.ind_table[i] =
|
||||
bp->fp->cl_id +
|
||||
ethtool_rxfh_indir_default(i, num_eth_queues);
|
||||
|
||||
|
@ -1685,12 +1684,11 @@ static int bnx2x_init_rss_pf(struct bnx2x *bp)
|
|||
* For 57712 and newer on the other hand it's a per-function
|
||||
* configuration.
|
||||
*/
|
||||
return bnx2x_config_rss_eth(bp, ind_table,
|
||||
bp->port.pmf || !CHIP_IS_E1x(bp));
|
||||
return bnx2x_config_rss_eth(bp, bp->port.pmf || !CHIP_IS_E1x(bp));
|
||||
}
|
||||
|
||||
int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
|
||||
u8 *ind_table, bool config_hash)
|
||||
bool config_hash)
|
||||
{
|
||||
struct bnx2x_config_rss_params params = {NULL};
|
||||
int i;
|
||||
|
@ -1713,11 +1711,15 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
|
|||
__set_bit(BNX2X_RSS_IPV4_TCP, ¶ms.rss_flags);
|
||||
__set_bit(BNX2X_RSS_IPV6, ¶ms.rss_flags);
|
||||
__set_bit(BNX2X_RSS_IPV6_TCP, ¶ms.rss_flags);
|
||||
if (rss_obj->udp_rss_v4)
|
||||
__set_bit(BNX2X_RSS_IPV4_UDP, ¶ms.rss_flags);
|
||||
if (rss_obj->udp_rss_v6)
|
||||
__set_bit(BNX2X_RSS_IPV6_UDP, ¶ms.rss_flags);
|
||||
|
||||
/* Hash bits */
|
||||
params.rss_result_mask = MULTI_MASK;
|
||||
|
||||
memcpy(params.ind_table, ind_table, sizeof(params.ind_table));
|
||||
memcpy(params.ind_table, rss_obj->ind_table, sizeof(params.ind_table));
|
||||
|
||||
if (config_hash) {
|
||||
/* RSS keys */
|
||||
|
|
|
@ -94,7 +94,7 @@ void bnx2x_send_unload_done(struct bnx2x *bp);
|
|||
* @config_hash: re-configure RSS hash keys configuration
|
||||
*/
|
||||
int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj,
|
||||
u8 *ind_table, bool config_hash);
|
||||
bool config_hash);
|
||||
|
||||
/**
|
||||
* bnx2x__init_func_obj - init function object
|
||||
|
@ -865,11 +865,9 @@ static inline int func_by_vn(struct bnx2x *bp, int vn)
|
|||
return 2 * vn + BP_PORT(bp);
|
||||
}
|
||||
|
||||
static inline int bnx2x_config_rss_eth(struct bnx2x *bp, u8 *ind_table,
|
||||
bool config_hash)
|
||||
static inline int bnx2x_config_rss_eth(struct bnx2x *bp, bool config_hash)
|
||||
{
|
||||
return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, ind_table,
|
||||
config_hash);
|
||||
return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, config_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2600,6 +2600,41 @@ static int bnx2x_set_phys_id(struct net_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int bnx2x_get_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info)
|
||||
{
|
||||
|
||||
switch (info->flow_type) {
|
||||
case TCP_V4_FLOW:
|
||||
case TCP_V6_FLOW:
|
||||
info->data = RXH_IP_SRC | RXH_IP_DST |
|
||||
RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
||||
break;
|
||||
case UDP_V4_FLOW:
|
||||
if (bp->rss_conf_obj.udp_rss_v4)
|
||||
info->data = RXH_IP_SRC | RXH_IP_DST |
|
||||
RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
||||
else
|
||||
info->data = RXH_IP_SRC | RXH_IP_DST;
|
||||
break;
|
||||
case UDP_V6_FLOW:
|
||||
if (bp->rss_conf_obj.udp_rss_v6)
|
||||
info->data = RXH_IP_SRC | RXH_IP_DST |
|
||||
RXH_L4_B_0_1 | RXH_L4_B_2_3;
|
||||
else
|
||||
info->data = RXH_IP_SRC | RXH_IP_DST;
|
||||
break;
|
||||
case IPV4_FLOW:
|
||||
case IPV6_FLOW:
|
||||
info->data = RXH_IP_SRC | RXH_IP_DST;
|
||||
break;
|
||||
default:
|
||||
info->data = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
|
||||
u32 *rules __always_unused)
|
||||
{
|
||||
|
@ -2609,7 +2644,102 @@ static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
|
|||
case ETHTOOL_GRXRINGS:
|
||||
info->data = BNX2X_NUM_ETH_QUEUES(bp);
|
||||
return 0;
|
||||
case ETHTOOL_GRXFH:
|
||||
return bnx2x_get_rss_flags(bp, info);
|
||||
default:
|
||||
DP(BNX2X_MSG_ETHTOOL, "Command parameters not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info)
|
||||
{
|
||||
int udp_rss_requested;
|
||||
|
||||
DP(BNX2X_MSG_ETHTOOL,
|
||||
"Set rss flags command parameters: flow type = %d, data = %llu\n",
|
||||
info->flow_type, info->data);
|
||||
|
||||
switch (info->flow_type) {
|
||||
case TCP_V4_FLOW:
|
||||
case TCP_V6_FLOW:
|
||||
/* For TCP only 4-tupple hash is supported */
|
||||
if (info->data ^ (RXH_IP_SRC | RXH_IP_DST |
|
||||
RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
|
||||
DP(BNX2X_MSG_ETHTOOL,
|
||||
"Command parameters not supported\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
case UDP_V4_FLOW:
|
||||
case UDP_V6_FLOW:
|
||||
/* For UDP either 2-tupple hash or 4-tupple hash is supported */
|
||||
if (info->data == (RXH_IP_SRC | RXH_IP_DST |
|
||||
RXH_L4_B_0_1 | RXH_L4_B_2_3))
|
||||
udp_rss_requested = 1;
|
||||
else if (info->data == (RXH_IP_SRC | RXH_IP_DST))
|
||||
udp_rss_requested = 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
if ((info->flow_type == UDP_V4_FLOW) &&
|
||||
(bp->rss_conf_obj.udp_rss_v4 != udp_rss_requested)) {
|
||||
bp->rss_conf_obj.udp_rss_v4 = udp_rss_requested;
|
||||
DP(BNX2X_MSG_ETHTOOL,
|
||||
"rss re-configured, UDP 4-tupple %s\n",
|
||||
udp_rss_requested ? "enabled" : "disabled");
|
||||
return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0);
|
||||
} else if ((info->flow_type == UDP_V6_FLOW) &&
|
||||
(bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) {
|
||||
bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested;
|
||||
return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0);
|
||||
DP(BNX2X_MSG_ETHTOOL,
|
||||
"rss re-configured, UDP 4-tupple %s\n",
|
||||
udp_rss_requested ? "enabled" : "disabled");
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
case IPV4_FLOW:
|
||||
case IPV6_FLOW:
|
||||
/* For IP only 2-tupple hash is supported */
|
||||
if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) {
|
||||
DP(BNX2X_MSG_ETHTOOL,
|
||||
"Command parameters not supported\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
case SCTP_V4_FLOW:
|
||||
case AH_ESP_V4_FLOW:
|
||||
case AH_V4_FLOW:
|
||||
case ESP_V4_FLOW:
|
||||
case SCTP_V6_FLOW:
|
||||
case AH_ESP_V6_FLOW:
|
||||
case AH_V6_FLOW:
|
||||
case ESP_V6_FLOW:
|
||||
case IP_USER_FLOW:
|
||||
case ETHER_FLOW:
|
||||
/* RSS is not supported for these protocols */
|
||||
if (info->data) {
|
||||
DP(BNX2X_MSG_ETHTOOL,
|
||||
"Command parameters not supported\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int bnx2x_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info)
|
||||
{
|
||||
struct bnx2x *bp = netdev_priv(dev);
|
||||
|
||||
switch (info->cmd) {
|
||||
case ETHTOOL_SRXFH:
|
||||
return bnx2x_set_rss_flags(bp, info);
|
||||
default:
|
||||
DP(BNX2X_MSG_ETHTOOL, "Command parameters not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -2649,7 +2779,6 @@ static int bnx2x_set_rxfh_indir(struct net_device *dev, const u32 *indir)
|
|||
{
|
||||
struct bnx2x *bp = netdev_priv(dev);
|
||||
size_t i;
|
||||
u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE] = {0};
|
||||
|
||||
for (i = 0; i < T_ETH_INDIRECTION_TABLE_SIZE; i++) {
|
||||
/*
|
||||
|
@ -2661,10 +2790,10 @@ static int bnx2x_set_rxfh_indir(struct net_device *dev, const u32 *indir)
|
|||
* align the received table to the Client ID of the leading RSS
|
||||
* queue
|
||||
*/
|
||||
ind_table[i] = indir[i] + bp->fp->cl_id;
|
||||
bp->rss_conf_obj.ind_table[i] = indir[i] + bp->fp->cl_id;
|
||||
}
|
||||
|
||||
return bnx2x_config_rss_eth(bp, ind_table, false);
|
||||
return bnx2x_config_rss_eth(bp, false);
|
||||
}
|
||||
|
||||
static const struct ethtool_ops bnx2x_ethtool_ops = {
|
||||
|
@ -2694,6 +2823,7 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
|
|||
.set_phys_id = bnx2x_set_phys_id,
|
||||
.get_ethtool_stats = bnx2x_get_ethtool_stats,
|
||||
.get_rxnfc = bnx2x_get_rxnfc,
|
||||
.set_rxnfc = bnx2x_set_rxnfc,
|
||||
.get_rxfh_indir_size = bnx2x_get_rxfh_indir_size,
|
||||
.get_rxfh_indir = bnx2x_get_rxfh_indir,
|
||||
.set_rxfh_indir = bnx2x_set_rxfh_indir,
|
||||
|
|
|
@ -4107,6 +4107,10 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
|
|||
data->capabilities |=
|
||||
ETH_RSS_UPDATE_RAMROD_DATA_IPV4_TCP_CAPABILITY;
|
||||
|
||||
if (test_bit(BNX2X_RSS_IPV4_UDP, &p->rss_flags))
|
||||
data->capabilities |=
|
||||
ETH_RSS_UPDATE_RAMROD_DATA_IPV4_UDP_CAPABILITY;
|
||||
|
||||
if (test_bit(BNX2X_RSS_IPV6, &p->rss_flags))
|
||||
data->capabilities |=
|
||||
ETH_RSS_UPDATE_RAMROD_DATA_IPV6_CAPABILITY;
|
||||
|
@ -4115,6 +4119,10 @@ static int bnx2x_setup_rss(struct bnx2x *bp,
|
|||
data->capabilities |=
|
||||
ETH_RSS_UPDATE_RAMROD_DATA_IPV6_TCP_CAPABILITY;
|
||||
|
||||
if (test_bit(BNX2X_RSS_IPV6_UDP, &p->rss_flags))
|
||||
data->capabilities |=
|
||||
ETH_RSS_UPDATE_RAMROD_DATA_IPV6_UDP_CAPABILITY;
|
||||
|
||||
/* Hashing mask */
|
||||
data->rss_result_mask = p->rss_result_mask;
|
||||
|
||||
|
|
|
@ -694,8 +694,10 @@ enum {
|
|||
|
||||
BNX2X_RSS_IPV4,
|
||||
BNX2X_RSS_IPV4_TCP,
|
||||
BNX2X_RSS_IPV4_UDP,
|
||||
BNX2X_RSS_IPV6,
|
||||
BNX2X_RSS_IPV6_TCP,
|
||||
BNX2X_RSS_IPV6_UDP,
|
||||
};
|
||||
|
||||
struct bnx2x_config_rss_params {
|
||||
|
@ -729,6 +731,10 @@ struct bnx2x_rss_config_obj {
|
|||
/* Last configured indirection table */
|
||||
u8 ind_table[T_ETH_INDIRECTION_TABLE_SIZE];
|
||||
|
||||
/* flags for enabling 4-tupple hash on UDP */
|
||||
u8 udp_rss_v4;
|
||||
u8 udp_rss_v6;
|
||||
|
||||
int (*config_rss)(struct bnx2x *bp,
|
||||
struct bnx2x_config_rss_params *p);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue