Commit 751969e5 authored by Piotr Gardocki's avatar Piotr Gardocki Committed by Tony Nguyen

iavf: fix FDIR rule fields masks validation

Return an error if a field's mask is neither full nor empty. When a mask
is only partial the field is not being used for rule programming but it
gives a wrong impression it is used. Fix by returning an error on any
partial mask to make it clear they are not supported.
The ip_ver assignment is moved earlier in code to allow using it in
iavf_validate_fdir_fltr_masks.

Fixes: 527691bf ("iavf: Support IPv4 Flow Director filters")
Fixes: e90cbc25 ("iavf: Support IPv6 Flow Director filters")
Signed-off-by: default avatarPiotr Gardocki <piotrx.gardocki@intel.com>
Tested-by: default avatarRafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent de4c5efe
...@@ -1289,6 +1289,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe ...@@ -1289,6 +1289,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.src_port = fsp->m_u.tcp_ip4_spec.psrc; fltr->ip_mask.src_port = fsp->m_u.tcp_ip4_spec.psrc;
fltr->ip_mask.dst_port = fsp->m_u.tcp_ip4_spec.pdst; fltr->ip_mask.dst_port = fsp->m_u.tcp_ip4_spec.pdst;
fltr->ip_mask.tos = fsp->m_u.tcp_ip4_spec.tos; fltr->ip_mask.tos = fsp->m_u.tcp_ip4_spec.tos;
fltr->ip_ver = 4;
break; break;
case AH_V4_FLOW: case AH_V4_FLOW:
case ESP_V4_FLOW: case ESP_V4_FLOW:
...@@ -1300,6 +1301,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe ...@@ -1300,6 +1301,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.v4_addrs.dst_ip = fsp->m_u.ah_ip4_spec.ip4dst; fltr->ip_mask.v4_addrs.dst_ip = fsp->m_u.ah_ip4_spec.ip4dst;
fltr->ip_mask.spi = fsp->m_u.ah_ip4_spec.spi; fltr->ip_mask.spi = fsp->m_u.ah_ip4_spec.spi;
fltr->ip_mask.tos = fsp->m_u.ah_ip4_spec.tos; fltr->ip_mask.tos = fsp->m_u.ah_ip4_spec.tos;
fltr->ip_ver = 4;
break; break;
case IPV4_USER_FLOW: case IPV4_USER_FLOW:
fltr->ip_data.v4_addrs.src_ip = fsp->h_u.usr_ip4_spec.ip4src; fltr->ip_data.v4_addrs.src_ip = fsp->h_u.usr_ip4_spec.ip4src;
...@@ -1312,6 +1314,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe ...@@ -1312,6 +1314,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.l4_header = fsp->m_u.usr_ip4_spec.l4_4_bytes; fltr->ip_mask.l4_header = fsp->m_u.usr_ip4_spec.l4_4_bytes;
fltr->ip_mask.tos = fsp->m_u.usr_ip4_spec.tos; fltr->ip_mask.tos = fsp->m_u.usr_ip4_spec.tos;
fltr->ip_mask.proto = fsp->m_u.usr_ip4_spec.proto; fltr->ip_mask.proto = fsp->m_u.usr_ip4_spec.proto;
fltr->ip_ver = 4;
break; break;
case TCP_V6_FLOW: case TCP_V6_FLOW:
case UDP_V6_FLOW: case UDP_V6_FLOW:
...@@ -1330,6 +1333,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe ...@@ -1330,6 +1333,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.src_port = fsp->m_u.tcp_ip6_spec.psrc; fltr->ip_mask.src_port = fsp->m_u.tcp_ip6_spec.psrc;
fltr->ip_mask.dst_port = fsp->m_u.tcp_ip6_spec.pdst; fltr->ip_mask.dst_port = fsp->m_u.tcp_ip6_spec.pdst;
fltr->ip_mask.tclass = fsp->m_u.tcp_ip6_spec.tclass; fltr->ip_mask.tclass = fsp->m_u.tcp_ip6_spec.tclass;
fltr->ip_ver = 6;
break; break;
case AH_V6_FLOW: case AH_V6_FLOW:
case ESP_V6_FLOW: case ESP_V6_FLOW:
...@@ -1345,6 +1349,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe ...@@ -1345,6 +1349,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
sizeof(struct in6_addr)); sizeof(struct in6_addr));
fltr->ip_mask.spi = fsp->m_u.ah_ip6_spec.spi; fltr->ip_mask.spi = fsp->m_u.ah_ip6_spec.spi;
fltr->ip_mask.tclass = fsp->m_u.ah_ip6_spec.tclass; fltr->ip_mask.tclass = fsp->m_u.ah_ip6_spec.tclass;
fltr->ip_ver = 6;
break; break;
case IPV6_USER_FLOW: case IPV6_USER_FLOW:
memcpy(&fltr->ip_data.v6_addrs.src_ip, fsp->h_u.usr_ip6_spec.ip6src, memcpy(&fltr->ip_data.v6_addrs.src_ip, fsp->h_u.usr_ip6_spec.ip6src,
...@@ -1361,6 +1366,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe ...@@ -1361,6 +1366,7 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
fltr->ip_mask.l4_header = fsp->m_u.usr_ip6_spec.l4_4_bytes; fltr->ip_mask.l4_header = fsp->m_u.usr_ip6_spec.l4_4_bytes;
fltr->ip_mask.tclass = fsp->m_u.usr_ip6_spec.tclass; fltr->ip_mask.tclass = fsp->m_u.usr_ip6_spec.tclass;
fltr->ip_mask.proto = fsp->m_u.usr_ip6_spec.l4_proto; fltr->ip_mask.proto = fsp->m_u.usr_ip6_spec.l4_proto;
fltr->ip_ver = 6;
break; break;
case ETHER_FLOW: case ETHER_FLOW:
fltr->eth_data.etype = fsp->h_u.ether_spec.h_proto; fltr->eth_data.etype = fsp->h_u.ether_spec.h_proto;
...@@ -1371,6 +1377,10 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe ...@@ -1371,6 +1377,10 @@ iavf_add_fdir_fltr_info(struct iavf_adapter *adapter, struct ethtool_rx_flow_spe
return -EINVAL; return -EINVAL;
} }
err = iavf_validate_fdir_fltr_masks(adapter, fltr);
if (err)
return err;
if (iavf_fdir_is_dup_fltr(adapter, fltr)) if (iavf_fdir_is_dup_fltr(adapter, fltr))
return -EEXIST; return -EEXIST;
......
...@@ -18,6 +18,79 @@ static const struct in6_addr ipv6_addr_full_mask = { ...@@ -18,6 +18,79 @@ static const struct in6_addr ipv6_addr_full_mask = {
} }
}; };
static const struct in6_addr ipv6_addr_zero_mask = {
.in6_u = {
.u6_addr8 = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
}
}
};
/**
* iavf_validate_fdir_fltr_masks - validate Flow Director filter fields masks
* @adapter: pointer to the VF adapter structure
* @fltr: Flow Director filter data structure
*
* Returns 0 if all masks of packet fields are either full or empty. Returns
* error on at least one partial mask.
*/
int iavf_validate_fdir_fltr_masks(struct iavf_adapter *adapter,
struct iavf_fdir_fltr *fltr)
{
if (fltr->eth_mask.etype && fltr->eth_mask.etype != htons(U16_MAX))
goto partial_mask;
if (fltr->ip_ver == 4) {
if (fltr->ip_mask.v4_addrs.src_ip &&
fltr->ip_mask.v4_addrs.src_ip != htonl(U32_MAX))
goto partial_mask;
if (fltr->ip_mask.v4_addrs.dst_ip &&
fltr->ip_mask.v4_addrs.dst_ip != htonl(U32_MAX))
goto partial_mask;
if (fltr->ip_mask.tos && fltr->ip_mask.tos != U8_MAX)
goto partial_mask;
} else if (fltr->ip_ver == 6) {
if (memcmp(&fltr->ip_mask.v6_addrs.src_ip, &ipv6_addr_zero_mask,
sizeof(struct in6_addr)) &&
memcmp(&fltr->ip_mask.v6_addrs.src_ip, &ipv6_addr_full_mask,
sizeof(struct in6_addr)))
goto partial_mask;
if (memcmp(&fltr->ip_mask.v6_addrs.dst_ip, &ipv6_addr_zero_mask,
sizeof(struct in6_addr)) &&
memcmp(&fltr->ip_mask.v6_addrs.dst_ip, &ipv6_addr_full_mask,
sizeof(struct in6_addr)))
goto partial_mask;
if (fltr->ip_mask.tclass && fltr->ip_mask.tclass != U8_MAX)
goto partial_mask;
}
if (fltr->ip_mask.proto && fltr->ip_mask.proto != U8_MAX)
goto partial_mask;
if (fltr->ip_mask.src_port && fltr->ip_mask.src_port != htons(U16_MAX))
goto partial_mask;
if (fltr->ip_mask.dst_port && fltr->ip_mask.dst_port != htons(U16_MAX))
goto partial_mask;
if (fltr->ip_mask.spi && fltr->ip_mask.spi != htonl(U32_MAX))
goto partial_mask;
if (fltr->ip_mask.l4_header &&
fltr->ip_mask.l4_header != htonl(U32_MAX))
goto partial_mask;
return 0;
partial_mask:
dev_err(&adapter->pdev->dev, "Failed to add Flow Director filter, partial masks are not supported\n");
return -EOPNOTSUPP;
}
/** /**
* iavf_pkt_udp_no_pay_len - the length of UDP packet without payload * iavf_pkt_udp_no_pay_len - the length of UDP packet without payload
* @fltr: Flow Director filter data structure * @fltr: Flow Director filter data structure
...@@ -263,8 +336,6 @@ iavf_fill_fdir_ip4_hdr(struct iavf_fdir_fltr *fltr, ...@@ -263,8 +336,6 @@ iavf_fill_fdir_ip4_hdr(struct iavf_fdir_fltr *fltr,
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, DST); VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV4, DST);
} }
fltr->ip_ver = 4;
return 0; return 0;
} }
...@@ -309,8 +380,6 @@ iavf_fill_fdir_ip6_hdr(struct iavf_fdir_fltr *fltr, ...@@ -309,8 +380,6 @@ iavf_fill_fdir_ip6_hdr(struct iavf_fdir_fltr *fltr,
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, DST); VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, IPV6, DST);
} }
fltr->ip_ver = 6;
return 0; return 0;
} }
......
...@@ -110,6 +110,8 @@ struct iavf_fdir_fltr { ...@@ -110,6 +110,8 @@ struct iavf_fdir_fltr {
struct virtchnl_fdir_add vc_add_msg; struct virtchnl_fdir_add vc_add_msg;
}; };
int iavf_validate_fdir_fltr_masks(struct iavf_adapter *adapter,
struct iavf_fdir_fltr *fltr);
int iavf_fill_fdir_add_msg(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr); int iavf_fill_fdir_add_msg(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr); void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr); bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr);
......
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