1fe750c24SBenoît Ganne/*
2fe750c24SBenoît Ganne *------------------------------------------------------------------
3fe750c24SBenoît Ganne * Copyright (c) 2018 Cisco and/or its affiliates.
4fe750c24SBenoît Ganne * Licensed under the Apache License, Version 2.0 (the "License");
5fe750c24SBenoît Ganne * you may not use this file except in compliance with the License.
6fe750c24SBenoît Ganne * You may obtain a copy of the License at:
7fe750c24SBenoît Ganne *
8fe750c24SBenoît Ganne *     http://www.apache.org/licenses/LICENSE-2.0
9fe750c24SBenoît Ganne *
10fe750c24SBenoît Ganne * Unless required by applicable law or agreed to in writing, software
11fe750c24SBenoît Ganne * distributed under the License is distributed on an "AS IS" BASIS,
12fe750c24SBenoît Ganne * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fe750c24SBenoît Ganne * See the License for the specific language governing permissions and
14fe750c24SBenoît Ganne * limitations under the License.
15fe750c24SBenoît Ganne *------------------------------------------------------------------
16fe750c24SBenoît Ganne */
17fe750c24SBenoît Ganne
18fe750c24SBenoît Ganne#include <vlib/vlib.h>
19812afe71SBenoît Ganne#include <vnet/vnet.h>
20fe750c24SBenoît Ganne#include <rdma/rdma.h>
21fe750c24SBenoît Ganne
22fe750c24SBenoît Ganneu8 *
23fe750c24SBenoît Ganneformat_rdma_device_name (u8 * s, va_list * args)
24fe750c24SBenoît Ganne{
25fe750c24SBenoît Ganne  u32 i = va_arg (*args, u32);
26fe750c24SBenoît Ganne  rdma_main_t *rm = &rdma_main;
27fe750c24SBenoît Ganne  rdma_device_t *rd = vec_elt_at_index (rm->devices, i);
28fe750c24SBenoît Ganne
2996d4e533SDamjan Marion  if (rd->name)
307ff07354SBenoît Ganne    return format (s, "%v", rd->name);
3196d4e533SDamjan Marion
32fe750c24SBenoît Ganne  s = format (s, "rdma-%u", rd->dev_instance);
33fe750c24SBenoît Ganne  return s;
34fe750c24SBenoît Ganne}
35fe750c24SBenoît Ganne
36fe750c24SBenoît Ganneu8 *
37fe750c24SBenoît Ganneformat_rdma_device_flags (u8 * s, va_list * args)
38fe750c24SBenoît Ganne{
39fe750c24SBenoît Ganne  rdma_device_t *rd = va_arg (*args, rdma_device_t *);
40fe750c24SBenoît Ganne  u8 *t = 0;
41fe750c24SBenoît Ganne
42fe750c24SBenoît Ganne#define _(a, b, c) if (rd->flags & (1 << a)) \
43fe750c24SBenoît Gannet = format (t, "%s%s", t ? " ":"", c);
44fe750c24SBenoît Ganne  foreach_rdma_device_flags
45fe750c24SBenoît Ganne#undef _
46fe750c24SBenoît Ganne    s = format (s, "%v", t);
47fe750c24SBenoît Ganne  vec_free (t);
48fe750c24SBenoît Ganne  return s;
49fe750c24SBenoît Ganne}
50fe750c24SBenoît Ganne
51dd648aacSDamjan Marionu8 *
52dd648aacSDamjan Marionformat_rdma_bit_flag (u8 * s, va_list * args)
53dd648aacSDamjan Marion{
54dd648aacSDamjan Marion  u64 flags = va_arg (*args, u64);
55dd648aacSDamjan Marion  char **strs = va_arg (*args, char **);
56dd648aacSDamjan Marion  u32 n_strs = va_arg (*args, u32);
57dd648aacSDamjan Marion  int i = 0;
58dd648aacSDamjan Marion
59dd648aacSDamjan Marion  while (flags)
60dd648aacSDamjan Marion    {
61dd648aacSDamjan Marion      if ((flags & (1 << i)))
62dd648aacSDamjan Marion	{
63dd648aacSDamjan Marion	  if (i < n_strs && strs[i] != 0)
64dd648aacSDamjan Marion	    s = format (s, " %s", strs[i]);
65dd648aacSDamjan Marion	  else
66dd648aacSDamjan Marion	    s = format (s, " unknown(%u)", i);
67dd648aacSDamjan Marion	  flags ^= 1 << i;
68dd648aacSDamjan Marion	}
69dd648aacSDamjan Marion      i++;
70dd648aacSDamjan Marion    }
71dd648aacSDamjan Marion
72dd648aacSDamjan Marion  return s;
73dd648aacSDamjan Marion}
74dd648aacSDamjan Marion
75fe750c24SBenoît Ganneu8 *
76fe750c24SBenoît Ganneformat_rdma_device (u8 * s, va_list * args)
77fe750c24SBenoît Ganne{
78e6b4a5acSDamjan Marion  vlib_main_t *vm = vlib_get_main ();
79fe750c24SBenoît Ganne  u32 i = va_arg (*args, u32);
80fe750c24SBenoît Ganne  rdma_main_t *rm = &rdma_main;
81fe750c24SBenoît Ganne  rdma_device_t *rd = vec_elt_at_index (rm->devices, i);
82e6b4a5acSDamjan Marion  vlib_pci_device_info_t *d;
83fe750c24SBenoît Ganne  u32 indent = format_get_indent (s);
84fe750c24SBenoît Ganne
85dd648aacSDamjan Marion  s = format (s, "netdev %v pci-addr %U\n", rd->linux_ifname,
86dd648aacSDamjan Marion	      format_vlib_pci_addr, &rd->pci->addr);
87e6b4a5acSDamjan Marion  if ((d = vlib_pci_get_device_info (vm, &rd->pci->addr, 0)))
88e6b4a5acSDamjan Marion    {
89e6b4a5acSDamjan Marion      s = format (s, "%Uproduct name: %s\n", format_white_space, indent,
90e6b4a5acSDamjan Marion		  d->product_name ? (char *) d->product_name : "");
91e6b4a5acSDamjan Marion      s = format (s, "%Upart number: %U\n", format_white_space, indent,
92e6b4a5acSDamjan Marion		  format_vlib_pci_vpd, d->vpd_r, "PN");
93e6b4a5acSDamjan Marion      s = format (s, "%Urevision: %U\n", format_white_space, indent,
94e6b4a5acSDamjan Marion		  format_vlib_pci_vpd, d->vpd_r, "EC");
95e6b4a5acSDamjan Marion      s = format (s, "%Userial number: %U\n", format_white_space, indent,
96e6b4a5acSDamjan Marion		  format_vlib_pci_vpd, d->vpd_r, "SN");
97e6b4a5acSDamjan Marion      vlib_pci_free_device_info (d);
98e6b4a5acSDamjan Marion    }
99e7e8bf37SBenoît Ganne  s = format (s, "%Uflags: %U", format_white_space, indent,
100e7e8bf37SBenoît Ganne	      format_rdma_device_flags, rd);
101fe750c24SBenoît Ganne  if (rd->error)
102fe750c24SBenoît Ganne    s = format (s, "\n%Uerror %U", format_white_space, indent,
103fe750c24SBenoît Ganne		format_clib_error, rd->error);
104fe750c24SBenoît Ganne
105dd648aacSDamjan Marion  if (rd->flags & RDMA_DEVICE_F_MLX5DV)
106dd648aacSDamjan Marion    {
107dd648aacSDamjan Marion      struct mlx5dv_context c = { };
108dd648aacSDamjan Marion      const char *str_flags[7] = { "cqe-v1", "obsolete", "mpw-allowed",
109dd648aacSDamjan Marion	"enhanced-mpw", "cqe-128b-comp", "cqe-128b-pad",
110dd648aacSDamjan Marion	"packet-based-credit-mode"
111dd648aacSDamjan Marion      };
112dd648aacSDamjan Marion
113dd648aacSDamjan Marion      if (mlx5dv_query_device (rd->ctx, &c) != 0)
114dd648aacSDamjan Marion	return s;
115dd648aacSDamjan Marion
116dd648aacSDamjan Marion      s = format (s, "\n%Umlx5: version %u", format_white_space, indent,
117dd648aacSDamjan Marion		  c.version);
118dd648aacSDamjan Marion      s = format (s, "\n%Udevice flags: %U",
119dd648aacSDamjan Marion		  format_white_space, indent + 2,
120dd648aacSDamjan Marion		  format_rdma_bit_flag, c.flags, str_flags,
121dd648aacSDamjan Marion		  ARRAY_LEN (str_flags));
122dd648aacSDamjan Marion    }
123dd648aacSDamjan Marion
124fe750c24SBenoît Ganne  return s;
125fe750c24SBenoît Ganne}
126fe750c24SBenoît Ganne
127fe750c24SBenoît Ganneu8 *
128fe750c24SBenoît Ganneformat_rdma_input_trace (u8 * s, va_list * args)
129fe750c24SBenoît Ganne{
130fe750c24SBenoît Ganne  vlib_main_t *vm = va_arg (*args, vlib_main_t *);
131fe750c24SBenoît Ganne  vlib_node_t *node = va_arg (*args, vlib_node_t *);
132fe750c24SBenoît Ganne  rdma_input_trace_t *t = va_arg (*args, rdma_input_trace_t *);
133fe750c24SBenoît Ganne  vnet_main_t *vnm = vnet_get_main ();
134fe750c24SBenoît Ganne  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, t->hw_if_index);
135dd648aacSDamjan Marion  char *l4_hdr_types[8] =
136dd648aacSDamjan Marion    { 0, "tcp", "udp", "tcp-empty-ack", "tcp-with-acl" };
137dd648aacSDamjan Marion  char *l3_hdr_types[4] = { 0, "ip6", "ip4" };
138dd648aacSDamjan Marion  u8 l3_hdr_type = CQE_FLAG_L3_HDR_TYPE (t->cqe_flags);
139dd648aacSDamjan Marion  u8 l4_hdr_type = CQE_FLAG_L4_HDR_TYPE (t->cqe_flags);
140fe750c24SBenoît Ganne
141fe750c24SBenoît Ganne  s = format (s, "rdma: %v (%d) next-node %U",
142fe750c24SBenoît Ganne	      hi->name, t->hw_if_index, format_vlib_next_node_name, vm,
143fe750c24SBenoît Ganne	      node->index, t->next_index);
144fe750c24SBenoît Ganne
145dd648aacSDamjan Marion  if (t->cqe_flags & CQE_FLAG_L2_OK)
146dd648aacSDamjan Marion    s = format (s, " l2-ok");
147dd648aacSDamjan Marion
148dd648aacSDamjan Marion  if (t->cqe_flags & CQE_FLAG_L3_OK)
149dd648aacSDamjan Marion    s = format (s, " l3-ok");
150dd648aacSDamjan Marion
151dd648aacSDamjan Marion  if (t->cqe_flags & CQE_FLAG_L4_OK)
152dd648aacSDamjan Marion    s = format (s, " l4-ok");
153dd648aacSDamjan Marion
154dd648aacSDamjan Marion  if (t->cqe_flags & CQE_FLAG_IP_FRAG)
155dd648aacSDamjan Marion    s = format (s, " ip-frag");
156dd648aacSDamjan Marion
157dd648aacSDamjan Marion  if (l3_hdr_type)
158dd648aacSDamjan Marion    s = format (s, " %s", l3_hdr_types[l3_hdr_type]);
159dd648aacSDamjan Marion
160dd648aacSDamjan Marion  if (l4_hdr_type)
161dd648aacSDamjan Marion    s = format (s, " %s", l4_hdr_types[l4_hdr_type]);
162dd648aacSDamjan Marion
163dd648aacSDamjan Marion  if ((t->cqe_flags & CQE_FLAG_IP_EXT_OPTS))
164dd648aacSDamjan Marion    {
165dd648aacSDamjan Marion      if (l3_hdr_type == CQE_FLAG_L3_HDR_TYPE_IP6)
166dd648aacSDamjan Marion	s = format (s, " ip4-ext-hdr");
167dd648aacSDamjan Marion      if (l3_hdr_type == CQE_FLAG_L3_HDR_TYPE_IP4)
168dd648aacSDamjan Marion	s = format (s, " ip4-opt");
169dd648aacSDamjan Marion    }
170dd648aacSDamjan Marion
171dd648aacSDamjan Marion  return s;
172dd648aacSDamjan Marion}
173dd648aacSDamjan Marion
174dd648aacSDamjan Marionstatic u8 *
175dd648aacSDamjan Marionformat_mlx5_bits (u8 * s, va_list * args)
176dd648aacSDamjan Marion{
177dd648aacSDamjan Marion  void *ptr = va_arg (*args, void *);
178dd648aacSDamjan Marion  u32 offset = va_arg (*args, u32);
179dd648aacSDamjan Marion  u32 sb = va_arg (*args, u32);
180dd648aacSDamjan Marion  u32 eb = va_arg (*args, u32);
181dd648aacSDamjan Marion
182dd648aacSDamjan Marion  if (sb == 63 && eb == 0)
183dd648aacSDamjan Marion    {
184dd648aacSDamjan Marion      u64 x = mlx5_get_u64 (ptr, offset);
185dd648aacSDamjan Marion      return format (s, "0x%lx", x);
186dd648aacSDamjan Marion    }
187dd648aacSDamjan Marion
188dd648aacSDamjan Marion  u32 x = mlx5_get_bits (ptr, offset, sb, eb);
189dd648aacSDamjan Marion  s = format (s, "%d", x);
190dd648aacSDamjan Marion  if (x > 9)
191dd648aacSDamjan Marion    s = format (s, " (0x%x)", x);
192dd648aacSDamjan Marion  return s;
193dd648aacSDamjan Marion}
194dd648aacSDamjan Marion
195dd648aacSDamjan Marionstatic u8 *
196dd648aacSDamjan Marionformat_mlx5_field (u8 * s, va_list * args)
197dd648aacSDamjan Marion{
198dd648aacSDamjan Marion  void *ptr = va_arg (*args, void *);
199dd648aacSDamjan Marion  u32 offset = va_arg (*args, u32);
200dd648aacSDamjan Marion  u32 sb = va_arg (*args, u32);
201dd648aacSDamjan Marion  u32 eb = va_arg (*args, u32);
202dd648aacSDamjan Marion  char *name = va_arg (*args, char *);
203dd648aacSDamjan Marion
204dd648aacSDamjan Marion  u8 *tmp = 0;
205dd648aacSDamjan Marion
206dd648aacSDamjan Marion  tmp = format (0, "0x%02x %s ", offset, name);
207dd648aacSDamjan Marion  if (sb == eb)
208dd648aacSDamjan Marion    tmp = format (tmp, "[%u]", sb);
209dd648aacSDamjan Marion  else
210dd648aacSDamjan Marion    tmp = format (tmp, "[%u:%u]", sb, eb);
211dd648aacSDamjan Marion  s = format (s, "%-45v = %U", tmp, format_mlx5_bits, ptr, offset, sb, eb);
212dd648aacSDamjan Marion  vec_free (tmp);
213dd648aacSDamjan Marion
214dd648aacSDamjan Marion  return s;
215dd648aacSDamjan Marion}
216dd648aacSDamjan Marion
217dd648aacSDamjan Marionu8 *
218dd648aacSDamjan Marionformat_mlx5_cqe_rx (u8 * s, va_list * args)
219dd648aacSDamjan Marion{
220dd648aacSDamjan Marion  void *cqe = va_arg (*args, void *);
221dd648aacSDamjan Marion  uword indent = format_get_indent (s);
222dd648aacSDamjan Marion  int line = 0;
223dd648aacSDamjan Marion
224dd648aacSDamjan Marion#define _(a, b, c, d) \
225dd648aacSDamjan Marion  if (mlx5_get_bits (cqe, a, b, c)) \
226dd648aacSDamjan Marion    s = format (s, "%U%U\n", \
227dd648aacSDamjan Marion		format_white_space, line++ ? indent : 0, \
228dd648aacSDamjan Marion		format_mlx5_field, cqe, a, b, c, #d);
229dd648aacSDamjan Marion  foreach_cqe_rx_field;
230dd648aacSDamjan Marion#undef _
231dd648aacSDamjan Marion  return s;
232dd648aacSDamjan Marion}
233dd648aacSDamjan Marion
234dd648aacSDamjan Marionu8 *
235dd648aacSDamjan Marionformat_rdma_rxq (u8 * s, va_list * args)
236dd648aacSDamjan Marion{
237dd648aacSDamjan Marion  rdma_device_t *rd = va_arg (*args, rdma_device_t *);
238dd648aacSDamjan Marion  u32 queue_index = va_arg (*args, u32);
239dd648aacSDamjan Marion  rdma_rxq_t *rxq = vec_elt_at_index (rd->rxqs, queue_index);
240dd648aacSDamjan Marion  u32 indent = format_get_indent (s);
241dd648aacSDamjan Marion
242dd648aacSDamjan Marion  s = format (s, "size %u head %u tail %u", rxq->size, rxq->head, rxq->tail);
243dd648aacSDamjan Marion
244dd648aacSDamjan Marion  if (rd->flags & RDMA_DEVICE_F_MLX5DV)
245dd648aacSDamjan Marion    {
246dd648aacSDamjan Marion      u32 next_cqe_index = rxq->cq_ci & (rxq->size - 1);
247dd648aacSDamjan Marion      s = format (s, "\n%Uwq: stride %u wqe-cnt %u",
248dd648aacSDamjan Marion		  format_white_space, indent + 2, rxq->wq_stride,
249dd648aacSDamjan Marion		  rxq->wqe_cnt);
250dd648aacSDamjan Marion      s = format (s, "\n%Ucq: cqn %u cqe-cnt %u ci %u",
251dd648aacSDamjan Marion		  format_white_space, indent + 2, rxq->cqn,
252dd648aacSDamjan Marion		  1 << rxq->log2_cq_size, rxq->cq_ci);
253dd648aacSDamjan Marion      s = format (s, "\n%Unext-cqe(%u):", format_white_space, indent + 4,
254dd648aacSDamjan Marion		  next_cqe_index);
255dd648aacSDamjan Marion      s = format (s, "\n%U%U", format_white_space, indent + 6,
256dd648aacSDamjan Marion		  format_mlx5_cqe_rx, rxq->cqes + next_cqe_index);
257dd648aacSDamjan Marion      s = format (s, "\n%U%U", format_white_space, indent + 6,
258dd648aacSDamjan Marion		  format_hexdump, rxq->cqes + next_cqe_index,
259dd648aacSDamjan Marion		  sizeof (mlx5dv_cqe_t));
260dd648aacSDamjan Marion    }
261dd648aacSDamjan Marion
262fe750c24SBenoît Ganne  return s;
263fe750c24SBenoît Ganne}
264fe750c24SBenoît Ganne
265fe750c24SBenoît Ganne/*
266fe750c24SBenoît Ganne * fd.io coding-style-patch-verification: ON
267fe750c24SBenoît Ganne *
268fe750c24SBenoît Ganne * Local Variables:
269fe750c24SBenoît Ganne * eval: (c-set-style "gnu")
270fe750c24SBenoît Ganne * End:
271fe750c24SBenoît Ganne */