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