linux/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c
<<
>>
Prefs
   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
  63static 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
 155static 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
 200const 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
 231const 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_VPORT:
 239                trace_seq_printf(p, "vport=%u\n", dst->vport.num);
 240                break;
 241        case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
 242                trace_seq_printf(p, "ft=%p\n", dst->ft);
 243                break;
 244        case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM:
 245                trace_seq_printf(p, "ft_num=%u\n", dst->ft_num);
 246                break;
 247        case MLX5_FLOW_DESTINATION_TYPE_TIR:
 248                trace_seq_printf(p, "tir=%u\n", dst->tir_num);
 249                break;
 250        case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER:
 251                trace_seq_printf(p, "sampler_id=%u\n", dst->sampler_id);
 252                break;
 253        case MLX5_FLOW_DESTINATION_TYPE_COUNTER:
 254                trace_seq_printf(p, "counter_id=%u\n", counter_id);
 255                break;
 256        case MLX5_FLOW_DESTINATION_TYPE_PORT:
 257                trace_seq_printf(p, "port\n");
 258                break;
 259        }
 260
 261        trace_seq_putc(p, 0);
 262        return ret;
 263}
 264
 265EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_ft);
 266EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_ft);
 267EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_fg);
 268EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_fg);
 269EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_set_fte);
 270EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_fte);
 271EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_add_rule);
 272EXPORT_TRACEPOINT_SYMBOL(mlx5_fs_del_rule);
 273
 274