1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2018 Mellanox Technologies. */
4 #include <net/bareudp.h>
8 static bool can_offload(struct mlx5e_priv *priv)
10 return MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev, reformat_l3_tunnel_to_l2);
13 static int calc_hlen(struct mlx5e_encap_entry *e)
15 return sizeof(struct udphdr) + MPLS_HLEN;
18 static int init_encap_attr(struct net_device *tunnel_dev,
19 struct mlx5e_priv *priv,
20 struct mlx5e_encap_entry *e,
21 struct netlink_ext_ack *extack)
23 e->tunnel = &mplsoudp_tunnel;
24 e->reformat_type = MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL;
28 static int generate_ip_tun_hdr(char buf[],
30 struct mlx5e_encap_entry *r)
32 const struct ip_tunnel_key *tun_key = &r->tun_info->key;
33 struct udphdr *udp = (struct udphdr *)(buf);
34 struct mpls_shim_hdr *mpls;
37 tun_id = be32_to_cpu(tunnel_id_to_key32(tun_key->tun_id));
38 mpls = (struct mpls_shim_hdr *)(udp + 1);
39 *ip_proto = IPPROTO_UDP;
41 udp->dest = tun_key->tp_dst;
42 *mpls = mpls_entry_encode(tun_id, tun_key->ttl, tun_key->tos, true);
47 static int parse_udp_ports(struct mlx5e_priv *priv,
48 struct mlx5_flow_spec *spec,
49 struct flow_cls_offload *f,
53 return mlx5e_tc_tun_parse_udp_ports(priv, spec, f, headers_c, headers_v);
56 static int parse_tunnel(struct mlx5e_priv *priv,
57 struct mlx5_flow_spec *spec,
58 struct flow_cls_offload *f,
62 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
63 struct flow_match_enc_keyid enc_keyid;
64 struct flow_match_mpls match;
68 misc2_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
70 misc2_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
73 if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS))
76 if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID))
79 flow_rule_match_enc_keyid(rule, &enc_keyid);
81 if (!enc_keyid.mask->keyid)
84 if (!MLX5_CAP_ETH(priv->mdev, tunnel_stateless_mpls_over_udp) &&
85 !(MLX5_CAP_GEN(priv->mdev, flex_parser_protocols) & MLX5_FLEX_PROTO_CW_MPLS_UDP))
88 flow_rule_match_mpls(rule, &match);
90 /* Only support matching the first LSE */
91 if (match.mask->used_lses != 1)
94 MLX5_SET(fte_match_set_misc2, misc2_c,
95 outer_first_mpls_over_udp.mpls_label,
96 match.mask->ls[0].mpls_label);
97 MLX5_SET(fte_match_set_misc2, misc2_v,
98 outer_first_mpls_over_udp.mpls_label,
99 match.key->ls[0].mpls_label);
101 MLX5_SET(fte_match_set_misc2, misc2_c,
102 outer_first_mpls_over_udp.mpls_exp,
103 match.mask->ls[0].mpls_tc);
104 MLX5_SET(fte_match_set_misc2, misc2_v,
105 outer_first_mpls_over_udp.mpls_exp, match.key->ls[0].mpls_tc);
107 MLX5_SET(fte_match_set_misc2, misc2_c,
108 outer_first_mpls_over_udp.mpls_s_bos,
109 match.mask->ls[0].mpls_bos);
110 MLX5_SET(fte_match_set_misc2, misc2_v,
111 outer_first_mpls_over_udp.mpls_s_bos,
112 match.key->ls[0].mpls_bos);
114 MLX5_SET(fte_match_set_misc2, misc2_c,
115 outer_first_mpls_over_udp.mpls_ttl,
116 match.mask->ls[0].mpls_ttl);
117 MLX5_SET(fte_match_set_misc2, misc2_v,
118 outer_first_mpls_over_udp.mpls_ttl,
119 match.key->ls[0].mpls_ttl);
120 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
125 struct mlx5e_tc_tunnel mplsoudp_tunnel = {
126 .tunnel_type = MLX5E_TC_TUNNEL_TYPE_MPLSOUDP,
127 .match_level = MLX5_MATCH_L4,
128 .can_offload = can_offload,
129 .calc_hlen = calc_hlen,
130 .init_encap_attr = init_encap_attr,
131 .generate_ip_tun_hdr = generate_ip_tun_hdr,
132 .parse_udp_ports = parse_udp_ports,
133 .parse_tunnel = parse_tunnel,
134 .encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic,