@@ -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
32603289no_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