Skip to content

Commit efca91e

Browse files
Kaaameanguy11
authored andcommitted
i40e: Add flow director support for IPv6
Flow director for IPv6 is not supported. 1) Implementation of support for IPv6 flow director. 2) Added handlers for addition of TCP6, UDP6, SCTP6, IPv6. 3) Refactored legacy code to make it more generic. 4) Added packet templates for TCP6, UDP6, SCTP6, IPv6. 5) Added handling of IPv6 source and destination address for flow director. 6) Improved argument passing for source and destination portin TCP6, UDP6 and SCTP6. 7) Added handling of ethtool -n for IPv6, TCP6,UDP6, SCTP6. 8) Used correct bit flag regarding FLEXOFF field of flow director data descriptor. Without this patch, there would be no support for flow director on IPv6, TCP6, UDP6, SCTP6. Tested based on x710 datasheet by using: ethtool -N enp133s0f0 flow-type tcp4 src-port 13 dst-port 37 user-def 0x44142 action 1 ethtool -N enp133s0f0 flow-type tcp6 src-port 13 dst-port 40 user-def 0x44142 action 2 ethtool -N enp133s0f0 flow-type udp4 src-port 20 dst-port 40 user-def 0x44142 action 3 ethtool -N enp133s0f0 flow-type udp6 src-port 25 dst-port 40 user-def 0x44142 action 4 ethtool -N enp133s0f0 flow-type sctp4 src-port 55 dst-port 65 user-def 0x44142 action 5 ethtool -N enp133s0f0 flow-type sctp6 src-port 60 dst-port 40 user-def 0x44142 action 6 ethtool -N enp133s0f0 flow-type ip4 src-ip 1.1.1.1 dst-ip 1.1.1.4 user-def 0x44142 action 7 ethtool -N enp133s0f0 flow-type ip6 src-ip fe80::3efd:feff:fe6f:bbbb dst-ip fe80::3efd:feff:fe6f:aaaa user-def 0x44142 action 8 Then send traffic from client which matches the criteria provided to ethtool. Observe that packets are redirected to user set queues with ethtool -S <interface> Signed-off-by: Przemyslaw Patynowski <[email protected]> Tested-by: Tony Brelinski <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent 95f352d commit efca91e

File tree

4 files changed

+551
-119
lines changed

4 files changed

+551
-119
lines changed

