aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSaeed Mahameed <saeedm@mellanox.com>2018-07-05 20:11:09 -0400
committerSaeed Mahameed <saeedm@mellanox.com>2018-08-13 15:50:12 -0400
commitca7deb028a2c7c38e6f743443376dd52ea526f0d (patch)
treec3585ef334c2292bf1f99d76018e719c1bddb581
parent142644f8a1f8b419005d8b3c641e80b32ce2a5f7 (diff)
net/mlx5e: Ethtool steering, ip6 support
Add ip6 support for ethtool flow steering. New supported flow types: ip6|tcp6|udp6| Supported fields: src-ip|dst-ip|src-port|dst-port Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
index cf2491a54d32..c81ab2136cc5 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
@@ -66,11 +66,14 @@ static struct mlx5e_ethtool_table *get_flow_table(struct mlx5e_priv *priv,
66 switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { 66 switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
67 case TCP_V4_FLOW: 67 case TCP_V4_FLOW:
68 case UDP_V4_FLOW: 68 case UDP_V4_FLOW:
69 case TCP_V6_FLOW:
70 case UDP_V6_FLOW:
69 max_tuples = ETHTOOL_NUM_L3_L4_FTS; 71 max_tuples = ETHTOOL_NUM_L3_L4_FTS;
70 prio = MLX5E_ETHTOOL_L3_L4_PRIO + (max_tuples - num_tuples); 72 prio = MLX5E_ETHTOOL_L3_L4_PRIO + (max_tuples - num_tuples);
71 eth_ft = &priv->fs.ethtool.l3_l4_ft[prio]; 73 eth_ft = &priv->fs.ethtool.l3_l4_ft[prio];
72 break; 74 break;
73 case IP_USER_FLOW: 75 case IP_USER_FLOW:
76 case IPV6_USER_FLOW:
74 max_tuples = ETHTOOL_NUM_L3_L4_FTS; 77 max_tuples = ETHTOOL_NUM_L3_L4_FTS;
75 prio = MLX5E_ETHTOOL_L3_L4_PRIO + (max_tuples - num_tuples); 78 prio = MLX5E_ETHTOOL_L3_L4_PRIO + (max_tuples - num_tuples);
76 eth_ft = &priv->fs.ethtool.l3_l4_ft[prio]; 79 eth_ft = &priv->fs.ethtool.l3_l4_ft[prio];
@@ -143,6 +146,29 @@ set_ip4(void *headers_c, void *headers_v, __be32 ip4src_m,
143} 146}
144 147
145static void 148static void
149set_ip6(void *headers_c, void *headers_v, __be32 ip6src_m[4],
150 __be32 ip6src_v[4], __be32 ip6dst_m[4], __be32 ip6dst_v[4])
151{
152 u8 ip6_sz = MLX5_FLD_SZ_BYTES(ipv6_layout, ipv6);
153
154 if (!ipv6_addr_any((struct in6_addr *)ip6src_m)) {
155 memcpy(MLX5E_FTE_ADDR_OF(headers_v, src_ipv4_src_ipv6.ipv6_layout.ipv6),
156 ip6src_v, ip6_sz);
157 memcpy(MLX5E_FTE_ADDR_OF(headers_c, src_ipv4_src_ipv6.ipv6_layout.ipv6),
158 ip6src_m, ip6_sz);
159 }
160 if (!ipv6_addr_any((struct in6_addr *)ip6dst_m)) {
161 memcpy(MLX5E_FTE_ADDR_OF(headers_v, dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
162 ip6dst_v, ip6_sz);
163 memcpy(MLX5E_FTE_ADDR_OF(headers_c, dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
164 ip6dst_m, ip6_sz);
165 }
166
167 MLX5E_FTE_SET(headers_c, ethertype, 0xffff);
168 MLX5E_FTE_SET(headers_v, ethertype, ETH_P_IPV6);
169}
170
171static void
146set_tcp(void *headers_c, void *headers_v, __be16 psrc_m, __be16 psrc_v, 172set_tcp(void *headers_c, void *headers_v, __be16 psrc_m, __be16 psrc_v,
147 __be16 pdst_m, __be16 pdst_v) 173 __be16 pdst_m, __be16 pdst_v)
148{ 174{
@@ -214,6 +240,42 @@ parse_ip4(void *headers_c, void *headers_v, struct ethtool_rx_flow_spec *fs)
214} 240}
215 241
216static void 242static void
243parse_ip6(void *headers_c, void *headers_v, struct ethtool_rx_flow_spec *fs)
244{
245 struct ethtool_usrip6_spec *l3_mask = &fs->m_u.usr_ip6_spec;
246 struct ethtool_usrip6_spec *l3_val = &fs->h_u.usr_ip6_spec;
247
248 set_ip6(headers_c, headers_v, l3_mask->ip6src,
249 l3_val->ip6src, l3_mask->ip6dst, l3_val->ip6dst);
250}
251
252static void
253parse_tcp6(void *headers_c, void *headers_v, struct ethtool_rx_flow_spec *fs)
254{
255 struct ethtool_tcpip6_spec *l4_mask = &fs->m_u.tcp_ip6_spec;
256 struct ethtool_tcpip6_spec *l4_val = &fs->h_u.tcp_ip6_spec;
257
258 set_ip6(headers_c, headers_v, l4_mask->ip6src,
259 l4_val->ip6src, l4_mask->ip6dst, l4_val->ip6dst);
260
261 set_tcp(headers_c, headers_v, l4_mask->psrc, l4_val->psrc,
262 l4_mask->pdst, l4_val->pdst);
263}
264
265static void
266parse_udp6(void *headers_c, void *headers_v, struct ethtool_rx_flow_spec *fs)
267{
268 struct ethtool_tcpip6_spec *l4_mask = &fs->m_u.udp_ip6_spec;
269 struct ethtool_tcpip6_spec *l4_val = &fs->h_u.udp_ip6_spec;
270
271 set_ip6(headers_c, headers_v, l4_mask->ip6src,
272 l4_val->ip6src, l4_mask->ip6dst, l4_val->ip6dst);
273
274 set_udp(headers_c, headers_v, l4_mask->psrc, l4_val->psrc,
275 l4_mask->pdst, l4_val->pdst);
276}
277
278static void
217parse_ether(void *headers_c, void *headers_v, struct ethtool_rx_flow_spec *fs) 279parse_ether(void *headers_c, void *headers_v, struct ethtool_rx_flow_spec *fs)
218{ 280{
219 struct ethhdr *eth_mask = &fs->m_u.ether_spec; 281 struct ethhdr *eth_mask = &fs->m_u.ether_spec;
@@ -264,6 +326,15 @@ static int set_flow_attrs(u32 *match_c, u32 *match_v,
264 case IP_USER_FLOW: 326 case IP_USER_FLOW:
265 parse_ip4(outer_headers_c, outer_headers_v, fs); 327 parse_ip4(outer_headers_c, outer_headers_v, fs);
266 break; 328 break;
329 case TCP_V6_FLOW:
330 parse_tcp6(outer_headers_c, outer_headers_v, fs);
331 break;
332 case UDP_V6_FLOW:
333 parse_udp6(outer_headers_c, outer_headers_v, fs);
334 break;
335 case IPV6_USER_FLOW:
336 parse_ip6(outer_headers_c, outer_headers_v, fs);
337 break;
267 case ETHER_FLOW: 338 case ETHER_FLOW:
268 parse_ether(outer_headers_c, outer_headers_v, fs); 339 parse_ether(outer_headers_c, outer_headers_v, fs);
269 break; 340 break;
@@ -473,6 +544,51 @@ static int validate_ip4(struct ethtool_rx_flow_spec *fs)
473 return ++ntuples; 544 return ++ntuples;
474} 545}
475 546
547static int validate_ip6(struct ethtool_rx_flow_spec *fs)
548{
549 struct ethtool_usrip6_spec *l3_mask = &fs->m_u.usr_ip6_spec;
550 int ntuples = 0;
551
552 if (l3_mask->l4_4_bytes || l3_mask->tclass || l3_mask->l4_proto)
553 return -EINVAL;
554 if (!ipv6_addr_any((struct in6_addr *)l3_mask->ip6src))
555 ntuples++;
556
557 if (!ipv6_addr_any((struct in6_addr *)l3_mask->ip6dst))
558 ntuples++;
559
560 /* Flow is IPv6 */
561 return ++ntuples;
562}
563
564static int validate_tcpudp6(struct ethtool_rx_flow_spec *fs)
565{
566 struct ethtool_tcpip6_spec *l4_mask = &fs->m_u.tcp_ip6_spec;
567 int ntuples = 0;
568
569 if (l4_mask->tclass)
570 return -EINVAL;
571
572 if (!ipv6_addr_any((struct in6_addr *)l4_mask->ip6src))
573 ntuples++;
574
575 if (!ipv6_addr_any((struct in6_addr *)l4_mask->ip6dst))
576 ntuples++;
577
578 if (l4_mask->psrc) {
579 if (!all_ones(l4_mask->psrc))
580 return -EINVAL;
581 ntuples++;
582 }
583 if (l4_mask->pdst) {
584 if (!all_ones(l4_mask->pdst))
585 return -EINVAL;
586 ntuples++;
587 }
588 /* Flow is TCP/UDP */
589 return ++ntuples;
590}
591
476static int validate_vlan(struct ethtool_rx_flow_spec *fs) 592static int validate_vlan(struct ethtool_rx_flow_spec *fs)
477{ 593{
478 if (fs->m_ext.vlan_etype || 594 if (fs->m_ext.vlan_etype ||
@@ -516,6 +632,19 @@ static int validate_flow(struct mlx5e_priv *priv,
516 return ret; 632 return ret;
517 num_tuples += ret; 633 num_tuples += ret;
518 break; 634 break;
635 case TCP_V6_FLOW:
636 case UDP_V6_FLOW:
637 ret = validate_tcpudp6(fs);
638 if (ret < 0)
639 return ret;
640 num_tuples += ret;
641 break;
642 case IPV6_USER_FLOW:
643 ret = validate_ip6(fs);
644 if (ret < 0)
645 return ret;
646 num_tuples += ret;
647 break;
519 default: 648 default:
520 return -ENOTSUPP; 649 return -ENOTSUPP;
521 } 650 }