Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/mlx5e: Branch according to classified tunnel type

Currently the tunnel offloading encap/decap methods assumes that VXLAN
is the sole tunneling protocol. Lay the infrastructure for supporting
multiple tunneling protocols by branching according to the tunnel
net device kind.

Encap filters tunnel type is determined according to the egress/mirred
net device. Decap filters classify the tunnel type according to the
filter's ingress net device kind.

Distinguish between the tunnel type as defined by the SW model and
the FW reformat type that specifies the HW operation being made.

Signed-off-by: Oz Shlomo <ozsh@mellanox.com>
Reviewed-by: Eli Britstein <elibr@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>

authored by

Oz Shlomo and committed by
Saeed Mahameed
54c177ca 4d70564d

+114 -48
+2
drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
··· 149 149 150 150 struct net_device *out_dev; 151 151 int tunnel_type; 152 + int tunnel_hlen; 153 + int reformat_type; 152 154 u8 flags; 153 155 char *encap_header; 154 156 int encap_size;
+112 -48
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
··· 79 79 80 80 #define MLX5E_TC_MAX_SPLITS 1 81 81 82 + enum { 83 + MLX5E_TC_TUNNEL_TYPE_UNKNOWN, 84 + MLX5E_TC_TUNNEL_TYPE_VXLAN 85 + }; 86 + 87 + static int mlx5e_get_tunnel_type(struct net_device *tunnel_dev); 88 + 82 89 struct mlx5e_tc_flow { 83 90 struct rhash_head node; 84 91 struct mlx5e_priv *priv; ··· 684 677 } 685 678 } 686 679 680 + static const char *mlx5e_netdev_kind(struct net_device *dev) 681 + { 682 + if (dev->rtnl_link_ops) 683 + return dev->rtnl_link_ops->kind; 684 + else 685 + return ""; 686 + } 687 + 687 688 static int 688 689 mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv, 689 690 struct mlx5e_tc_flow_parse_attr *parse_attr, ··· 1052 1037 struct mlx5e_tc_flow *flow; 1053 1038 int err; 1054 1039 1055 - err = mlx5_packet_reformat_alloc(priv->mdev, e->tunnel_type, 1040 + err = mlx5_packet_reformat_alloc(priv->mdev, 1041 + e->reformat_type, 1056 1042 e->encap_size, e->encap_header, 1057 1043 MLX5_FLOW_NAMESPACE_FDB, 1058 1044 &e->encap_id); ··· 1281 1265 1282 1266 static int parse_tunnel_attr(struct mlx5e_priv *priv, 1283 1267 struct mlx5_flow_spec *spec, 1284 - struct tc_cls_flower_offload *f) 1268 + struct tc_cls_flower_offload *f, 1269 + struct net_device *filter_dev) 1285 1270 { 1286 1271 struct netlink_ext_ack *extack = f->common.extack; 1287 1272 void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, ··· 1294 1277 skb_flow_dissector_target(f->dissector, 1295 1278 FLOW_DISSECTOR_KEY_ENC_CONTROL, 1296 1279 f->key); 1280 + int tunnel_type; 1281 + int err = 0; 1297 1282 1298 - if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) { 1299 - int err = 0; 1300 - 1283 + tunnel_type = mlx5e_get_tunnel_type(filter_dev); 1284 + if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN) { 1301 1285 err = parse_tunnel_vxlan_attr(priv, spec, f, 1302 1286 headers_c, headers_v); 1303 - if (err) 1304 - goto vxlan_match_offload_err; 1305 - } else { /* udp dst port must be given */ 1306 - vxlan_match_offload_err: 1287 + } else { 1307 1288 NL_SET_ERR_MSG_MOD(extack, 1308 - "IP tunnel decap offload supported only for vxlan, must set UDP dport"); 1289 + "decapsulation offload is not supported"); 1309 1290 netdev_warn(priv->netdev, 1310 - "IP tunnel decap offload supported only for vxlan, must set UDP dport\n"); 1291 + "decapsulation offload is not supported for %s net device (%d)\n", 1292 + mlx5e_netdev_kind(filter_dev), tunnel_type); 1293 + return -EOPNOTSUPP; 1294 + } 1295 + 1296 + if (err) { 1297 + NL_SET_ERR_MSG_MOD(extack, 1298 + "failed to parse tunnel attributes"); 1299 + netdev_warn(priv->netdev, 1300 + "failed to parse %s tunnel attributes (%d)\n", 1301 + mlx5e_netdev_kind(filter_dev), tunnel_type); 1311 1302 return -EOPNOTSUPP; 1312 1303 } 1313 1304 ··· 1420 1395 static int __parse_cls_flower(struct mlx5e_priv *priv, 1421 1396 struct mlx5_flow_spec *spec, 1422 1397 struct tc_cls_flower_offload *f, 1398 + struct net_device *filter_dev, 1423 1399 u8 *match_level) 1424 1400 { 1425 1401 struct netlink_ext_ack *extack = f->common.extack; ··· 1472 1446 switch (key->addr_type) { 1473 1447 case FLOW_DISSECTOR_KEY_IPV4_ADDRS: 1474 1448 case FLOW_DISSECTOR_KEY_IPV6_ADDRS: 1475 - if (parse_tunnel_attr(priv, spec, f)) 1449 + if (parse_tunnel_attr(priv, spec, f, filter_dev)) 1476 1450 return -EOPNOTSUPP; 1477 1451 break; 1478 1452 default: ··· 1814 1788 static int parse_cls_flower(struct mlx5e_priv *priv, 1815 1789 struct mlx5e_tc_flow *flow, 1816 1790 struct mlx5_flow_spec *spec, 1817 - struct tc_cls_flower_offload *f) 1791 + struct tc_cls_flower_offload *f, 1792 + struct net_device *filter_dev) 1818 1793 { 1819 1794 struct netlink_ext_ack *extack = f->common.extack; 1820 1795 struct mlx5_core_dev *dev = priv->mdev; ··· 1825 1798 u8 match_level; 1826 1799 int err; 1827 1800 1828 - err = __parse_cls_flower(priv, spec, f, &match_level); 1801 + err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level); 1829 1802 1830 1803 if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) { 1831 1804 rep = rpriv->rep; ··· 2470 2443 } 2471 2444 2472 2445 static int mlx5e_gen_ip_tunnel_header(char buf[], __u8 *ip_proto, 2473 - struct ip_tunnel_key *tun_key) 2446 + struct mlx5e_encap_entry *e) 2474 2447 { 2475 - *ip_proto = IPPROTO_UDP; 2476 - return mlx5e_gen_vxlan_header(buf, tun_key); 2448 + int err = 0; 2449 + struct ip_tunnel_key *key = &e->tun_info.key; 2450 + 2451 + if (e->tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN) { 2452 + *ip_proto = IPPROTO_UDP; 2453 + err = mlx5e_gen_vxlan_header(buf, key); 2454 + } else { 2455 + pr_warn("mlx5: Cannot generate tunnel header for tunnel type (%d)\n" 2456 + , e->tunnel_type); 2457 + err = -EOPNOTSUPP; 2458 + } 2459 + 2460 + return err; 2477 2461 } 2478 2462 2479 2463 static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv, ··· 2494 2456 int max_encap_size = MLX5_CAP_ESW(priv->mdev, max_encap_header_size); 2495 2457 int ipv4_encap_size = ETH_HLEN + 2496 2458 sizeof(struct iphdr) + 2497 - VXLAN_HLEN; 2459 + e->tunnel_hlen; 2498 2460 struct ip_tunnel_key *tun_key = &e->tun_info.key; 2499 2461 struct net_device *out_dev; 2500 2462 struct neighbour *n = NULL; ··· 2565 2527 2566 2528 /* add tunneling protocol header */ 2567 2529 err = mlx5e_gen_ip_tunnel_header((char *)ip + sizeof(struct iphdr), 2568 - &ip->protocol, tun_key); 2530 + &ip->protocol, e); 2569 2531 if (err) 2570 2532 goto destroy_neigh_entry; 2571 2533 ··· 2578 2540 goto out; 2579 2541 } 2580 2542 2581 - err = mlx5_packet_reformat_alloc(priv->mdev, e->tunnel_type, 2543 + err = mlx5_packet_reformat_alloc(priv->mdev, 2544 + e->reformat_type, 2582 2545 ipv4_encap_size, encap_header, 2583 2546 MLX5_FLOW_NAMESPACE_FDB, 2584 2547 &e->encap_id); ··· 2608 2569 int max_encap_size = MLX5_CAP_ESW(priv->mdev, max_encap_header_size); 2609 2570 int ipv6_encap_size = ETH_HLEN + 2610 2571 sizeof(struct ipv6hdr) + 2611 - VXLAN_HLEN; 2572 + e->tunnel_hlen; 2612 2573 struct ip_tunnel_key *tun_key = &e->tun_info.key; 2613 2574 struct net_device *out_dev; 2614 2575 struct neighbour *n = NULL; ··· 2678 2639 2679 2640 /* add tunneling protocol header */ 2680 2641 err = mlx5e_gen_ip_tunnel_header((char *)ip6h + sizeof(struct ipv6hdr), 2681 - &ip6h->nexthdr, tun_key); 2642 + &ip6h->nexthdr, e); 2682 2643 if (err) 2683 2644 goto destroy_neigh_entry; 2684 2645 ··· 2691 2652 goto out; 2692 2653 } 2693 2654 2694 - err = mlx5_packet_reformat_alloc(priv->mdev, e->tunnel_type, 2655 + err = mlx5_packet_reformat_alloc(priv->mdev, 2656 + e->reformat_type, 2695 2657 ipv6_encap_size, encap_header, 2696 2658 MLX5_FLOW_NAMESPACE_FDB, 2697 2659 &e->encap_id); ··· 2714 2674 return err; 2715 2675 } 2716 2676 2677 + static int mlx5e_get_tunnel_type(struct net_device *tunnel_dev) 2678 + { 2679 + if (netif_is_vxlan(tunnel_dev)) 2680 + return MLX5E_TC_TUNNEL_TYPE_VXLAN; 2681 + else 2682 + return MLX5E_TC_TUNNEL_TYPE_UNKNOWN; 2683 + } 2684 + 2717 2685 bool mlx5e_tc_tun_device_to_offload(struct mlx5e_priv *priv, 2718 2686 struct net_device *netdev) 2719 2687 { 2720 - if (netif_is_vxlan(netdev) && 2688 + int tunnel_type = mlx5e_get_tunnel_type(netdev); 2689 + 2690 + if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN && 2721 2691 MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) 2722 2692 return true; 2693 + else 2694 + return false; 2695 + } 2723 2696 2724 - return false; 2697 + static int mlx5e_init_tunnel_attr(struct net_device *tunnel_dev, 2698 + struct mlx5e_priv *priv, 2699 + struct mlx5e_encap_entry *e, 2700 + struct netlink_ext_ack *extack) 2701 + { 2702 + e->tunnel_type = mlx5e_get_tunnel_type(tunnel_dev); 2703 + 2704 + if (e->tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN) { 2705 + int dst_port = be16_to_cpu(e->tun_info.key.tp_dst); 2706 + 2707 + if (!mlx5_vxlan_lookup_port(priv->mdev->vxlan, dst_port)) { 2708 + NL_SET_ERR_MSG_MOD(extack, 2709 + "vxlan udp dport was not registered with the HW"); 2710 + netdev_warn(priv->netdev, 2711 + "%d isn't an offloaded vxlan udp dport\n", 2712 + dst_port); 2713 + return -EOPNOTSUPP; 2714 + } 2715 + e->reformat_type = MLX5_REFORMAT_TYPE_L2_TO_VXLAN; 2716 + e->tunnel_hlen = VXLAN_HLEN; 2717 + } else { 2718 + e->reformat_type = -1; 2719 + e->tunnel_hlen = -1; 2720 + return -EOPNOTSUPP; 2721 + } 2722 + return 0; 2725 2723 } 2726 2724 2727 2725 static int mlx5e_attach_encap(struct mlx5e_priv *priv, ··· 2774 2696 struct mlx5_esw_flow_attr *attr = flow->esw_attr; 2775 2697 struct ip_tunnel_key *key = &tun_info->key; 2776 2698 struct mlx5e_encap_entry *e; 2777 - int tunnel_type, err = 0; 2778 2699 uintptr_t hash_key; 2779 2700 bool found = false; 2780 - 2781 - if (!MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) { 2782 - NL_SET_ERR_MSG_MOD(extack, 2783 - "vxlan HW offloading is not supported"); 2784 - netdev_warn(priv->netdev, 2785 - "vxlan HW offloading is not supported\n"); 2786 - return -EOPNOTSUPP; 2787 - } 2788 - 2789 - if (mlx5_vxlan_lookup_port(priv->mdev->vxlan, be16_to_cpu(key->tp_dst)) && 2790 - MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) { 2791 - tunnel_type = MLX5_REFORMAT_TYPE_L2_TO_VXLAN; 2792 - } else { 2793 - NL_SET_ERR_MSG_MOD(extack, 2794 - "port isn't an offloaded vxlan udp dport"); 2795 - netdev_warn(priv->netdev, 2796 - "%d isn't an offloaded vxlan udp dport\n", be16_to_cpu(key->tp_dst)); 2797 - return -EOPNOTSUPP; 2798 - } 2701 + int err = 0; 2799 2702 2800 2703 hash_key = hash_encap_info(key); 2801 2704 ··· 2797 2738 return -ENOMEM; 2798 2739 2799 2740 e->tun_info = *tun_info; 2800 - e->tunnel_type = tunnel_type; 2741 + err = mlx5e_init_tunnel_attr(mirred_dev, priv, e, extack); 2742 + if (err) 2743 + goto out_err; 2744 + 2801 2745 INIT_LIST_HEAD(&e->flows); 2802 2746 2803 2747 if (family == AF_INET) ··· 3125 3063 goto out; 3126 3064 parse_attr->filter_dev = filter_dev; 3127 3065 flow->esw_attr->parse_attr = parse_attr; 3128 - err = parse_cls_flower(flow->priv, flow, &parse_attr->spec, f); 3066 + err = parse_cls_flower(flow->priv, flow, &parse_attr->spec, 3067 + f, filter_dev); 3129 3068 if (err) 3130 3069 goto err_free; 3131 3070 ··· 3179 3116 goto out; 3180 3117 3181 3118 parse_attr->filter_dev = filter_dev; 3182 - err = parse_cls_flower(flow->priv, flow, &parse_attr->spec, f); 3119 + err = parse_cls_flower(flow->priv, flow, &parse_attr->spec, 3120 + f, filter_dev); 3183 3121 if (err) 3184 3122 goto err_free; 3185 3123