Commit b29c61da authored by Saeed Mahameed's avatar Saeed Mahameed

net/mlx5e: Ethtool steering flow validation refactoring

Have a ethtool rx flow spec validation helper function per flow type.
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 42c625a4
...@@ -379,90 +379,125 @@ static struct mlx5e_ethtool_rule *get_ethtool_rule(struct mlx5e_priv *priv, ...@@ -379,90 +379,125 @@ static struct mlx5e_ethtool_rule *get_ethtool_rule(struct mlx5e_priv *priv,
#define all_zeros_or_all_ones(field) \ #define all_zeros_or_all_ones(field) \
((field) == 0 || (field) == (__force typeof(field))-1) ((field) == 0 || (field) == (__force typeof(field))-1)
static int validate_flow(struct mlx5e_priv *priv, static int validate_ethter(struct ethtool_rx_flow_spec *fs)
struct ethtool_rx_flow_spec *fs)
{ {
struct ethtool_tcpip4_spec *l4_mask; struct ethhdr *eth_mask = &fs->m_u.ether_spec;
struct ethtool_usrip4_spec *l3_mask; int ntuples = 0;
struct ethhdr *eth_mask;
int num_tuples = 0;
if (fs->location >= MAX_NUM_OF_ETHTOOL_RULES)
return -EINVAL;
if (fs->ring_cookie >= priv->channels.params.num_channels &&
fs->ring_cookie != RX_CLS_FLOW_DISC)
return -EINVAL;
switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
case ETHER_FLOW:
eth_mask = &fs->m_u.ether_spec;
if (!is_zero_ether_addr(eth_mask->h_dest)) if (!is_zero_ether_addr(eth_mask->h_dest))
num_tuples++; ntuples++;
if (!is_zero_ether_addr(eth_mask->h_source)) if (!is_zero_ether_addr(eth_mask->h_source))
num_tuples++; ntuples++;
if (eth_mask->h_proto) if (eth_mask->h_proto)
num_tuples++; ntuples++;
break; return ntuples;
case TCP_V4_FLOW: }
case UDP_V4_FLOW:
if (fs->m_u.tcp_ip4_spec.tos) static int validate_tcpudp4(struct ethtool_rx_flow_spec *fs)
{
struct ethtool_tcpip4_spec *l4_mask = &fs->m_u.tcp_ip4_spec;
int ntuples = 0;
if (l4_mask->tos)
return -EINVAL; return -EINVAL;
l4_mask = &fs->m_u.tcp_ip4_spec;
if (l4_mask->ip4src) { if (l4_mask->ip4src) {
if (!all_ones(l4_mask->ip4src)) if (!all_ones(l4_mask->ip4src))
return -EINVAL; return -EINVAL;
num_tuples++; ntuples++;
} }
if (l4_mask->ip4dst) { if (l4_mask->ip4dst) {
if (!all_ones(l4_mask->ip4dst)) if (!all_ones(l4_mask->ip4dst))
return -EINVAL; return -EINVAL;
num_tuples++; ntuples++;
} }
if (l4_mask->psrc) { if (l4_mask->psrc) {
if (!all_ones(l4_mask->psrc)) if (!all_ones(l4_mask->psrc))
return -EINVAL; return -EINVAL;
num_tuples++; ntuples++;
} }
if (l4_mask->pdst) { if (l4_mask->pdst) {
if (!all_ones(l4_mask->pdst)) if (!all_ones(l4_mask->pdst))
return -EINVAL; return -EINVAL;
num_tuples++; ntuples++;
} }
/* Flow is TCP/UDP */ /* Flow is TCP/UDP */
num_tuples++; return ++ntuples;
break; }
case IP_USER_FLOW:
l3_mask = &fs->m_u.usr_ip4_spec; static int validate_ip4(struct ethtool_rx_flow_spec *fs)
{
struct ethtool_usrip4_spec *l3_mask = &fs->m_u.usr_ip4_spec;
int ntuples = 0;
if (l3_mask->l4_4_bytes || l3_mask->tos || l3_mask->proto || if (l3_mask->l4_4_bytes || l3_mask->tos || l3_mask->proto ||
fs->h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4) fs->h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4)
return -EINVAL; return -EINVAL;
if (l3_mask->ip4src) { if (l3_mask->ip4src) {
if (!all_ones(l3_mask->ip4src)) if (!all_ones(l3_mask->ip4src))
return -EINVAL; return -EINVAL;
num_tuples++; ntuples++;
} }
if (l3_mask->ip4dst) { if (l3_mask->ip4dst) {
if (!all_ones(l3_mask->ip4dst)) if (!all_ones(l3_mask->ip4dst))
return -EINVAL; return -EINVAL;
num_tuples++; ntuples++;
} }
/* Flow is IPv4 */ /* Flow is IPv4 */
num_tuples++; return ++ntuples;
break; }
default:
return -EINVAL; static int validate_vlan(struct ethtool_rx_flow_spec *fs)
} {
if ((fs->flow_type & FLOW_EXT)) {
if (fs->m_ext.vlan_etype || if (fs->m_ext.vlan_etype ||
(fs->m_ext.vlan_tci != cpu_to_be16(VLAN_VID_MASK))) fs->m_ext.vlan_tci != cpu_to_be16(VLAN_VID_MASK))
return -EINVAL; return -EINVAL;
if (fs->m_ext.vlan_tci) { if (fs->m_ext.vlan_tci &&
if (be16_to_cpu(fs->h_ext.vlan_tci) >= VLAN_N_VID) (be16_to_cpu(fs->h_ext.vlan_tci) >= VLAN_N_VID))
return -EINVAL; return -EINVAL;
return 1;
}
static int validate_flow(struct mlx5e_priv *priv,
struct ethtool_rx_flow_spec *fs)
{
int num_tuples = 0;
int ret = 0;
if (fs->location >= MAX_NUM_OF_ETHTOOL_RULES)
return -ENOSPC;
if (fs->ring_cookie >= priv->channels.params.num_channels &&
fs->ring_cookie != RX_CLS_FLOW_DISC)
return -EINVAL;
switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
case ETHER_FLOW:
num_tuples += validate_ethter(fs);
break;
case TCP_V4_FLOW:
case UDP_V4_FLOW:
ret = validate_tcpudp4(fs);
if (ret < 0)
return ret;
num_tuples += ret;
break;
case IP_USER_FLOW:
ret = validate_ip4(fs);
if (ret < 0)
return ret;
num_tuples += ret;
break;
default:
return -ENOTSUPP;
} }
num_tuples++; if ((fs->flow_type & FLOW_EXT)) {
ret = validate_vlan(fs);
if (ret < 0)
return ret;
num_tuples += ret;
} }
if (fs->flow_type & FLOW_MAC_EXT && if (fs->flow_type & FLOW_MAC_EXT &&
...@@ -483,8 +518,9 @@ int mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv, ...@@ -483,8 +518,9 @@ int mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv,
num_tuples = validate_flow(priv, fs); num_tuples = validate_flow(priv, fs);
if (num_tuples <= 0) { if (num_tuples <= 0) {
netdev_warn(priv->netdev, "%s: flow is not valid\n", __func__); netdev_warn(priv->netdev, "%s: flow is not valid %d\n",
return -EINVAL; __func__, num_tuples);
return num_tuples;
} }
eth_ft = get_flow_table(priv, fs, num_tuples); eth_ft = get_flow_table(priv, fs, num_tuples);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment