rdma: add Mellanox mlx5 Direct Verbs receive support
[vpp.git] / src / plugins / rdma / format.c
index c9553b2..89a2a7c 100644 (file)
@@ -48,6 +48,30 @@ t = format (t, "%s%s", t ? " ":"", c);
   return s;
 }
 
+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;
+}
+
 u8 *
 format_rdma_device (u8 * s, va_list * args)
 {
@@ -56,13 +80,33 @@ format_rdma_device (u8 * s, va_list * args)
   rdma_device_t *rd = vec_elt_at_index (rm->devices, i);
   u32 indent = format_get_indent (s);
 
-  s = format (s, "netdev: %v\n", rd->linux_ifname);
+  s = format (s, "netdev %v pci-addr %U\n", rd->linux_ifname,
+             format_vlib_pci_addr, &rd->pci->addr);
   s = format (s, "%Uflags: %U", format_white_space, indent,
              format_rdma_device_flags, rd);
   if (rd->error)
     s = format (s, "\n%Uerror %U", format_white_space, indent,
                format_clib_error, rd->error);
 
+  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));
+    }
+
   return s;
 }
 
@@ -74,11 +118,133 @@ format_rdma_input_trace (u8 * s, va_list * args)
   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);
+  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);
 
   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);
 
+  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));
+    }
+
   return s;
 }