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 case MLX5_FLOW_DESTINATION_TYPE_NONE: 263 trace_seq_printf(p, "none\n"); 264 break; 265 } 266 267 trace_seq_putc(p, 0); 268 return ret; 269 } 270 271 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_ft); 272 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_ft); 273 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_fg); 274 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_fg); 275 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_set_fte); 276 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_fte); 277 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_rule); 278 EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_rule); 279 280