rdma: add support for RSS configuration
[vpp.git] / src / plugins / rdma / format.c
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
22 u8 *
23 format_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
36 u8 *
37 format_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)) \
43 t = 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
51 u8 *
52 format_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
75 u8 *
76 format_rdma_rss4 (u8 *s, va_list *args)
77 {
78   const rdma_rss4_t *rss4 = va_arg (*args, const rdma_rss4_t *);
79   switch (*rss4)
80     {
81     case RDMA_RSS4_IP:
82       return format (s, "ipv4");
83     case RDMA_RSS4_IP_UDP:
84       return format (s, "ipv4-udp");
85     case RDMA_RSS4_AUTO: /* fallthrough */
86     case RDMA_RSS4_IP_TCP:
87       return format (s, "ipv4-tcp");
88     }
89   ASSERT (0);
90   return format (s, "unknown(%x)", *rss4);
91 }
92
93 u8 *
94 format_rdma_rss6 (u8 *s, va_list *args)
95 {
96   const rdma_rss6_t *rss6 = va_arg (*args, const rdma_rss6_t *);
97   switch (*rss6)
98     {
99     case RDMA_RSS6_IP:
100       return format (s, "ipv6");
101     case RDMA_RSS6_IP_UDP:
102       return format (s, "ipv6-udp");
103     case RDMA_RSS6_AUTO: /* fallthrough */
104     case RDMA_RSS6_IP_TCP:
105       return format (s, "ipv6-tcp");
106     }
107   ASSERT (0);
108   return format (s, "unknown(%x)", *rss6);
109 }
110
111 u8 *
112 format_rdma_device (u8 * s, va_list * args)
113 {
114   vlib_main_t *vm = vlib_get_main ();
115   u32 i = va_arg (*args, u32);
116   rdma_main_t *rm = &rdma_main;
117   rdma_device_t *rd = vec_elt_at_index (rm->devices, i);
118   vlib_pci_device_info_t *d;
119   u32 indent = format_get_indent (s);
120
121   s = format (s, "netdev %v pci-addr %U\n", rd->linux_ifname,
122               format_vlib_pci_addr, &rd->pci->addr);
123   if ((d = vlib_pci_get_device_info (vm, &rd->pci->addr, 0)))
124     {
125       s = format (s, "%Uproduct name: %s\n", format_white_space, indent,
126                   d->product_name ? (char *) d->product_name : "");
127       s = format (s, "%Upart number: %U\n", format_white_space, indent,
128                   format_vlib_pci_vpd, d->vpd_r, "PN");
129       s = format (s, "%Urevision: %U\n", format_white_space, indent,
130                   format_vlib_pci_vpd, d->vpd_r, "EC");
131       s = format (s, "%Userial number: %U\n", format_white_space, indent,
132                   format_vlib_pci_vpd, d->vpd_r, "SN");
133       vlib_pci_free_device_info (d);
134     }
135   s = format (s, "%Uflags: %U\n", format_white_space, indent,
136               format_rdma_device_flags, rd);
137   s = format (s, "%Urss: %U %U", format_white_space, indent, format_rdma_rss4,
138               &rd->rss4, format_rdma_rss6, &rd->rss6);
139   if (rd->error)
140     s = format (s, "\n%Uerror %U", format_white_space, indent,
141                 format_clib_error, rd->error);
142
143   if (rd->flags & RDMA_DEVICE_F_MLX5DV)
144     {
145       struct mlx5dv_context c = { };
146       const char *str_flags[7] = { "cqe-v1", "obsolete", "mpw-allowed",
147         "enhanced-mpw", "cqe-128b-comp", "cqe-128b-pad",
148         "packet-based-credit-mode"
149       };
150
151       if (mlx5dv_query_device (rd->ctx, &c) != 0)
152         return s;
153
154       s = format (s, "\n%Umlx5: version %u", format_white_space, indent,
155                   c.version);
156       s = format (s, "\n%Udevice flags: %U",
157                   format_white_space, indent + 2,
158                   format_rdma_bit_flag, c.flags, str_flags,
159                   ARRAY_LEN (str_flags));
160     }
161
162   return s;
163 }
164
165 u8 *
166 format_rdma_input_trace (u8 * s, va_list * args)
167 {
168   vlib_main_t *vm = va_arg (*args, vlib_main_t *);
169   vlib_node_t *node = va_arg (*args, vlib_node_t *);
170   rdma_input_trace_t *t = va_arg (*args, rdma_input_trace_t *);
171   vnet_main_t *vnm = vnet_get_main ();
172   vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, t->hw_if_index);
173   char *l4_hdr_types[8] =
174     { 0, "tcp", "udp", "tcp-empty-ack", "tcp-with-acl" };
175   char *l3_hdr_types[4] = { 0, "ip6", "ip4" };
176   u8 l3_hdr_type = CQE_FLAG_L3_HDR_TYPE (t->cqe_flags);
177   u8 l4_hdr_type = CQE_FLAG_L4_HDR_TYPE (t->cqe_flags);
178
179   s = format (s, "rdma: %v (%d) next-node %U",
180               hi->name, t->hw_if_index, format_vlib_next_node_name, vm,
181               node->index, t->next_index);
182
183   if (t->cqe_flags & CQE_FLAG_L2_OK)
184     s = format (s, " l2-ok");
185
186   if (t->cqe_flags & CQE_FLAG_L3_OK)
187     s = format (s, " l3-ok");
188
189   if (t->cqe_flags & CQE_FLAG_L4_OK)
190     s = format (s, " l4-ok");
191
192   if (t->cqe_flags & CQE_FLAG_IP_FRAG)
193     s = format (s, " ip-frag");
194
195   if (l3_hdr_type)
196     s = format (s, " %s", l3_hdr_types[l3_hdr_type]);
197
198   if (l4_hdr_type)
199     s = format (s, " %s", l4_hdr_types[l4_hdr_type]);
200
201   if ((t->cqe_flags & CQE_FLAG_IP_EXT_OPTS))
202     {
203       if (l3_hdr_type == CQE_FLAG_L3_HDR_TYPE_IP6)
204         s = format (s, " ip4-ext-hdr");
205       if (l3_hdr_type == CQE_FLAG_L3_HDR_TYPE_IP4)
206         s = format (s, " ip4-opt");
207     }
208
209   return s;
210 }
211
212 static u8 *
213 format_mlx5_bits (u8 * s, va_list * args)
214 {
215   void *ptr = va_arg (*args, void *);
216   u32 offset = va_arg (*args, u32);
217   u32 sb = va_arg (*args, u32);
218   u32 eb = va_arg (*args, u32);
219
220   if (sb == 63 && eb == 0)
221     {
222       u64 x = mlx5_get_u64 (ptr, offset);
223       return format (s, "0x%lx", x);
224     }
225
226   u32 x = mlx5_get_bits (ptr, offset, sb, eb);
227   s = format (s, "%d", x);
228   if (x > 9)
229     s = format (s, " (0x%x)", x);
230   return s;
231 }
232
233 static u8 *
234 format_mlx5_field (u8 * s, va_list * args)
235 {
236   void *ptr = va_arg (*args, void *);
237   u32 offset = va_arg (*args, u32);
238   u32 sb = va_arg (*args, u32);
239   u32 eb = va_arg (*args, u32);
240   char *name = va_arg (*args, char *);
241
242   u8 *tmp = 0;
243
244   tmp = format (0, "0x%02x %s ", offset, name);
245   if (sb == eb)
246     tmp = format (tmp, "[%u]", sb);
247   else
248     tmp = format (tmp, "[%u:%u]", sb, eb);
249   s = format (s, "%-45v = %U", tmp, format_mlx5_bits, ptr, offset, sb, eb);
250   vec_free (tmp);
251
252   return s;
253 }
254
255 u8 *
256 format_mlx5_cqe_rx (u8 * s, va_list * args)
257 {
258   void *cqe = va_arg (*args, void *);
259   uword indent = format_get_indent (s);
260   int line = 0;
261
262 #define _(a, b, c, d) \
263   if (mlx5_get_bits (cqe, a, b, c)) \
264     s = format (s, "%U%U\n", \
265                 format_white_space, line++ ? indent : 0, \
266                 format_mlx5_field, cqe, a, b, c, #d);
267   foreach_cqe_rx_field;
268 #undef _
269   return s;
270 }
271
272 u8 *
273 format_rdma_rxq (u8 * s, va_list * args)
274 {
275   rdma_device_t *rd = va_arg (*args, rdma_device_t *);
276   u32 queue_index = va_arg (*args, u32);
277   rdma_rxq_t *rxq = vec_elt_at_index (rd->rxqs, queue_index);
278   u32 indent = format_get_indent (s);
279
280   s = format (s, "size %u head %u tail %u", rxq->size, rxq->head, rxq->tail);
281
282   if (rd->flags & RDMA_DEVICE_F_MLX5DV)
283     {
284       u32 next_cqe_index = rxq->cq_ci & (rxq->size - 1);
285       s = format (s, "\n%Uwq: stride %u wqe-cnt %u",
286                   format_white_space, indent + 2, rxq->wq_stride,
287                   rxq->wqe_cnt);
288       s = format (s, "\n%Ucq: cqn %u cqe-cnt %u ci %u",
289                   format_white_space, indent + 2, rxq->cqn,
290                   1 << rxq->log2_cq_size, rxq->cq_ci);
291       s = format (s, "\n%Unext-cqe(%u):", format_white_space, indent + 4,
292                   next_cqe_index);
293       s = format (s, "\n%U%U", format_white_space, indent + 6,
294                   format_mlx5_cqe_rx, rxq->cqes + next_cqe_index);
295       s = format (s, "\n%U%U", format_white_space, indent + 6,
296                   format_hexdump, rxq->cqes + next_cqe_index,
297                   sizeof (mlx5dv_cqe_t));
298     }
299
300   return s;
301 }
302
303 /*
304  * fd.io coding-style-patch-verification: ON
305  *
306  * Local Variables:
307  * eval: (c-set-style "gnu")
308  * End:
309  */