1f828ca6aSEli Cohen // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2f828ca6aSEli Cohen /* Copyright (c) 2018 Mellanox Technologies. */
3f828ca6aSEli Cohen
4f828ca6aSEli Cohen #include <net/bareudp.h>
5f828ca6aSEli Cohen #include <net/mpls.h>
6f828ca6aSEli Cohen #include "en/tc_tun.h"
7f828ca6aSEli Cohen
can_offload(struct mlx5e_priv * priv)8f828ca6aSEli Cohen static bool can_offload(struct mlx5e_priv *priv)
9f828ca6aSEli Cohen {
10f828ca6aSEli Cohen return MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev, reformat_l3_tunnel_to_l2);
11f828ca6aSEli Cohen }
12f828ca6aSEli Cohen
calc_hlen(struct mlx5e_encap_entry * e)13f828ca6aSEli Cohen static int calc_hlen(struct mlx5e_encap_entry *e)
14f828ca6aSEli Cohen {
15f828ca6aSEli Cohen return sizeof(struct udphdr) + MPLS_HLEN;
16f828ca6aSEli Cohen }
17f828ca6aSEli Cohen
init_encap_attr(struct net_device * tunnel_dev,struct mlx5e_priv * priv,struct mlx5e_encap_entry * e,struct netlink_ext_ack * extack)18f828ca6aSEli Cohen static int init_encap_attr(struct net_device *tunnel_dev,
19f828ca6aSEli Cohen struct mlx5e_priv *priv,
20f828ca6aSEli Cohen struct mlx5e_encap_entry *e,
21f828ca6aSEli Cohen struct netlink_ext_ack *extack)
22f828ca6aSEli Cohen {
23f828ca6aSEli Cohen e->tunnel = &mplsoudp_tunnel;
24f828ca6aSEli Cohen e->reformat_type = MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL;
25f828ca6aSEli Cohen return 0;
26f828ca6aSEli Cohen }
27f828ca6aSEli Cohen
generate_ip_tun_hdr(char buf[],__u8 * ip_proto,struct mlx5e_encap_entry * r)28f828ca6aSEli Cohen static int generate_ip_tun_hdr(char buf[],
29f828ca6aSEli Cohen __u8 *ip_proto,
30f828ca6aSEli Cohen struct mlx5e_encap_entry *r)
31f828ca6aSEli Cohen {
32f828ca6aSEli Cohen const struct ip_tunnel_key *tun_key = &r->tun_info->key;
33c63741b4SMaor Dickman const struct mlx5e_mpls_info *mpls_info = &r->mpls_info;
34f828ca6aSEli Cohen struct udphdr *udp = (struct udphdr *)(buf);
35f828ca6aSEli Cohen struct mpls_shim_hdr *mpls;
36f828ca6aSEli Cohen
37f828ca6aSEli Cohen mpls = (struct mpls_shim_hdr *)(udp + 1);
38f828ca6aSEli Cohen *ip_proto = IPPROTO_UDP;
39f828ca6aSEli Cohen
40f828ca6aSEli Cohen udp->dest = tun_key->tp_dst;
41c63741b4SMaor Dickman *mpls = mpls_entry_encode(mpls_info->label, mpls_info->ttl, mpls_info->tc, mpls_info->bos);
42f828ca6aSEli Cohen
43f828ca6aSEli Cohen return 0;
44f828ca6aSEli Cohen }
45f828ca6aSEli Cohen
parse_udp_ports(struct mlx5e_priv * priv,struct mlx5_flow_spec * spec,struct flow_cls_offload * f,void * headers_c,void * headers_v)46f828ca6aSEli Cohen static int parse_udp_ports(struct mlx5e_priv *priv,
47f828ca6aSEli Cohen struct mlx5_flow_spec *spec,
48f828ca6aSEli Cohen struct flow_cls_offload *f,
49f828ca6aSEli Cohen void *headers_c,
50f828ca6aSEli Cohen void *headers_v)
51f828ca6aSEli Cohen {
52f828ca6aSEli Cohen return mlx5e_tc_tun_parse_udp_ports(priv, spec, f, headers_c, headers_v);
53f828ca6aSEli Cohen }
54f828ca6aSEli Cohen
parse_tunnel(struct mlx5e_priv * priv,struct mlx5_flow_spec * spec,struct flow_cls_offload * f,void * headers_c,void * headers_v)55f828ca6aSEli Cohen static int parse_tunnel(struct mlx5e_priv *priv,
56f828ca6aSEli Cohen struct mlx5_flow_spec *spec,
57f828ca6aSEli Cohen struct flow_cls_offload *f,
58f828ca6aSEli Cohen void *headers_c,
59f828ca6aSEli Cohen void *headers_v)
60f828ca6aSEli Cohen {
6172046a91SEli Cohen struct flow_rule *rule = flow_cls_offload_flow_rule(f);
6272046a91SEli Cohen struct flow_match_mpls match;
6372046a91SEli Cohen void *misc2_c;
6472046a91SEli Cohen void *misc2_v;
6572046a91SEli Cohen
66af4c2fabSEli Cohen if (!MLX5_CAP_ETH(priv->mdev, tunnel_stateless_mpls_over_udp) &&
67af4c2fabSEli Cohen !(MLX5_CAP_GEN(priv->mdev, flex_parser_protocols) & MLX5_FLEX_PROTO_CW_MPLS_UDP))
6872046a91SEli Cohen return -EOPNOTSUPP;
6972046a91SEli Cohen
70*fdc18e4eSMaor Dickman if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_KEYID))
71*fdc18e4eSMaor Dickman return -EOPNOTSUPP;
72*fdc18e4eSMaor Dickman
73*fdc18e4eSMaor Dickman if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_MPLS))
74*fdc18e4eSMaor Dickman return 0;
75*fdc18e4eSMaor Dickman
7672046a91SEli Cohen flow_rule_match_mpls(rule, &match);
7772046a91SEli Cohen
7858cff782SGuillaume Nault /* Only support matching the first LSE */
7958cff782SGuillaume Nault if (match.mask->used_lses != 1)
8058cff782SGuillaume Nault return -EOPNOTSUPP;
8172046a91SEli Cohen
82*fdc18e4eSMaor Dickman misc2_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
83*fdc18e4eSMaor Dickman misc_parameters_2);
84*fdc18e4eSMaor Dickman misc2_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
85*fdc18e4eSMaor Dickman misc_parameters_2);
86*fdc18e4eSMaor Dickman
8772046a91SEli Cohen MLX5_SET(fte_match_set_misc2, misc2_c,
8858cff782SGuillaume Nault outer_first_mpls_over_udp.mpls_label,
8958cff782SGuillaume Nault match.mask->ls[0].mpls_label);
9072046a91SEli Cohen MLX5_SET(fte_match_set_misc2, misc2_v,
9158cff782SGuillaume Nault outer_first_mpls_over_udp.mpls_label,
9258cff782SGuillaume Nault match.key->ls[0].mpls_label);
9372046a91SEli Cohen
9472046a91SEli Cohen MLX5_SET(fte_match_set_misc2, misc2_c,
9558cff782SGuillaume Nault outer_first_mpls_over_udp.mpls_exp,
9658cff782SGuillaume Nault match.mask->ls[0].mpls_tc);
9772046a91SEli Cohen MLX5_SET(fte_match_set_misc2, misc2_v,
9858cff782SGuillaume Nault outer_first_mpls_over_udp.mpls_exp, match.key->ls[0].mpls_tc);
9972046a91SEli Cohen
10072046a91SEli Cohen MLX5_SET(fte_match_set_misc2, misc2_c,
10158cff782SGuillaume Nault outer_first_mpls_over_udp.mpls_s_bos,
10258cff782SGuillaume Nault match.mask->ls[0].mpls_bos);
10372046a91SEli Cohen MLX5_SET(fte_match_set_misc2, misc2_v,
10458cff782SGuillaume Nault outer_first_mpls_over_udp.mpls_s_bos,
10558cff782SGuillaume Nault match.key->ls[0].mpls_bos);
10658cff782SGuillaume Nault
10758cff782SGuillaume Nault MLX5_SET(fte_match_set_misc2, misc2_c,
10858cff782SGuillaume Nault outer_first_mpls_over_udp.mpls_ttl,
10958cff782SGuillaume Nault match.mask->ls[0].mpls_ttl);
11058cff782SGuillaume Nault MLX5_SET(fte_match_set_misc2, misc2_v,
11158cff782SGuillaume Nault outer_first_mpls_over_udp.mpls_ttl,
11258cff782SGuillaume Nault match.key->ls[0].mpls_ttl);
11372046a91SEli Cohen spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2;
11472046a91SEli Cohen
115f828ca6aSEli Cohen return 0;
116f828ca6aSEli Cohen }
117f828ca6aSEli Cohen
118f828ca6aSEli Cohen struct mlx5e_tc_tunnel mplsoudp_tunnel = {
119f828ca6aSEli Cohen .tunnel_type = MLX5E_TC_TUNNEL_TYPE_MPLSOUDP,
120f828ca6aSEli Cohen .match_level = MLX5_MATCH_L4,
121f828ca6aSEli Cohen .can_offload = can_offload,
122f828ca6aSEli Cohen .calc_hlen = calc_hlen,
123f828ca6aSEli Cohen .init_encap_attr = init_encap_attr,
124f828ca6aSEli Cohen .generate_ip_tun_hdr = generate_ip_tun_hdr,
125f828ca6aSEli Cohen .parse_udp_ports = parse_udp_ports,
126f828ca6aSEli Cohen .parse_tunnel = parse_tunnel,
127929a2fadSDima Chumak .encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic,
128f828ca6aSEli Cohen };
129