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
print_lyr_2_4_hdrs(struct trace_seq * p,const u32 * mask,const u32 * value)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
80 PRINT_MASKED_VALP(smac, u8 *, p, "%pM");
81 PRINT_MASKED_VALP(dmac, u8 *, p, "%pM");
82 PRINT_MASKED_VAL(ethertype, p, "%04x");
83
84 if (ethertype.m == 0xffff) {
85 if (ethertype.v == ETH_P_IP) {
86 #define MASK_VAL_L2_BE(type, name, fld) \
87 MASK_VAL_BE(type, fte_match_set_lyr_2_4, name, mask, value, fld)
88 MASK_VAL_L2_BE(u32, src_ipv4,
89 src_ipv4_src_ipv6.ipv4_layout.ipv4);
90 MASK_VAL_L2_BE(u32, dst_ipv4,
91 dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
92
93 PRINT_MASKED_VALP(src_ipv4, typeof(&src_ipv4.v), p,
94 "%pI4");
95 PRINT_MASKED_VALP(dst_ipv4, typeof(&dst_ipv4.v), p,
96 "%pI4");
97 } else if (ethertype.v == ETH_P_IPV6) {
98 static const struct in6_addr full_ones = {
99 .in6_u.u6_addr32 = {__constant_htonl(0xffffffff),
100 __constant_htonl(0xffffffff),
101 __constant_htonl(0xffffffff),
102 __constant_htonl(0xffffffff)},
103 };
104 DECLARE_MASK_VAL(struct in6_addr, src_ipv6);
105 DECLARE_MASK_VAL(struct in6_addr, dst_ipv6);
106
107 memcpy(src_ipv6.m.in6_u.u6_addr8,
108 MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask,
109 src_ipv4_src_ipv6.ipv6_layout.ipv6),
110 sizeof(src_ipv6.m));
111 memcpy(dst_ipv6.m.in6_u.u6_addr8,
112 MLX5_ADDR_OF(fte_match_set_lyr_2_4, mask,
113 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
114 sizeof(dst_ipv6.m));
115 memcpy(src_ipv6.v.in6_u.u6_addr8,
116 MLX5_ADDR_OF(fte_match_set_lyr_2_4, value,
117 src_ipv4_src_ipv6.ipv6_layout.ipv6),
118 sizeof(src_ipv6.v));
119 memcpy(dst_ipv6.v.in6_u.u6_addr8,
120 MLX5_ADDR_OF(fte_match_set_lyr_2_4, value,
121 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
122 sizeof(dst_ipv6.v));
123
124 if (!memcmp(&src_ipv6.m, &full_ones, sizeof(full_ones)))
125 trace_seq_printf(p, "src_ipv6=%pI6 ",
126 &src_ipv6.v);
127 if (!memcmp(&dst_ipv6.m, &full_ones, sizeof(full_ones)))
128 trace_seq_printf(p, "dst_ipv6=%pI6 ",
129 &dst_ipv6.v);
130 }
131 }
132
133 #define PRINT_MASKED_VAL_L2(type, name, fld, p, format) {\
134 MASK_VAL_L2(type, name, fld); \
135 PRINT_MASKED_VAL(name, p, format); \
136 }
137
138 PRINT_MASKED_VAL_L2(u8, ip_protocol, ip_protocol, p, "%02x");
139 PRINT_MASKED_VAL_L2(u16, tcp_flags, tcp_flags, p, "%x");
140 PRINT_MASKED_VAL_L2(u16, tcp_sport, tcp_sport, p, "%u");
141 PRINT_MASKED_VAL_L2(u16, tcp_dport, tcp_dport, p, "%u");
142 PRINT_MASKED_VAL_L2(u16, udp_sport, udp_sport, p, "%u");
143 PRINT_MASKED_VAL_L2(u16, udp_dport, udp_dport, p, "%u");
144 PRINT_MASKED_VAL_L2(u16, first_vid, first_vid, p, "%04x");
145 PRINT_MASKED_VAL_L2(u8, first_prio, first_prio, p, "%x");
146 PRINT_MASKED_VAL_L2(u8, first_cfi, first_cfi, p, "%d");
147 PRINT_MASKED_VAL_L2(u8, ip_dscp, ip_dscp, p, "%02x");
148 PRINT_MASKED_VAL_L2(u8, ip_ecn, ip_ecn, p, "%x");
149 PRINT_MASKED_VAL_L2(u8, cvlan_tag, cvlan_tag, p, "%d");
150 PRINT_MASKED_VAL_L2(u8, svlan_tag, svlan_tag, p, "%d");
151 PRINT_MASKED_VAL_L2(u8, frag, frag, p, "%d");
152 }
153
print_misc_parameters_hdrs(struct trace_seq * p,const u32 * mask,const u32 * value)154 static void print_misc_parameters_hdrs(struct trace_seq *p,
155 const u32 *mask, const u32 *value)
156 {
157 #define MASK_VAL_MISC(type, name, fld) \
158 MASK_VAL(type, fte_match_set_misc, name, mask, value, fld)
159 #define PRINT_MASKED_VAL_MISC(type, name, fld, p, format) {\
160 MASK_VAL_MISC(type, name, fld); \
161 PRINT_MASKED_VAL(name, p, format); \
162 }
163 DECLARE_MASK_VAL(u64, gre_key) = {
164 .m = MLX5_GET(fte_match_set_misc, mask, gre_key.nvgre.hi) << 8 |
165 MLX5_GET(fte_match_set_misc, mask, gre_key.nvgre.lo),
166 .v = MLX5_GET(fte_match_set_misc, value, gre_key.nvgre.hi) << 8 |
167 MLX5_GET(fte_match_set_misc, value, gre_key.nvgre.lo)};
168
169 PRINT_MASKED_VAL(gre_key, p, "%llu");
170 PRINT_MASKED_VAL_MISC(u32, source_sqn, source_sqn, p, "%u");
171 PRINT_MASKED_VAL_MISC(u16, source_port, source_port, p, "%u");
172 PRINT_MASKED_VAL_MISC(u8, outer_second_prio, outer_second_prio,
173 p, "%u");
174 PRINT_MASKED_VAL_MISC(u8, outer_second_cfi, outer_second_cfi, p, "%u");
175 PRINT_MASKED_VAL_MISC(u16, outer_second_vid, outer_second_vid, p, "%u");
176 PRINT_MASKED_VAL_MISC(u8, inner_second_prio, inner_second_prio,
177 p, "%u");
178 PRINT_MASKED_VAL_MISC(u8, inner_second_cfi, inner_second_cfi, p, "%u");
179 PRINT_MASKED_VAL_MISC(u16, inner_second_vid, inner_second_vid, p, "%u");
180
181 PRINT_MASKED_VAL_MISC(u8, outer_second_cvlan_tag,
182 outer_second_cvlan_tag, p, "%u");
183 PRINT_MASKED_VAL_MISC(u8, inner_second_cvlan_tag,
184 inner_second_cvlan_tag, p, "%u");
185 PRINT_MASKED_VAL_MISC(u8, outer_second_svlan_tag,
186 outer_second_svlan_tag, p, "%u");
187 PRINT_MASKED_VAL_MISC(u8, inner_second_svlan_tag,
188 inner_second_svlan_tag, p, "%u");
189
190 PRINT_MASKED_VAL_MISC(u8, gre_protocol, gre_protocol, p, "%u");
191
192 PRINT_MASKED_VAL_MISC(u32, vxlan_vni, vxlan_vni, p, "%u");
193 PRINT_MASKED_VAL_MISC(u32, outer_ipv6_flow_label, outer_ipv6_flow_label,
194 p, "%x");
195 PRINT_MASKED_VAL_MISC(u32, inner_ipv6_flow_label, inner_ipv6_flow_label,
196 p, "%x");
197 }
198
parse_fs_hdrs(struct trace_seq * p,u8 match_criteria_enable,const u32 * mask_outer,const u32 * mask_misc,const u32 * mask_inner,const u32 * value_outer,const u32 * value_misc,const u32 * value_inner)199 const char *parse_fs_hdrs(struct trace_seq *p,
200 u8 match_criteria_enable,
201 const u32 *mask_outer,
202 const u32 *mask_misc,
203 const u32 *mask_inner,
204 const u32 *value_outer,
205 const u32 *value_misc,
206 const u32 *value_inner)
207 {
208 const char *ret = trace_seq_buffer_ptr(p);
209
210 if (match_criteria_enable &
211 1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_OUTER_HEADERS) {
212 trace_seq_printf(p, "[outer] ");
213 print_lyr_2_4_hdrs(p, mask_outer, value_outer);
214 }
215
216 if (match_criteria_enable &
217 1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_MISC_PARAMETERS) {
218 trace_seq_printf(p, "[misc] ");
219 print_misc_parameters_hdrs(p, mask_misc, value_misc);
220 }
221 if (match_criteria_enable &
222 1 << MLX5_CREATE_FLOW_GROUP_IN_MATCH_CRITERIA_ENABLE_INNER_HEADERS) {
223 trace_seq_printf(p, "[inner] ");
224 print_lyr_2_4_hdrs(p, mask_inner, value_inner);
225 }
226 trace_seq_putc(p, 0);
227 return ret;
228 }
229
parse_fs_dst(struct trace_seq * p,const struct mlx5_flow_destination * dst,u32 counter_id)230 const char *parse_fs_dst(struct trace_seq *p,
231 const struct mlx5_flow_destination *dst,
232 u32 counter_id)
233 {
234 const char *ret = trace_seq_buffer_ptr(p);
235
236 switch (dst->type) {
237 case MLX5_FLOW_DESTINATION_TYPE_VPORT:
238 trace_seq_printf(p, "vport=%u\n", dst->vport.num);
239 break;
240 case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
241 trace_seq_printf(p, "ft=%p\n", dst->ft);
242 break;
243 case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
244 trace_seq_printf(p, "ft_num=%u\n", dst->ft_num);
245 break;
246 case MLX5_FLOW_DESTINATION_TYPE_TIR:
247 trace_seq_printf(p, "tir=%u\n", dst->tir_num);
248 break;
249 case MLX5_FLOW_DESTINATION_TYPE_COUNTER:
250 trace_seq_printf(p, "counter_id=%u\n", counter_id);
251 break;
252 case MLX5_FLOW_DESTINATION_TYPE_PORT:
253 trace_seq_printf(p, "port\n");
254 break;
255 }
256
257 trace_seq_putc(p, 0);
258 return ret;
259 }
260
261 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_ft);
262 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_ft);
263 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_fg);
264 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_fg);
265 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_set_fte);
266 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_fte);
267 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_rule);
268 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_rule);
269
270