2019-03-25 11:41:34 +01:00
|
|
|
/*
|
|
|
|
|
*------------------------------------------------------------------
|
|
|
|
|
* Copyright (c) 2018 Cisco and/or its affiliates.
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at:
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <vlib/vlib.h>
|
2019-10-15 10:51:11 +02:00
|
|
|
#include <vnet/vnet.h>
|
2019-03-25 11:41:34 +01:00
|
|
|
#include <rdma/rdma.h>
|
|
|
|
|
|
|
|
|
|
u8 *
|
|
|
|
|
format_rdma_device_name (u8 * s, va_list * args)
|
|
|
|
|
{
|
|
|
|
|
u32 i = va_arg (*args, u32);
|
|
|
|
|
rdma_main_t *rm = &rdma_main;
|
|
|
|
|
rdma_device_t *rd = vec_elt_at_index (rm->devices, i);
|
|
|
|
|
|
2019-03-28 23:34:56 +01:00
|
|
|
if (rd->name)
|
2019-09-30 16:43:25 +02:00
|
|
|
return format (s, "%v", rd->name);
|
2019-03-28 23:34:56 +01:00
|
|
|
|
2019-03-25 11:41:34 +01:00
|
|
|
s = format (s, "rdma-%u", rd->dev_instance);
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 *
|
|
|
|
|
format_rdma_device_flags (u8 * s, va_list * args)
|
|
|
|
|
{
|
|
|
|
|
rdma_device_t *rd = va_arg (*args, rdma_device_t *);
|
|
|
|
|
u8 *t = 0;
|
|
|
|
|
|
|
|
|
|
#define _(a, b, c) if (rd->flags & (1 << a)) \
|
|
|
|
|
t = format (t, "%s%s", t ? " ":"", c);
|
|
|
|
|
foreach_rdma_device_flags
|
|
|
|
|
#undef _
|
|
|
|
|
s = format (s, "%v", t);
|
|
|
|
|
vec_free (t);
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-12 11:56:00 +01:00
|
|
|
u8 *
|
|
|
|
|
format_rdma_bit_flag (u8 * s, va_list * args)
|
|
|
|
|
{
|
|
|
|
|
u64 flags = va_arg (*args, u64);
|
|
|
|
|
char **strs = va_arg (*args, char **);
|
|
|
|
|
u32 n_strs = va_arg (*args, u32);
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
while (flags)
|
|
|
|
|
{
|
|
|
|
|
if ((flags & (1 << i)))
|
|
|
|
|
{
|
|
|
|
|
if (i < n_strs && strs[i] != 0)
|
|
|
|
|
s = format (s, " %s", strs[i]);
|
|
|
|
|
else
|
|
|
|
|
s = format (s, " unknown(%u)", i);
|
|
|
|
|
flags ^= 1 << i;
|
|
|
|
|
}
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-25 11:41:34 +01:00
|
|
|
u8 *
|
|
|
|
|
format_rdma_device (u8 * s, va_list * args)
|
|
|
|
|
{
|
2020-03-30 16:16:06 +02:00
|
|
|
vlib_main_t *vm = vlib_get_main ();
|
2019-03-25 11:41:34 +01:00
|
|
|
u32 i = va_arg (*args, u32);
|
|
|
|
|
rdma_main_t *rm = &rdma_main;
|
|
|
|
|
rdma_device_t *rd = vec_elt_at_index (rm->devices, i);
|
2020-03-30 16:16:06 +02:00
|
|
|
vlib_pci_device_info_t *d;
|
2019-03-25 11:41:34 +01:00
|
|
|
u32 indent = format_get_indent (s);
|
|
|
|
|
|
2020-03-12 11:56:00 +01:00
|
|
|
s = format (s, "netdev %v pci-addr %U\n", rd->linux_ifname,
|
|
|
|
|
format_vlib_pci_addr, &rd->pci->addr);
|
2020-03-30 16:16:06 +02:00
|
|
|
if ((d = vlib_pci_get_device_info (vm, &rd->pci->addr, 0)))
|
|
|
|
|
{
|
|
|
|
|
s = format (s, "%Uproduct name: %s\n", format_white_space, indent,
|
|
|
|
|
d->product_name ? (char *) d->product_name : "");
|
|
|
|
|
s = format (s, "%Upart number: %U\n", format_white_space, indent,
|
|
|
|
|
format_vlib_pci_vpd, d->vpd_r, "PN");
|
|
|
|
|
s = format (s, "%Urevision: %U\n", format_white_space, indent,
|
|
|
|
|
format_vlib_pci_vpd, d->vpd_r, "EC");
|
|
|
|
|
s = format (s, "%Userial number: %U\n", format_white_space, indent,
|
|
|
|
|
format_vlib_pci_vpd, d->vpd_r, "SN");
|
|
|
|
|
vlib_pci_free_device_info (d);
|
|
|
|
|
}
|
2019-08-21 15:11:43 +02:00
|
|
|
s = format (s, "%Uflags: %U", format_white_space, indent,
|
|
|
|
|
format_rdma_device_flags, rd);
|
2019-03-25 11:41:34 +01:00
|
|
|
if (rd->error)
|
|
|
|
|
s = format (s, "\n%Uerror %U", format_white_space, indent,
|
|
|
|
|
format_clib_error, rd->error);
|
|
|
|
|
|
2020-03-12 11:56:00 +01:00
|
|
|
if (rd->flags & RDMA_DEVICE_F_MLX5DV)
|
|
|
|
|
{
|
|
|
|
|
struct mlx5dv_context c = { };
|
|
|
|
|
const char *str_flags[7] = { "cqe-v1", "obsolete", "mpw-allowed",
|
|
|
|
|
"enhanced-mpw", "cqe-128b-comp", "cqe-128b-pad",
|
|
|
|
|
"packet-based-credit-mode"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (mlx5dv_query_device (rd->ctx, &c) != 0)
|
|
|
|
|
return s;
|
|
|
|
|
|
|
|
|
|
s = format (s, "\n%Umlx5: version %u", format_white_space, indent,
|
|
|
|
|
c.version);
|
|
|
|
|
s = format (s, "\n%Udevice flags: %U",
|
|
|
|
|
format_white_space, indent + 2,
|
|
|
|
|
format_rdma_bit_flag, c.flags, str_flags,
|
|
|
|
|
ARRAY_LEN (str_flags));
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-25 11:41:34 +01:00
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 *
|
|
|
|
|
format_rdma_input_trace (u8 * s, va_list * args)
|
|
|
|
|
{
|
|
|
|
|
vlib_main_t *vm = va_arg (*args, vlib_main_t *);
|
|
|
|
|
vlib_node_t *node = va_arg (*args, vlib_node_t *);
|
|
|
|
|
rdma_input_trace_t *t = va_arg (*args, rdma_input_trace_t *);
|
|
|
|
|
vnet_main_t *vnm = vnet_get_main ();
|
|
|
|
|
vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, t->hw_if_index);
|
2020-03-12 11:56:00 +01:00
|
|
|
char *l4_hdr_types[8] =
|
|
|
|
|
{ 0, "tcp", "udp", "tcp-empty-ack", "tcp-with-acl" };
|
|
|
|
|
char *l3_hdr_types[4] = { 0, "ip6", "ip4" };
|
|
|
|
|
u8 l3_hdr_type = CQE_FLAG_L3_HDR_TYPE (t->cqe_flags);
|
|
|
|
|
u8 l4_hdr_type = CQE_FLAG_L4_HDR_TYPE (t->cqe_flags);
|
2019-03-25 11:41:34 +01:00
|
|
|
|
|
|
|
|
s = format (s, "rdma: %v (%d) next-node %U",
|
|
|
|
|
hi->name, t->hw_if_index, format_vlib_next_node_name, vm,
|
|
|
|
|
node->index, t->next_index);
|
|
|
|
|
|
2020-03-12 11:56:00 +01:00
|
|
|
if (t->cqe_flags & CQE_FLAG_L2_OK)
|
|
|
|
|
s = format (s, " l2-ok");
|
|
|
|
|
|
|
|
|
|
if (t->cqe_flags & CQE_FLAG_L3_OK)
|
|
|
|
|
s = format (s, " l3-ok");
|
|
|
|
|
|
|
|
|
|
if (t->cqe_flags & CQE_FLAG_L4_OK)
|
|
|
|
|
s = format (s, " l4-ok");
|
|
|
|
|
|
|
|
|
|
if (t->cqe_flags & CQE_FLAG_IP_FRAG)
|
|
|
|
|
s = format (s, " ip-frag");
|
|
|
|
|
|
|
|
|
|
if (l3_hdr_type)
|
|
|
|
|
s = format (s, " %s", l3_hdr_types[l3_hdr_type]);
|
|
|
|
|
|
|
|
|
|
if (l4_hdr_type)
|
|
|
|
|
s = format (s, " %s", l4_hdr_types[l4_hdr_type]);
|
|
|
|
|
|
|
|
|
|
if ((t->cqe_flags & CQE_FLAG_IP_EXT_OPTS))
|
|
|
|
|
{
|
|
|
|
|
if (l3_hdr_type == CQE_FLAG_L3_HDR_TYPE_IP6)
|
|
|
|
|
s = format (s, " ip4-ext-hdr");
|
|
|
|
|
if (l3_hdr_type == CQE_FLAG_L3_HDR_TYPE_IP4)
|
|
|
|
|
s = format (s, " ip4-opt");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static u8 *
|
|
|
|
|
format_mlx5_bits (u8 * s, va_list * args)
|
|
|
|
|
{
|
|
|
|
|
void *ptr = va_arg (*args, void *);
|
|
|
|
|
u32 offset = va_arg (*args, u32);
|
|
|
|
|
u32 sb = va_arg (*args, u32);
|
|
|
|
|
u32 eb = va_arg (*args, u32);
|
|
|
|
|
|
|
|
|
|
if (sb == 63 && eb == 0)
|
|
|
|
|
{
|
|
|
|
|
u64 x = mlx5_get_u64 (ptr, offset);
|
|
|
|
|
return format (s, "0x%lx", x);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u32 x = mlx5_get_bits (ptr, offset, sb, eb);
|
|
|
|
|
s = format (s, "%d", x);
|
|
|
|
|
if (x > 9)
|
|
|
|
|
s = format (s, " (0x%x)", x);
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static u8 *
|
|
|
|
|
format_mlx5_field (u8 * s, va_list * args)
|
|
|
|
|
{
|
|
|
|
|
void *ptr = va_arg (*args, void *);
|
|
|
|
|
u32 offset = va_arg (*args, u32);
|
|
|
|
|
u32 sb = va_arg (*args, u32);
|
|
|
|
|
u32 eb = va_arg (*args, u32);
|
|
|
|
|
char *name = va_arg (*args, char *);
|
|
|
|
|
|
|
|
|
|
u8 *tmp = 0;
|
|
|
|
|
|
|
|
|
|
tmp = format (0, "0x%02x %s ", offset, name);
|
|
|
|
|
if (sb == eb)
|
|
|
|
|
tmp = format (tmp, "[%u]", sb);
|
|
|
|
|
else
|
|
|
|
|
tmp = format (tmp, "[%u:%u]", sb, eb);
|
|
|
|
|
s = format (s, "%-45v = %U", tmp, format_mlx5_bits, ptr, offset, sb, eb);
|
|
|
|
|
vec_free (tmp);
|
|
|
|
|
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 *
|
|
|
|
|
format_mlx5_cqe_rx (u8 * s, va_list * args)
|
|
|
|
|
{
|
|
|
|
|
void *cqe = va_arg (*args, void *);
|
|
|
|
|
uword indent = format_get_indent (s);
|
|
|
|
|
int line = 0;
|
|
|
|
|
|
|
|
|
|
#define _(a, b, c, d) \
|
|
|
|
|
if (mlx5_get_bits (cqe, a, b, c)) \
|
|
|
|
|
s = format (s, "%U%U\n", \
|
|
|
|
|
format_white_space, line++ ? indent : 0, \
|
|
|
|
|
format_mlx5_field, cqe, a, b, c, #d);
|
|
|
|
|
foreach_cqe_rx_field;
|
|
|
|
|
#undef _
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u8 *
|
|
|
|
|
format_rdma_rxq (u8 * s, va_list * args)
|
|
|
|
|
{
|
|
|
|
|
rdma_device_t *rd = va_arg (*args, rdma_device_t *);
|
|
|
|
|
u32 queue_index = va_arg (*args, u32);
|
|
|
|
|
rdma_rxq_t *rxq = vec_elt_at_index (rd->rxqs, queue_index);
|
|
|
|
|
u32 indent = format_get_indent (s);
|
|
|
|
|
|
|
|
|
|
s = format (s, "size %u head %u tail %u", rxq->size, rxq->head, rxq->tail);
|
|
|
|
|
|
|
|
|
|
if (rd->flags & RDMA_DEVICE_F_MLX5DV)
|
|
|
|
|
{
|
|
|
|
|
u32 next_cqe_index = rxq->cq_ci & (rxq->size - 1);
|
|
|
|
|
s = format (s, "\n%Uwq: stride %u wqe-cnt %u",
|
|
|
|
|
format_white_space, indent + 2, rxq->wq_stride,
|
|
|
|
|
rxq->wqe_cnt);
|
|
|
|
|
s = format (s, "\n%Ucq: cqn %u cqe-cnt %u ci %u",
|
|
|
|
|
format_white_space, indent + 2, rxq->cqn,
|
|
|
|
|
1 << rxq->log2_cq_size, rxq->cq_ci);
|
|
|
|
|
s = format (s, "\n%Unext-cqe(%u):", format_white_space, indent + 4,
|
|
|
|
|
next_cqe_index);
|
|
|
|
|
s = format (s, "\n%U%U", format_white_space, indent + 6,
|
|
|
|
|
format_mlx5_cqe_rx, rxq->cqes + next_cqe_index);
|
|
|
|
|
s = format (s, "\n%U%U", format_white_space, indent + 6,
|
|
|
|
|
format_hexdump, rxq->cqes + next_cqe_index,
|
|
|
|
|
sizeof (mlx5dv_cqe_t));
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-25 11:41:34 +01:00
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* fd.io coding-style-patch-verification: ON
|
|
|
|
|
*
|
|
|
|
|
* Local Variables:
|
|
|
|
|
* eval: (c-set-style "gnu")
|
|
|
|
|
* End:
|
|
|
|
|
*/
|