Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b29c61da authored by Saeed Mahameed's avatar Saeed Mahameed
Browse files

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
Loading
Loading
Loading
Loading
+100 −64
Original line number Diff line number Diff line
@@ -379,90 +379,125 @@ static struct mlx5e_ethtool_rule *get_ethtool_rule(struct mlx5e_priv *priv,
#define all_zeros_or_all_ones(field)		\
	((field) == 0 || (field) == (__force typeof(field))-1)

static int validate_flow(struct mlx5e_priv *priv,
			 struct ethtool_rx_flow_spec *fs)
static int validate_ethter(struct ethtool_rx_flow_spec *fs)
{
	struct ethtool_tcpip4_spec *l4_mask;
	struct ethtool_usrip4_spec *l3_mask;
	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;
	struct ethhdr *eth_mask = &fs->m_u.ether_spec;
	int ntuples = 0;

	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))
			num_tuples++;
		ntuples++;
	if (!is_zero_ether_addr(eth_mask->h_source))
			num_tuples++;
		ntuples++;
	if (eth_mask->h_proto)
			num_tuples++;
		break;
	case TCP_V4_FLOW:
	case UDP_V4_FLOW:
		if (fs->m_u.tcp_ip4_spec.tos)
		ntuples++;
	return ntuples;
}

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;
		l4_mask = &fs->m_u.tcp_ip4_spec;

	if (l4_mask->ip4src) {
		if (!all_ones(l4_mask->ip4src))
			return -EINVAL;
			num_tuples++;
		ntuples++;
	}
	if (l4_mask->ip4dst) {
		if (!all_ones(l4_mask->ip4dst))
			return -EINVAL;
			num_tuples++;
		ntuples++;
	}
	if (l4_mask->psrc) {
		if (!all_ones(l4_mask->psrc))
			return -EINVAL;
			num_tuples++;
		ntuples++;
	}
	if (l4_mask->pdst) {
		if (!all_ones(l4_mask->pdst))
			return -EINVAL;
			num_tuples++;
		ntuples++;
	}
	/* Flow is TCP/UDP */
		num_tuples++;
		break;
	case IP_USER_FLOW:
		l3_mask = &fs->m_u.usr_ip4_spec;
	return ++ntuples;
}

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 ||
	    fs->h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4)
		return -EINVAL;
	if (l3_mask->ip4src) {
		if (!all_ones(l3_mask->ip4src))
			return -EINVAL;
			num_tuples++;
		ntuples++;
	}
	if (l3_mask->ip4dst) {
		if (!all_ones(l3_mask->ip4dst))
			return -EINVAL;
			num_tuples++;
		ntuples++;
	}
	/* Flow is IPv4 */
		num_tuples++;
		break;
	default:
		return -EINVAL;
	return ++ntuples;
}
	if ((fs->flow_type & FLOW_EXT)) {

static int validate_vlan(struct ethtool_rx_flow_spec *fs)
{
	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;

		if (fs->m_ext.vlan_tci) {
			if (be16_to_cpu(fs->h_ext.vlan_tci) >= VLAN_N_VID)
	if (fs->m_ext.vlan_tci &&
	    (be16_to_cpu(fs->h_ext.vlan_tci) >= VLAN_N_VID))
		return -EINVAL;

	return 1;
}
		num_tuples++;

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;
	}
	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 &&
@@ -483,8 +518,9 @@ int mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv,

	num_tuples = validate_flow(priv, fs);
	if (num_tuples <= 0) {
		netdev_warn(priv->netdev, "%s: flow is not valid\n",  __func__);
		return -EINVAL;
		netdev_warn(priv->netdev, "%s: flow is not valid %d\n",
			    __func__, num_tuples);
		return num_tuples;
	}

	eth_ft = get_flow_table(priv, fs, num_tuples);