drivers/net/ethernet/intel/i40e/i40e.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,12 @@ struct i40e_fdir_filter {
213213
struct hlist_node fdir_node;
214214
/* filter ipnut set */
215215
u8 flow_type;
216-
u8 ip4_proto;
216+
u8 ipl4_proto;
217217
/* TX packet view of src and dst */
218218
__be32 dst_ip;
219219
__be32 src_ip;
220+
__be32 dst_ip6[4];
221+
__be32 src_ip6[4];
220222
__be16 src_port;
221223
__be16 dst_port;
222224
__be32 sctp_v_tag;
@@ -477,6 +479,11 @@ struct i40e_pf {
477479
u16 fd_sctp4_filter_cnt;
478480
u16 fd_ip4_filter_cnt;
479481

482+
u16 fd_tcp6_filter_cnt;
483+
u16 fd_udp6_filter_cnt;
484+
u16 fd_sctp6_filter_cnt;
485+
u16 fd_ip6_filter_cnt;
486+
480487
/* Flexible filter table values that need to be programmed into
481488
* hardware, which expects L3 and L4 to be programmed separately. We
482489
* need to ensure that the values are in ascended order and don't have

drivers/net/ethernet/intel/i40e/i40e_ethtool.c

Lines changed: 194 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3222,13 +3222,30 @@ static int i40e_get_ethtool_fdir_entry(struct i40e_pf *pf,
32223222
fsp->m_u.usr_ip4_spec.proto = 0;
32233223
}
32243224

3225-
/* Reverse the src and dest notion, since the HW views them from
3226-
* Tx perspective where as the user expects it from Rx filter view.
3227-
*/
3228-
fsp->h_u.tcp_ip4_spec.psrc = rule->dst_port;
3229-
fsp->h_u.tcp_ip4_spec.pdst = rule->src_port;
3230-
fsp->h_u.tcp_ip4_spec.ip4src = rule->dst_ip;
3231-
fsp->h_u.tcp_ip4_spec.ip4dst = rule->src_ip;
3225+
if (fsp->flow_type == IPV6_USER_FLOW ||
3226+
fsp->flow_type == UDP_V6_FLOW ||
3227+
fsp->flow_type == TCP_V6_FLOW ||
3228+
fsp->flow_type == SCTP_V6_FLOW) {
3229+
/* Reverse the src and dest notion, since the HW views them
3230+
* from Tx perspective where as the user expects it from
3231+
* Rx filter view.
3232+
*/
3233+
fsp->h_u.tcp_ip6_spec.psrc = rule->dst_port;
3234+
fsp->h_u.tcp_ip6_spec.pdst = rule->src_port;
3235+
memcpy(fsp->h_u.tcp_ip6_spec.ip6dst, rule->src_ip6,
3236+
sizeof(__be32) * 4);
3237+
memcpy(fsp->h_u.tcp_ip6_spec.ip6src, rule->dst_ip6,
3238+
sizeof(__be32) * 4);
3239+
} else {
3240+
/* Reverse the src and dest notion, since the HW views them
3241+
* from Tx perspective where as the user expects it from
3242+
* Rx filter view.
3243+
*/
3244+
fsp->h_u.tcp_ip4_spec.psrc = rule->dst_port;
3245+
fsp->h_u.tcp_ip4_spec.pdst = rule->src_port;
3246+
fsp->h_u.tcp_ip4_spec.ip4src = rule->dst_ip;
3247+
fsp->h_u.tcp_ip4_spec.ip4dst = rule->src_ip;
3248+
}
32323249

32333250
switch (rule->flow_type) {
32343251
case SCTP_V4_FLOW:
@@ -3240,9 +3257,21 @@ static int i40e_get_ethtool_fdir_entry(struct i40e_pf *pf,
32403257
case UDP_V4_FLOW:
32413258
index = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
32423259
break;
3260+
case SCTP_V6_FLOW:
3261+
index = I40E_FILTER_PCTYPE_NONF_IPV6_SCTP;
3262+
break;
3263+
case TCP_V6_FLOW:
3264+
index = I40E_FILTER_PCTYPE_NONF_IPV6_TCP;
3265+
break;
3266+
case UDP_V6_FLOW:
3267+
index = I40E_FILTER_PCTYPE_NONF_IPV6_UDP;
3268+
break;
32433269
case IP_USER_FLOW:
32443270
index = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER;
32453271
break;
3272+
case IPV6_USER_FLOW:
3273+
index = I40E_FILTER_PCTYPE_NONF_IPV6_OTHER;
3274+
break;
32463275
default:
32473276
/* If we have stored a filter with a flow type not listed here
32483277
* it is almost certainly a driver bug. WARN(), and then
@@ -3258,6 +3287,20 @@ static int i40e_get_ethtool_fdir_entry(struct i40e_pf *pf,
32583287
input_set = i40e_read_fd_input_set(pf, index);
32593288

32603289
no_input_set:
3290+
if (input_set & I40E_L3_V6_SRC_MASK) {
3291+
fsp->m_u.tcp_ip6_spec.ip6src[0] = htonl(0xFFFFFFFF);
3292+
fsp->m_u.tcp_ip6_spec.ip6src[1] = htonl(0xFFFFFFFF);
3293+
fsp->m_u.tcp_ip6_spec.ip6src[2] = htonl(0xFFFFFFFF);
3294+
fsp->m_u.tcp_ip6_spec.ip6src[3] = htonl(0xFFFFFFFF);
3295+
}
3296+
3297+
if (input_set & I40E_L3_V6_DST_MASK) {
3298+
fsp->m_u.tcp_ip6_spec.ip6dst[0] = htonl(0xFFFFFFFF);
3299+
fsp->m_u.tcp_ip6_spec.ip6dst[1] = htonl(0xFFFFFFFF);
3300+
fsp->m_u.tcp_ip6_spec.ip6dst[2] = htonl(0xFFFFFFFF);
3301+
fsp->m_u.tcp_ip6_spec.ip6dst[3] = htonl(0xFFFFFFFF);
3302+
}
3303+
32613304
if (input_set & I40E_L3_SRC_MASK)
32623305
fsp->m_u.tcp_ip4_spec.ip4src = htonl(0xFFFFFFFF);
32633306

@@ -3921,6 +3964,14 @@ static const char *i40e_flow_str(struct ethtool_rx_flow_spec *fsp)
39213964
return "sctp4";
39223965
case IP_USER_FLOW:
39233966
return "ip4";
3967+
case TCP_V6_FLOW:
3968+
return "tcp6";
3969+
case UDP_V6_FLOW:
3970+
return "udp6";
3971+
case SCTP_V6_FLOW:
3972+
return "sctp6";
3973+
case IPV6_USER_FLOW:
3974+
return "ip6";
39243975
default:
39253976
return "unknown";
39263977
}
@@ -4056,9 +4107,14 @@ static int i40e_check_fdir_input_set(struct i40e_vsi *vsi,
40564107
struct ethtool_rx_flow_spec *fsp,
40574108
struct i40e_rx_flow_userdef *userdef)
40584109
{
4059-
struct i40e_pf *pf = vsi->back;
4110+
static const __be32 ipv6_full_mask[4] = {cpu_to_be32(0xffffffff),
4111+
cpu_to_be32(0xffffffff), cpu_to_be32(0xffffffff),
4112+
cpu_to_be32(0xffffffff)};
4113+
struct ethtool_tcpip6_spec *tcp_ip6_spec;
4114+
struct ethtool_usrip6_spec *usr_ip6_spec;
40604115
struct ethtool_tcpip4_spec *tcp_ip4_spec;
40614116
struct ethtool_usrip4_spec *usr_ip4_spec;
4117+
struct i40e_pf *pf = vsi->back;
40624118
u64 current_mask, new_mask;
40634119
bool new_flex_offset = false;
40644120
bool flex_l3 = false;
@@ -4080,11 +4136,28 @@ static int i40e_check_fdir_input_set(struct i40e_vsi *vsi,
40804136
index = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
40814137
fdir_filter_count = &pf->fd_udp4_filter_cnt;
40824138
break;
4139+
case SCTP_V6_FLOW:
4140+
index = I40E_FILTER_PCTYPE_NONF_IPV6_SCTP;
4141+
fdir_filter_count = &pf->fd_sctp6_filter_cnt;
4142+
break;
4143+
case TCP_V6_FLOW:
4144+
index = I40E_FILTER_PCTYPE_NONF_IPV6_TCP;
4145+
fdir_filter_count = &pf->fd_tcp6_filter_cnt;
4146+
break;
4147+
case UDP_V6_FLOW:
4148+
index = I40E_FILTER_PCTYPE_NONF_IPV6_UDP;
4149+
fdir_filter_count = &pf->fd_udp6_filter_cnt;
4150+
break;
40834151
case IP_USER_FLOW:
40844152
index = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER;
40854153
fdir_filter_count = &pf->fd_ip4_filter_cnt;
40864154
flex_l3 = true;
40874155
break;
4156+
case IPV6_USER_FLOW:
4157+
index = I40E_FILTER_PCTYPE_NONF_IPV6_OTHER;
4158+
fdir_filter_count = &pf->fd_ip6_filter_cnt;
4159+
flex_l3 = true;
4160+
break;
40884161
default:
40894162
return -EOPNOTSUPP;
40904163
}
@@ -4147,6 +4220,53 @@ static int i40e_check_fdir_input_set(struct i40e_vsi *vsi,
41474220
return -EOPNOTSUPP;
41484221

41494222
break;
4223+
case SCTP_V6_FLOW:
4224+
new_mask &= ~I40E_VERIFY_TAG_MASK;
4225+
fallthrough;
4226+
case TCP_V6_FLOW:
4227+
case UDP_V6_FLOW:
4228+
tcp_ip6_spec = &fsp->m_u.tcp_ip6_spec;
4229+
4230+
/* Check if user provided IPv6 source address. */
4231+
if (ipv6_addr_equal((struct in6_addr *)&tcp_ip6_spec->ip6src,
4232+
(struct in6_addr *)&ipv6_full_mask))
4233+
new_mask |= I40E_L3_V6_SRC_MASK;
4234+
else if (ipv6_addr_any((struct in6_addr *)
4235+
&tcp_ip6_spec->ip6src))
4236+
new_mask &= ~I40E_L3_V6_SRC_MASK;
4237+
else
4238+
return -EOPNOTSUPP;
4239+
4240+
/* Check if user provided destination address. */
4241+
if (ipv6_addr_equal((struct in6_addr *)&tcp_ip6_spec->ip6dst,
4242+
(struct in6_addr *)&ipv6_full_mask))
4243+
new_mask |= I40E_L3_V6_DST_MASK;
4244+
else if (ipv6_addr_any((struct in6_addr *)
4245+
&tcp_ip6_spec->ip6src))
4246+
new_mask &= ~I40E_L3_V6_DST_MASK;
4247+
else
4248+
return -EOPNOTSUPP;
4249+
4250+
/* L4 source port */
4251+
if (tcp_ip6_spec->psrc == htons(0xFFFF))
4252+
new_mask |= I40E_L4_SRC_MASK;
4253+
else if (!tcp_ip6_spec->psrc)
4254+
new_mask &= ~I40E_L4_SRC_MASK;
4255+
else
4256+
return -EOPNOTSUPP;
4257+
4258+
/* L4 destination port */
4259+
if (tcp_ip6_spec->pdst == htons(0xFFFF))
4260+
new_mask |= I40E_L4_DST_MASK;
4261+
else if (!tcp_ip6_spec->pdst)
4262+
new_mask &= ~I40E_L4_DST_MASK;
4263+
else
4264+
return -EOPNOTSUPP;
4265+
4266+
/* Filtering on Traffic Classes is not supported. */
4267+
if (tcp_ip6_spec->tclass)
4268+
return -EOPNOTSUPP;
4269+
break;
41504270
case IP_USER_FLOW:
41514271
usr_ip4_spec = &fsp->m_u.usr_ip4_spec;
41524272

@@ -4186,6 +4306,45 @@ static int i40e_check_fdir_input_set(struct i40e_vsi *vsi,
41864306
if (usr_ip4_spec->proto)
41874307
return -EINVAL;
41884308

4309+
break;
4310+
case IPV6_USER_FLOW:
4311+
usr_ip6_spec = &fsp->m_u.usr_ip6_spec;
4312+
4313+
/* Check if user provided IPv6 source address. */
4314+
if (ipv6_addr_equal((struct in6_addr *)&usr_ip6_spec->ip6src,
4315+
(struct in6_addr *)&ipv6_full_mask))
4316+
new_mask |= I40E_L3_V6_SRC_MASK;
4317+
else if (ipv6_addr_any((struct in6_addr *)
4318+
&usr_ip6_spec->ip6src))
4319+
new_mask &= ~I40E_L3_V6_SRC_MASK;
4320+
else
4321+
return -EOPNOTSUPP;
4322+
4323+
/* Check if user provided destination address. */
4324+
if (ipv6_addr_equal((struct in6_addr *)&usr_ip6_spec->ip6dst,
4325+
(struct in6_addr *)&ipv6_full_mask))
4326+
new_mask |= I40E_L3_V6_DST_MASK;
4327+
else if (ipv6_addr_any((struct in6_addr *)
4328+
&usr_ip6_spec->ip6src))
4329+
new_mask &= ~I40E_L3_V6_DST_MASK;
4330+
else
4331+
return -EOPNOTSUPP;
4332+
4333+
if (usr_ip6_spec->l4_4_bytes == htonl(0xFFFFFFFF))
4334+
new_mask |= I40E_L4_SRC_MASK | I40E_L4_DST_MASK;
4335+
else if (!usr_ip6_spec->l4_4_bytes)
4336+
new_mask &= ~(I40E_L4_SRC_MASK | I40E_L4_DST_MASK);
4337+
else
4338+
return -EOPNOTSUPP;
4339+
4340+
/* Filtering on Traffic class is not supported. */
4341+
if (usr_ip6_spec->tclass)
4342+
return -EOPNOTSUPP;
4343+
4344+
/* Filtering on L4 protocol is not supported */
4345+
if (usr_ip6_spec->l4_proto)
4346+
return -EINVAL;
4347+
41894348
break;
41904349
default:
41914350
return -EOPNOTSUPP;
@@ -4370,7 +4529,7 @@ static bool i40e_match_fdir_filter(struct i40e_fdir_filter *a,
43704529
a->dst_port != b->dst_port ||
43714530
a->src_port != b->src_port ||
43724531
a->flow_type != b->flow_type ||
4373-
a->ip4_proto != b->ip4_proto)
4532+
a->ipl4_proto != b->ipl4_proto)
43744533
return false;
43754534

43764535
return true;
@@ -4528,15 +4687,33 @@ static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi,
45284687
input->dst_ip = fsp->h_u.tcp_ip4_spec.ip4src;
45294688
input->src_ip = fsp->h_u.tcp_ip4_spec.ip4dst;
45304689
input->flow_type = fsp->flow_type & ~FLOW_EXT;
4531-
input->ip4_proto = fsp->h_u.usr_ip4_spec.proto;
45324690

4533-
/* Reverse the src and dest notion, since the HW expects them to be from
4534-
* Tx perspective where as the input from user is from Rx filter view.
4535-
*/
4536-
input->dst_port = fsp->h_u.tcp_ip4_spec.psrc;
4537-
input->src_port = fsp->h_u.tcp_ip4_spec.pdst;
4538-
input->dst_ip = fsp->h_u.tcp_ip4_spec.ip4src;
4539-
input->src_ip = fsp->h_u.tcp_ip4_spec.ip4dst;
4691+
if (input->flow_type == IPV6_USER_FLOW ||
4692+
input->flow_type == UDP_V6_FLOW ||
4693+
input->flow_type == TCP_V6_FLOW ||
4694+
input->flow_type == SCTP_V6_FLOW) {
4695+
/* Reverse the src and dest notion, since the HW expects them
4696+
* to be from Tx perspective where as the input from user is
4697+
* from Rx filter view.
4698+
*/
4699+
input->ipl4_proto = fsp->h_u.usr_ip6_spec.l4_proto;
4700+
input->dst_port = fsp->h_u.tcp_ip6_spec.psrc;
4701+
input->src_port = fsp->h_u.tcp_ip6_spec.pdst;
4702+
memcpy(input->dst_ip6, fsp->h_u.ah_ip6_spec.ip6src,
4703+
sizeof(__be32) * 4);
4704+
memcpy(input->src_ip6, fsp->h_u.ah_ip6_spec.ip6dst,
4705+
sizeof(__be32) * 4);
4706+
} else {
4707+
/* Reverse the src and dest notion, since the HW expects them
4708+
* to be from Tx perspective where as the input from user is
4709+
* from Rx filter view.
4710+
*/
4711+
input->ipl4_proto = fsp->h_u.usr_ip4_spec.proto;
4712+
input->dst_port = fsp->h_u.tcp_ip4_spec.psrc;
4713+
input->src_port = fsp->h_u.tcp_ip4_spec.pdst;
4714+
input->dst_ip = fsp->h_u.tcp_ip4_spec.ip4src;
4715+
input->src_ip = fsp->h_u.tcp_ip4_spec.ip4dst;
4716+
}
45404717

45414718
if (userdef.flex_filter) {
45424719
input->flex_filter = true;

0 commit comments

Comments
 (0)