aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.h
blob: ca8fa32b8680f97a55a0f96d0e88e2d9f1e5338f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved. */

#ifndef	_DR_STE_
#define	_DR_STE_

#include "dr_types.h"

#define STE_IPV4 0x1
#define STE_IPV6 0x2
#define STE_TCP 0x1
#define STE_UDP 0x2
#define STE_SPI 0x3
#define IP_VERSION_IPV4 0x4
#define IP_VERSION_IPV6 0x6
#define STE_SVLAN 0x1
#define STE_CVLAN 0x2
#define HDR_LEN_L2_MACS   0xC
#define HDR_LEN_L2_VLAN   0x4
#define HDR_LEN_L2_ETHER  0x2
#define HDR_LEN_L2        (HDR_LEN_L2_MACS + HDR_LEN_L2_ETHER)
#define HDR_LEN_L2_W_VLAN (HDR_LEN_L2 + HDR_LEN_L2_VLAN)

/* Set to STE a specific value using DR_STE_SET */
#define DR_STE_SET_VAL(lookup_type, tag, t_fname, spec, s_fname, value) do { \
	if ((spec)->s_fname) { \
		MLX5_SET(ste_##lookup_type, tag, t_fname, value); \
		(spec)->s_fname = 0; \
	} \
} while (0)

/* Set to STE spec->s_fname to tag->t_fname set spec->s_fname as used */
#define DR_STE_SET_TAG(lookup_type, tag, t_fname, spec, s_fname) \
	DR_STE_SET_VAL(lookup_type, tag, t_fname, spec, s_fname, spec->s_fname)

/* Set to STE -1 to tag->t_fname and set spec->s_fname as used */
#define DR_STE_SET_ONES(lookup_type, tag, t_fname, spec, s_fname) \
	DR_STE_SET_VAL(lookup_type, tag, t_fname, spec, s_fname, -1)

