1 /*
2  * Copyright (c) 2017, Mellanox Technologies. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32 
33 #define CREATE_TRACE_POINTS
34 
35 #include "fs_tracepoint.h"
36 #include <linux/stringify.h>
37 
38 #define DECLARE_MASK_VAL(type, name) struct {type m; type v; } name
39 #define MASK_VAL(type, spec, name, mask, val, fld)	\
40 		DECLARE_MASK_VAL(type, name) =		\
41 			{.m = MLX5_GET(spec, mask, fld),\
42 			 .v = MLX5_GET(spec, val, fld)}
43 #define MASK_VAL_BE(type, spec, name, mask, val, fld)	\
44 		    DECLARE_MASK_VAL(type, name) =	\
45 			{.m = MLX5_GET_BE(type, spec, mask, fld),\
46 			 .v = MLX5_GET_BE(type, spec, val, fld)}
47 #define GET_MASKED_VAL(name) (name.m & name.v)
48 
49 #define GET_MASK_VAL(name, type, mask, val, fld)	\
50 		(name.m = MLX5_GET(type, mask, fld),	\
51 		 name.v = MLX5_GET(type, val, fld),	\
52 		 name.m & name.v)
53 #define PRINT_MASKED_VAL(name, p, format) {		\
54 	if (name.m)			\
55 		trace_seq_printf(p, __stringify(name) "=" format " ", name.v); \
56 	}
57 #define PRINT_MASKED_VALP(name, cast, p, format) {	\
58 	if (name.m)			\
59 		trace_seq_printf(p, __stringify(name) "=" format " ",	       \
60 				 (cast)&name.v);\
61 	}
62 
63 static void print_lyr_2_4_hdrs(struct trace_seq *p,
64 			       const u32 *mask, const u32 *value)
65 {
66 #define MASK_VAL_L2(type, name, fld) \
67 	MASK_VAL(type, fte_match_set_lyr_2_4, name, mask, value, fld)
68 	DECLARE_MASK_VAL(u64, smac) = {
69 		.m = MLX5_GET(fte_match_set_lyr_2_4, mask, smac_47_16) << 16 |
70 		     MLX5_GET(fte_match_set_lyr_2_4, mask, smac_15_0),
71 		.v = MLX5_GET(fte_match_set_lyr_2_4, value, smac_47_16) << 16 |
72 		     MLX5_GET(fte_match_set_lyr_2_4, value, smac_15_0)};
73 	DECLARE_MASK_VAL(u64, dmac) = {
74 		.m = MLX5_GET(fte_match_set_lyr_2_4, mask, dmac_47_16) << 16 |
75 		     MLX5_GET(fte_match_set_lyr_2_4, mask, dmac_15_0),
76 		.v = MLX5_GET(fte_match_set_lyr_2_4, value, dmac_47_16) << 16 |
77 		     MLX5_GET(fte_match_set_lyr_2_4, value, dmac_15_0)};
78 	MASK_VAL_L2(u16, ethertype, ethertype);
79 	MASK_VAL_L2(u8, ip_version, ip_version);
80 
81 	PRINT_MASKED_VALP(smac, u8 *, p, "%pM");
82 	PRINT_MASKED_VALP(dmac, u8 *, p, "%pM");
83 	PRINT_MASKED_VAL(ethertype, p, "%04x");
84 
85 	if ((ethertype.m == 0xffff && ethertype.v == ETH_P_IP) ||
86 	    (ip_version.m == 0xf && ip_version.v == 4)) {
87 #define MASK_VAL_L2_BE(type, name, fld) \
88 	MASK_VAL_BE(type, fte_match_set_lyr_2_4, name, mask, value, fld)
89 		MASK_VAL_L2_BE(u32, src_ipv4,
90 			       src_ipv4_src_ipv6.ipv4_layout.ipv4);
91 		MASK_VAL_L2_BE(u32, dst_ipv4,
92 			       dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
93 
94 		PRINT_MASKED_VALP(src_ipv4, typeof(&src_ipv4.v), p,
95 				  "%pI4");
96 		PRINT_MASKED_VALP(dst_ipv4, typeof(&dst_ipv4.v), p,
97 				  "%pI4");
98 	} else if ((ethertype.m == 0xffff && ethertype.v == ETH_P_IPV6) ||
99 		   (ip_version.m == 0xf && ip_version.v == 6)) {
100 		static const struct in6_addr full_ones = {
101 			.in6_u.u6_addr32 = {__constant_htonl(0xffffffff),
102 					    __constant_htonl(0xffffffff),
103 					    __constant_htonl(0xffffffff),
104 					    __constant_htonl(0xffffffff)},
105 		};
106 		DECLARE_MASK_VAL(struct in6_addr, src_ipv6);
107 		DECLARE_MASK_VAL(struct in6_addr, dst_ipv6);
108 
109 		memcpy(src_ipv6.m.in6_u.u6_addr8,
110 		       MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask,
111 				    src_ipv4_src_ipv6.ipv6_layout.ipv6),
112 		       sizeof(src_ipv6.m));
113 		memcpy(dst_ipv6.m.in6_u.u6_addr8,
114 		       MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask,
115 				    dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
116 		       sizeof(dst_ipv6.m));
117 		memcpy(src_ipv6.v.in6_u.u6_addr8,
118 		       MLX5_ADDR_OF(fte_match_set_lyr_2_4, value,
119 				    src_ipv4_src_ipv6.ipv6_layout.ipv6),
120 		       sizeof(src_ipv6.v));
121 		memcpy(dst_ipv6.v.in6_u.u6_addr8,
122 		       MLX5_ADDR_OF(fte_match_set_lyr_2_4, value,
123 				    dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
124 		       sizeof(dst_ipv6.v));
125 
126 		if (!memcmp(&src_ipv6.m, &full_ones, sizeof(full_ones)))
127 			trace_seq_printf(p, "src_ipv6=%pI6 ",
128 					 &src_ipv6.v);
129 		if (!memcmp(&dst_ipv6.m, &full_ones, sizeof(full_ones)))
130 			trace_seq_printf(p, "dst_ipv6=%pI6 ",
131 					 &dst_ipv6.v);
132 	}
133 
134 #define PRINT_MASKED_VAL_L2(type, name, fld, p, format) {\
135 	MASK_VAL_L2(type, name, fld);		         \
136 	PRINT_MASKED_VAL(name, p, format);		 \
137 }
138 
139 	PRINT_MASKED_VAL_L2(u8, ip_protocol, ip_protocol, p, "%02x");
140 	PRINT_MASKED_VAL_L2(u16, tcp_flags, tcp_flags, p, "%x");
141 	PRINT_MASKED_VAL_L2(u16, tcp_sport, tcp_sport, p, "%u");
142 	PRINT_MASKED_VAL_L2(u16, tcp_dport, tcp_dport, p, "%u");
143 	PRINT_MASKED_VAL_L2(u16, udp_sport, udp_sport, p, "%u");
144 	PRINT_MASKED_VAL_L2(u16, udp_dport, udp_dport, p, "%u");
145 	PRINT_MASKED_VAL_L2(u16, first_vid, first_vid, p, "%04x");
146 	PRINT_MASKED_VAL_L2(u8, first_prio, first_prio, p, "%x");
147 	PRINT_MASKED_VAL_L2(u8, first_cfi, first_cfi, p, "%d");
148 	PRINT_MASKED_VAL_L2(u8, ip_dscp, ip_dscp, p, "%02x");
149 	PRINT_MASKED_VAL_L2(u8, ip_ecn, ip_ecn, p, "%x");
150 	PRINT_MASKED_VAL_L2(u8, cvlan_tag, cvlan_tag, p, "%d");
151 	PRINT_MASKED_VAL_L2(u8, svlan_tag, svlan_tag, p, "%d");
152 	PRINT_MASKED_VAL_L2(u8, frag, frag, p, "%d");
153 }
154 
155 static void print_misc_parameters_hdrs(struct trace_seq *p,
156 				       const u32 *mask, const u32 *value)
157 {
158 #define MASK_VAL_MISC(type, name, fld) \
159 	MASK_VAL(type, fte_match_set_misc, name, mask, value, fld)
160 #define PRINT_MASKED_VAL_MISC(type, name, fld, p, format) {\
161 	MASK_VAL_MISC(type, name, fld);			   \
162 	PRINT_MASKED_VAL(name, p, format);		   \
163 }
164 	DECLARE_MASK_VAL(u64, gre_key) = {
165 		.m = MLX5_GET(fte_match_set_misc, mask, gre_key.nvgre.hi) << 8 |
166 		     MLX5_GET(fte_match_set_misc, mask, gre_key.nvgre.lo),
167 		.v = MLX5_GET(fte_match_set_misc, value, gre_key.nvgre.hi) << 8 |
168 		     MLX5_GET(fte_match_set_misc, value, gre_key.nvgre.lo)};
169 
170 	PRINT_MASKED_VAL(gre_key, p, "%llu");
171 	PRINT_MASKED_VAL_MISC(u32, source_sqn, source_sqn, p, "%u");
172 	PRINT_MASKED_VAL_MISC(u16, source_port, source_port, p, "%u");
173 	PRINT_MASKED_VAL_MISC(u8, outer_second_prio, outer_second_prio,
174 			      p, "%u");
175 	PRINT_MASKED_VAL_MISC(u8, outer_second_cfi, outer_second_cfi, p, "%u");
176 	PRINT_MASKED_VAL_MISC(u16, outer_second_vid, outer_second_vid, p, "%u");
177 	PRINT_MASKED_VAL_MISC(u8, inner_second_prio, inner_second_prio,
178 			      p, "%u");
179 	PRINT_MASKED_VAL_MISC(u8, inner_second_cfi, inner_second_cfi, p, "%u");
180 	PRINT_MASKED_VAL_MISC(u16, inner_second_vid, inner_second_vid, p, "%u");
181 
182 	PRINT_MASKED_VAL_MISC(u8, outer_second_cvlan_tag,
183 			      outer_second_cvlan_tag, p, "%u");
184 	PRINT_MASKED_VAL_MISC(u8, inner_second_cvlan_tag,
185 			      inner_second_cvlan_tag, p, "%u");
186 	PRINT_MASKED_VAL_MISC(u8, outer_second_svlan_tag,
187 			      outer_second_svlan_tag, p, "%u");
188 	PRINT_MASKED_VAL_MISC(u8, inner_second_svlan_tag,
189 			      inner_second_svlan_tag, p, "%u");
190 
191 	PRINT_MASKED_VAL_MISC(u8, gre_protocol, gre_protocol, p, "%u");
192 
193 	PRINT_MASKED_VAL_MISC(u32, vxlan_vni, vxlan_vni, p, "%u");
194 	PRINT_MASKED_VAL_MISC(u32, outer_ipv6_flow_label, outer_ipv6_flow_label,
195 			      p, "%x");
196 	PRINT_MASKED_VAL_MISC(u32, inner_ipv6_flow_label, inner_ipv6_flow_label,
197 			      p, "%x");
198 }
199 
200 const char *parse_fs_hdrs(struct trace_seq *p,
201 			  u8 match_criteria_enable,
202 			  const u32 *mask_outer,
203 			  const u32 *mask_misc,
204 			  const u32 *mask_inner,
205 			  const u32 *value_outer,
206 			  const u32 *value_misc,
207 			  const u32 *value_inner)
208 {
209 	const char *ret = trace_seq_buffer_ptr(p);
210 
211 	if (match_criteria_enable &
212 	    1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_OUTER_HEADERS) {
213 		trace_seq_printf(p, "[outer] ");
214 		print_lyr_2_4_hdrs(p, mask_outer, value_outer);
215 	}
216 
217 	if (match_criteria_enable &
218 	    1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_MISC_PARAMETERS) {
219 		trace_seq_printf(p, "[misc] ");
220 		print_misc_parameters_hdrs(p, mask_misc, value_misc);
221 	}
222 	if (match_criteria_enable &
223 	    1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_INNER_HEADERS) {
224 		trace_seq_printf(p, "[inner] ");
225 		print_lyr_2_4_hdrs(p, mask_inner, value_inner);
226 	}
227 	trace_seq_putc(p, 0);
228 	return ret;
229 }
230 
231 const char *parse_fs_dst(struct trace_seq *p,
232 			 const struct mlx5_flow_destination *dst,
233 			 u32 counter_id)
234 {
235 	const char *ret = trace_seq_buffer_ptr(p);
236 
237 	switch (dst->type) {
238 	case MLX5_FLOW_DESTINATION_TYPE_UPLINK:
239 		trace_seq_printf(p, "uplink\n");
240 		break;
241 	case MLX5_FLOW_DESTINATION_TYPE_VPORT:
242 		trace_seq_printf(p, "vport=%u\n", dst->vport.num);
243 		break;
244 	case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
245 		trace_seq_printf(p, "ft=%p\n", dst->ft);
246 		break;
247 	case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
248 		trace_seq_printf(p, "ft_num=%u\n", dst->ft_num);
249 		break;
250 	case MLX5_FLOW_DESTINATION_TYPE_TIR:
251 		trace_seq_printf(p, "tir=%u\n", dst->tir_num);
252 		break;
253 	case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER:
254 		trace_seq_printf(p, "sampler_id=%u\n", dst->sampler_id);
255 		break;
256 	case MLX5_FLOW_DESTINATION_TYPE_COUNTER:
257 		trace_seq_printf(p, "counter_id=%u\n", counter_id);
258 		break;
259 	case MLX5_FLOW_DESTINATION_TYPE_PORT:
260 		trace_seq_printf(p, "port\n");
261 		break;
262 	}
263 
264 	trace_seq_putc(p, 0);
265 	return ret;
266 }
267 
268 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_ft);
269 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_ft);
270 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_fg);
271 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_fg);
272 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_set_fte);
273 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_fte);
274 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_rule);
275 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_rule);
276 
277