#define DR_STE_SET_TCP_FLAGS(lookup_type, tag, spec) do { \
	MLX5_SET(ste_##lookup_type, tag, tcp_ns, !!((spec)->tcp_flags & (1 << 8))); \
	MLX5_SET(ste_##lookup_type, tag, tcp_cwr, !!((spec)->tcp_flags & (1 << 7))); \
	MLX5_SET(ste_##lookup_type, tag, tcp_ece, !!((spec)->tcp_flags & (1 << 6))); \
	MLX5_SET(ste_##lookup_type, tag, tcp_urg, !!((spec)->tcp_flags & (1 << 5))); \
	MLX5_SET(ste_##lookup_type, tag, tcp_ack, !!((spec)->tcp_flags & (1 << 4))); \
	MLX5_SET(ste_##lookup_type, tag, tcp_psh, !!((spec)->tcp_flags & (1 << 3))); \
	MLX5_SET(ste_##lookup_type, tag, tcp_rst, !!((spec)->tcp_flags & (1 << 2))); \
	MLX5_SET(ste_##lookup_type, tag, tcp_syn, !!((spec)->tcp_flags & (1 << 1))); \
	MLX5_SET(ste_##lookup_type, tag, tcp_fin, !!((spec)->tcp_flags & (1 << 0))); \
} while (0)

#define DR_STE_SET_MPLS(lookup_type, mask, in_out, tag) do { \
	struct mlx5dr_match_misc2 *_mask = mask; \
	u8 *_tag = tag; \
	DR_STE_SET_TAG(lookup_type, _tag, mpls0_label, _mask, \
		       in_out##_first_mpls_label);\
	DR_STE_SET_TAG(lookup_type, _tag, mpls0_s_bos, _mask, \
		       in_out##_first_mpls_s_bos); \
	DR_STE_SET_TAG(lookup_type, _tag, mpls0_exp, _mask, \
		       in_out##_first_mpls_exp); \
	DR_STE_SET_TAG(lookup_type, _tag, mpls0_ttl, _mask, \
		       in_out##_first_mpls_ttl); \
} while (0)

#define DR_STE_SET_FLEX_PARSER_FIELD(tag, fname, caps, spec) do { \
	u8 parser_id = (caps)->flex_parser_id_##fname; \
	u8 *parser_ptr = dr_ste_calc_flex_parser_offset(tag, parser_id); \
	*(__be32 *)parser_ptr = cpu_to_be32((spec)->fname);\
	(spec)->fname = 0;\
} while (0)

#define DR_STE_IS_OUTER_MPLS_OVER_GRE_SET(_misc) (\
	(_misc)->outer_first_mpls_over_gre_label || \
	(_misc)->outer_first_mpls_over_gre_exp || \
	(_misc)->outer_first_mpls_over_gre_s_bos || \
	(_misc)->outer_first_mpls_over_gre_ttl)

#define DR_STE_IS_OUTER_MPLS_OVER_UDP_SET(_misc) (\
	(_misc)->outer_first_mpls_over_udp_label || \
	(_misc)->outer_first_mpls_over_udp_exp || \
	(_misc)->outer_first_mpls_over_udp_s_bos || \
	(_misc)->outer_first_mpls_over_udp_ttl)

enum dr_ste_action_modify_type_l3 {
	DR_STE_ACTION_MDFY_TYPE_L3_NONE	= 0x0,
	DR_STE_ACTION_MDFY_TYPE_L3_IPV4	= 0x1,
	DR_STE_ACTION_MDFY_TYPE_L3_IPV6	= 0x2,
};

enum dr_ste_action_modify_type_l4 {
	DR_STE_ACTION_MDFY_TYPE_L4_NONE	= 0x0,
	DR_STE_ACTION_MDFY_TYPE_L4_TCP	= 0x1,
	DR_STE_ACTION_MDFY_TYPE_L4_UDP	= 0x2,
};

enum {
	HDR_MPLS_OFFSET_LABEL	= 12,
	HDR_MPLS_OFFSET_EXP	= 9,
	HDR_MPLS_OFFSET_S_BOS	= 8,
	HDR_MPLS_OFFSET_TTL	= 0,
};

u16 mlx5dr_ste_conv_bit_to_byte_mask(u8 *bit_mask);

static inline u8 *
dr_ste_calc_flex_parser_offset(u8 *tag, u8 parser_id)
{
	/* Calculate tag byte offset based on flex parser id */
	return tag + 4 * (3 - (parser_id % 4));
}

#define DR_STE_CTX_BUILDER(fname) \
	((*build_##fname##_init)(struct mlx5dr_ste_build *sb, \
				 struct mlx5dr_match_param *mask))

struct mlx5dr_ste_ctx {
	/* Builders */
	void DR_STE_CTX_BUILDER(eth_l2_src_dst);
	void DR_STE_CTX_BUILDER(eth_l3_ipv6_src);
	void DR_STE_CTX_BUILDER(eth_l3_ipv6_dst);
	void DR_STE_CTX_BUILDER(eth_l3_ipv4_5_tuple);
	void DR_STE_CTX_BUILDER(eth_l2_src);
	void DR_STE_CTX_BUILDER(eth_l2_dst);
	void DR_STE_CTX_BUILDER(eth_l2_tnl);
	void DR_STE_CTX_BUILDER(eth_l3_ipv4_misc);
	void DR_STE_CTX_BUILDER(eth_ipv6_l3_l4);
	void DR_STE_CTX_BUILDER(mpls);
	void DR_STE_CTX_BUILDER(tnl_gre);
	void DR_STE_CTX_BUILDER(tnl_mpls);
	void DR_STE_CTX_BUILDER(tnl_mpls_over_gre);
	void DR_STE_CTX_BUILDER(tnl_mpls_over_udp);
	void DR_STE_CTX_BUILDER(icmp);
	void DR_STE_CTX_BUILDER(general_purpose);
	void DR_STE_CTX_BUILDER(eth_l4_misc);
	void DR_STE_CTX_BUILDER(tnl_vxlan_gpe);
	void DR_STE_CTX_BUILDER(tnl_geneve);
	void DR_STE_CTX_BUILDER(tnl_geneve_tlv_opt);
	void DR_STE_CTX_BUILDER(tnl_geneve_tlv_opt_exist);
	void DR_STE_CTX_BUILDER(register_0);
	void DR_STE_CTX_BUILDER(register_1);
	void DR_STE_CTX_BUILDER(src_gvmi_qpn);
	void DR_STE_CTX_BUILDER(flex_parser_0);
	void DR_STE_CTX_BUILDER(flex_parser_1);
	void DR_STE_CTX_BUILDER(tnl_gtpu);
	void DR_STE_CTX_BUILDER(tnl_header_0_1);
	void DR_STE_CTX_BUILDER(tnl_gtpu_flex_parser_0);
	void DR_STE_CTX_BUILDER(tnl_gtpu_flex_parser_1);

	/* Getters and Setters */
	void (*ste_init)(u8 *hw_ste_p, u16 lu_type,
			 bool is_rx, u16 gvmi);
	void (*set_next_lu_type)(u8 *hw_ste_p, u16 lu_type);
	u16  (*get_next_lu_type)(u8 *hw_ste_p);
	void (*set_miss_addr)(u8 *hw_ste_p, u64 miss_addr);
	u64  (*get_miss_addr)(u8 *hw_ste_p);
	void (*set_hit_addr)(u8 *hw_ste_p, u64 icm_addr, u32 ht_size);
	void (*set_byte_mask)(u8 *hw_ste_p, u16 byte_mask);
	u16  (*get_byte_mask)(u8 *hw_ste_p);

	/* Actions */
	u32 actions_caps;
	void (*set_actions_rx)(struct mlx5dr_domain *dmn,
			       u8 *action_type_set,
			       u8 *hw_ste_arr,
			       struct mlx5dr_ste_actions_attr *attr,
			       u32 *added_stes);
	void (*set_actions_tx)(struct mlx5dr_domain *dmn,
			       u8 *action_type_set,
			       u8 *hw_ste_arr,
			       struct mlx5dr_ste_actions_attr *attr,
			       u32 *added_stes);
	u32 modify_field_arr_sz;
	const struct mlx5dr_ste_action_modify_field *modify_field_arr;
	void (*set_action_set)(u8 *hw_action,
			       u8 hw_field,
			       u8 shifter,
			       u8 length,
			       u32 data);
	void (*set_action_add)(u8 *hw_action,
			       u8 hw_field,
			       u8 shifter,
			       u8 length,
			       u32 data);
	void (*set_action_copy)(u8 *hw_action,
				u8 dst_hw_field,
				u8 dst_shifter,
				u8 dst_len,
				u8 src_hw_field,
				u8 src_shifter);
	int (*set_action_decap_l3_list)(void *data,
					u32 data_sz,
					u8 *hw_action,
					u32 hw_action_sz,
					u16 *used_hw_action_num);

	/* Send */
	void (*prepare_for_postsend)(u8 *hw_ste_p, u32 ste_size);
};

extern struct mlx5dr_ste_ctx ste_ctx_v0;
extern struct mlx5dr_ste_ctx ste_ctx_v1;

#endif  /* _DR_STE_ */