vmxnet3: show vmxnet3 with filtering capability [VPP-1452]
[vpp.git] / src / plugins / vmxnet3 / cli.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 #include <stdint.h>
18 #include <net/if.h>
19 #include <sys/ioctl.h>
20 #include <inttypes.h>
21
22 #include <vlib/vlib.h>
23 #include <vlib/unix/unix.h>
24 #include <vlib/pci/pci.h>
25 #include <vnet/ethernet/ethernet.h>
26
27 #include <vmxnet3/vmxnet3.h>
28
29 static clib_error_t *
30 vmxnet3_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
31                            vlib_cli_command_t * cmd)
32 {
33   unformat_input_t _line_input, *line_input = &_line_input;
34   vmxnet3_create_if_args_t args;
35   u32 tmp;
36
37   /* Get a line of input. */
38   if (!unformat_user (input, unformat_line_input, line_input))
39     return 0;
40
41   memset (&args, 0, sizeof (args));
42   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
43     {
44       if (unformat (line_input, "%U", unformat_vlib_pci_addr, &args.addr))
45         ;
46       else if (unformat (line_input, "elog"))
47         args.enable_elog = 1;
48       else if (unformat (line_input, "rx-queue-size %u", &tmp))
49         args.rxq_size = tmp;
50       else if (unformat (line_input, "tx-queue-size %u", &tmp))
51         args.txq_size = tmp;
52       else
53         return clib_error_return (0, "unknown input `%U'",
54                                   format_unformat_error, input);
55     }
56   unformat_free (line_input);
57
58
59   vmxnet3_create_if (vm, &args);
60
61   return args.error;
62 }
63
64 /* *INDENT-OFF* */
65 VLIB_CLI_COMMAND (vmxnet3_create_command, static) = {
66   .path = "create interface vmxnet3",
67   .short_help = "create interface vmxnet3 <pci-address>"
68                 "[rx-queue-size <size>] [tx-queue-size <size>]",
69   .function = vmxnet3_create_command_fn,
70 };
71 /* *INDENT-ON* */
72
73 static clib_error_t *
74 vmxnet3_delete_command_fn (vlib_main_t * vm, unformat_input_t * input,
75                            vlib_cli_command_t * cmd)
76 {
77   unformat_input_t _line_input, *line_input = &_line_input;
78   u32 sw_if_index = ~0;
79   vnet_hw_interface_t *hw;
80   vmxnet3_main_t *vmxm = &vmxnet3_main;
81   vmxnet3_device_t *vd;
82   vnet_main_t *vnm = vnet_get_main ();
83
84   /* Get a line of input. */
85   if (!unformat_user (input, unformat_line_input, line_input))
86     return 0;
87
88   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
89     {
90       if (unformat (line_input, "sw_if_index %d", &sw_if_index))
91         ;
92       else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
93                          vnm, &sw_if_index))
94         ;
95       else
96         return clib_error_return (0, "unknown input `%U'",
97                                   format_unformat_error, input);
98     }
99   unformat_free (line_input);
100
101   if (sw_if_index == ~0)
102     return clib_error_return (0,
103                               "please specify interface name or sw_if_index");
104
105   hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
106   if (hw == NULL || vmxnet3_device_class.index != hw->dev_class_index)
107     return clib_error_return (0, "not a vmxnet3 interface");
108
109   vd = pool_elt_at_index (vmxm->devices, hw->dev_instance);
110
111   vmxnet3_delete_if (vm, vd);
112
113   return 0;
114 }
115
116 /* *INDENT-OFF* */
117 VLIB_CLI_COMMAND (vmxnet3_delete_command, static) = {
118   .path = "delete interface vmxnet3",
119   .short_help = "delete interface vmxnet3 "
120     "{<interface> | sw_if_index <sw_idx>}",
121   .function = vmxnet3_delete_command_fn,
122 };
123 /* *INDENT-ON* */
124
125 static clib_error_t *
126 vmxnet3_test_command_fn (vlib_main_t * vm, unformat_input_t * input,
127                          vlib_cli_command_t * cmd)
128 {
129   unformat_input_t _line_input, *line_input = &_line_input;
130   u32 sw_if_index = ~0;
131   vnet_hw_interface_t *hw;
132   vmxnet3_main_t *vmxm = &vmxnet3_main;
133   vmxnet3_device_t *vd;
134   vnet_main_t *vnm = vnet_get_main ();
135   int enable_elog = 0, disable_elog = 0;
136
137   /* Get a line of input. */
138   if (!unformat_user (input, unformat_line_input, line_input))
139     return 0;
140
141   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
142     {
143       if (unformat (line_input, "sw_if_index %d", &sw_if_index))
144         ;
145       else if (unformat (line_input, "elog-on"))
146         enable_elog = 1;
147       else if (unformat (line_input, "elog-off"))
148         disable_elog = 1;
149       else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
150                          vnm, &sw_if_index))
151         ;
152       else
153         return clib_error_return (0, "unknown input `%U'",
154                                   format_unformat_error, input);
155     }
156   unformat_free (line_input);
157
158   if (sw_if_index == ~0)
159     return clib_error_return (0,
160                               "please specify interface name or sw_if_index");
161
162   hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
163   if (hw == NULL || vmxnet3_device_class.index != hw->dev_class_index)
164     return clib_error_return (0, "not a vmxnet3 interface");
165
166   vd = pool_elt_at_index (vmxm->devices, hw->dev_instance);
167
168   if (enable_elog)
169     vd->flags |= VMXNET3_DEVICE_F_ELOG;
170
171   if (disable_elog)
172     vd->flags &= ~VMXNET3_DEVICE_F_ELOG;
173
174   return 0;
175 }
176
177 /* *INDENT-OFF* */
178 VLIB_CLI_COMMAND (vmxnet3_test_command, static) = {
179   .path = "test vmxnet3",
180   .short_help = "test vmxnet3 <interface> | sw_if_index <sw_idx> [irq] "
181     "[elog-on] [elog-off]",
182   .function = vmxnet3_test_command_fn,
183 };
184 /* *INDENT-ON* */
185
186 static void
187 show_vmxnet3 (vlib_main_t * vm, u32 * hw_if_indices, u8 show_descr,
188               u8 show_one_table, u32 which, u8 show_one_slot, u32 slot)
189 {
190   u32 i, desc_idx;
191   vmxnet3_device_t *vd;
192   vnet_main_t *vnm = &vnet_main;
193   vmxnet3_main_t *vmxm = &vmxnet3_main;
194   vnet_hw_interface_t *hi;
195   vmxnet3_rxq_t *rxq;
196   vmxnet3_rx_desc *rxd;
197   vmxnet3_rx_comp *rx_comp;
198   vmxnet3_txq_t *txq;
199   vmxnet3_tx_desc *txd;
200   vmxnet3_tx_comp *tx_comp;
201   u16 qid;
202
203   if (!hw_if_indices)
204     return;
205
206   for (i = 0; i < vec_len (hw_if_indices); i++)
207     {
208       hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
209       vd = vec_elt_at_index (vmxm->devices, hi->dev_instance);
210       vlib_cli_output (vm, "Interface: %U (ifindex %d)",
211                        format_vnet_hw_if_index_name, vnm, hw_if_indices[i],
212                        hw_if_indices[i]);
213       vlib_cli_output (vm, "  Version: %u", vd->version);
214       vlib_cli_output (vm, "  PCI Address: %U", format_vlib_pci_addr,
215                        &vd->pci_addr);
216       vlib_cli_output (vm, "  Mac Address: %U", format_ethernet_address,
217                        vd->mac_addr);
218       vlib_cli_output (vm, "  hw if index: %u", vd->hw_if_index);
219       vlib_cli_output (vm, "  Device instance: %u", vd->dev_instance);
220       vlib_cli_output (vm, "  Number of interrupts: %u", vd->num_intrs);
221
222       vec_foreach_index (qid, vd->rxqs)
223       {
224         rxq = vec_elt_at_index (vd->rxqs, qid);
225         u16 rid;
226
227         vlib_cli_output (vm, "  Queue %u (RX)", qid);
228         vlib_cli_output (vm, "    RX completion next index %u",
229                          rxq->rx_comp_ring.next);
230         vlib_cli_output (vm, "    RX completion generation flag 0x%x",
231                          rxq->rx_comp_ring.gen);
232
233         /* RX descriptors tables */
234         for (rid = 0; rid < VMXNET3_RX_RING_SIZE; rid++)
235           {
236             vmxnet3_rx_ring *ring = &rxq->rx_ring[rid];
237
238             vlib_cli_output (vm,
239                              "    ring %u size %u fill %u "
240                              "consume %u produce %u", rid,
241                              rxq->size, ring->fill, ring->consume,
242                              ring->produce);
243             if (show_descr)
244               {
245                 vlib_cli_output (vm, "RX descriptors table");
246                 vlib_cli_output (vm, "  %5s  %18s  %10s",
247                                  "slot", "address", "flags");
248                 for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
249                   {
250                     rxd = &rxq->rx_desc[rid][desc_idx];
251                     vlib_cli_output (vm, "  %5u  0x%016llx  0x%08x",
252                                      desc_idx, rxd->address, rxd->flags);
253                   }
254               }
255             else if (show_one_table)
256               {
257                 if (((which == VMXNET3_SHOW_RX_DESC0) && (rid == 0)) ||
258                     ((which == VMXNET3_SHOW_RX_DESC1) && (rid == 1)))
259                   {
260                     vlib_cli_output (vm, "RX descriptors table");
261                     vlib_cli_output (vm, "  %5s  %18s  %10s",
262                                      "slot", "address", "flags");
263                     if (show_one_slot)
264                       {
265                         rxd = &rxq->rx_desc[rid][slot];
266                         vlib_cli_output (vm, "  %5u  0x%016llx  0x%08x",
267                                          slot, rxd->address, rxd->flags);
268                       }
269                     else
270                       for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
271                         {
272                           rxd = &rxq->rx_desc[rid][desc_idx];
273                           vlib_cli_output (vm, "  %5u  0x%016llx  0x%08x",
274                                            desc_idx, rxd->address,
275                                            rxd->flags);
276                         }
277                   }
278               }
279           }
280
281         /* RX completion table */
282         if (show_descr)
283           {
284             vlib_cli_output (vm, "RX completion descriptors table");
285             vlib_cli_output (vm, "  %5s  %10s  %10s  %10s  %10s",
286                              "slot", "index", "rss", "len", "flags");
287             for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
288               {
289                 rx_comp = &rxq->rx_comp[desc_idx];
290                 vlib_cli_output (vm, "  %5u  0x%08x  %10u  %10u  0x%08x",
291                                  desc_idx, rx_comp->index, rx_comp->rss,
292                                  rx_comp->len, rx_comp->flags);
293               }
294           }
295         else if (show_one_table)
296           {
297             if (which == VMXNET3_SHOW_RX_COMP)
298               {
299                 vlib_cli_output (vm, "RX completion descriptors table");
300                 vlib_cli_output (vm, "  %5s  %10s  %10s  %10s  %10s",
301                                  "slot", "index", "rss", "len", "flags");
302                 if (show_one_slot)
303                   {
304                     rx_comp = &rxq->rx_comp[slot];
305                     vlib_cli_output (vm, "  %5u  0x%08x  %10u  %10u  0x%08x",
306                                      slot, rx_comp->index, rx_comp->rss,
307                                      rx_comp->len, rx_comp->flags);
308                   }
309                 else
310                   for (desc_idx = 0; desc_idx < rxq->size; desc_idx++)
311                     {
312                       rx_comp = &rxq->rx_comp[desc_idx];
313                       vlib_cli_output (vm,
314                                        "  %5u  0x%08x  %10u  %10u  0x%08x",
315                                        desc_idx, rx_comp->index, rx_comp->rss,
316                                        rx_comp->len, rx_comp->flags);
317                     }
318               }
319           }
320       }
321
322       vec_foreach_index (qid, vd->rxqs)
323       {
324         txq = vec_elt_at_index (vd->txqs, 0);
325         vlib_cli_output (vm, "  Queue %u (TX)", qid);
326         vlib_cli_output (vm, "    TX completion next index %u",
327                          txq->tx_comp_ring.next);
328         vlib_cli_output (vm, "    TX completion generation flag 0x%x",
329                          txq->tx_comp_ring.gen);
330         vlib_cli_output (vm, "    size %u consume %u produce %u",
331                          txq->size, txq->tx_ring.consume,
332                          txq->tx_ring.produce);
333         if (show_descr)
334           {
335             vlib_cli_output (vm, "TX descriptors table");
336             vlib_cli_output (vm, "  %5s  %18s  %10s  %10s",
337                              "slot", "address", "flags0", "flags1");
338             for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
339               {
340                 txd = &txq->tx_desc[desc_idx];
341                 vlib_cli_output (vm, "  %5u  0x%016llx  0x%08x  0x%08x",
342                                  desc_idx, txd->address, txd->flags[0],
343                                  txd->flags[1]);
344               }
345
346             vlib_cli_output (vm, "TX completion descriptors table");
347             vlib_cli_output (vm, "  %5s  %10s  %10s",
348                              "slot", "index", "flags");
349             for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
350               {
351                 tx_comp = &txq->tx_comp[desc_idx];
352                 vlib_cli_output (vm, "  %5u  0x%08x  0x%08x",
353                                  desc_idx, tx_comp->index, tx_comp->flags);
354               }
355           }
356         else if (show_one_table)
357           {
358             if (which == VMXNET3_SHOW_TX_DESC)
359               {
360                 vlib_cli_output (vm, "TX descriptors table");
361                 vlib_cli_output (vm, "  %5s  %18s  %10s  %10s",
362                                  "slot", "address", "flags0", "flags1");
363                 if (show_one_slot)
364                   {
365                     txd = &txq->tx_desc[slot];
366                     vlib_cli_output (vm, "  %5u  0x%016llx  0x%08x  0x%08x",
367                                      slot, txd->address, txd->flags[0],
368                                      txd->flags[1]);
369                   }
370                 else
371                   for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
372                     {
373                       txd = &txq->tx_desc[desc_idx];
374                       vlib_cli_output (vm, "  %5u  0x%016llx  0x%08x  0x%08x",
375                                        desc_idx, txd->address, txd->flags[0],
376                                        txd->flags[1]);
377                     }
378               }
379             else if (which == VMXNET3_SHOW_TX_COMP)
380               {
381                 vlib_cli_output (vm, "TX completion descriptors table");
382                 vlib_cli_output (vm, "  %5s  %10s  %10s",
383                                  "slot", "index", "flags");
384                 if (show_one_slot)
385                   {
386                     tx_comp = &txq->tx_comp[slot];
387                     vlib_cli_output (vm, "  %5u  0x%08x  0x%08x",
388                                      slot, tx_comp->index, tx_comp->flags);
389                   }
390                 else
391                   for (desc_idx = 0; desc_idx < txq->size; desc_idx++)
392                     {
393                       tx_comp = &txq->tx_comp[desc_idx];
394                       vlib_cli_output (vm, "  %5u  0x%08x  0x%08x",
395                                        desc_idx, tx_comp->index,
396                                        tx_comp->flags);
397                     }
398               }
399           }
400       }
401     }
402 }
403
404 static clib_error_t *
405 show_vmxnet3_fn (vlib_main_t * vm, unformat_input_t * input,
406                  vlib_cli_command_t * cmd)
407 {
408   vmxnet3_main_t *vmxm = &vmxnet3_main;
409   vnet_main_t *vnm = &vnet_main;
410   vmxnet3_device_t *vd;
411   clib_error_t *error = 0;
412   u32 hw_if_index, *hw_if_indices = 0;
413   vnet_hw_interface_t *hi = 0;
414   u8 show_descr = 0, show_one_table = 0, show_one_slot = 0;
415   u32 which = ~0, slot;
416
417   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
418     {
419       if (unformat
420           (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
421         {
422           hi = vnet_get_hw_interface (vnm, hw_if_index);
423           if (vmxnet3_device_class.index != hi->dev_class_index)
424             {
425               error = clib_error_return (0, "unknown input `%U'",
426                                          format_unformat_error, input);
427               goto done;
428             }
429           vec_add1 (hw_if_indices, hw_if_index);
430         }
431       else if (unformat (input, "desc"))
432         show_descr = 1;
433       else if (hi)
434         {
435           vmxnet3_device_t *vd =
436             vec_elt_at_index (vmxm->devices, hi->dev_instance);
437
438           if (unformat (input, "rx-comp"))
439             {
440               show_one_table = 1;
441               which = VMXNET3_SHOW_RX_COMP;
442               if (unformat (input, "%u", &slot))
443                 {
444                   vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, 0);
445
446                   if (slot >= rxq->size)
447                     {
448                       error = clib_error_return (0,
449                                                  "slot size must be < rx queue "
450                                                  "size %u", rxq->size);
451                       goto done;
452                     }
453                   show_one_slot = 1;
454                 }
455             }
456           else if (unformat (input, "rx-desc-0"))
457             {
458               show_one_table = 1;
459               which = VMXNET3_SHOW_RX_DESC0;
460               if (unformat (input, "%u", &slot))
461                 {
462                   vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, 0);
463
464                   if (slot >= rxq->size)
465                     {
466                       error = clib_error_return (0,
467                                                  "slot size must be < rx queue "
468                                                  "size %u", rxq->size);
469                       goto done;
470                     }
471                   show_one_slot = 1;
472                 }
473             }
474           else if (unformat (input, "rx-desc-1"))
475             {
476               show_one_table = 1;
477               which = VMXNET3_SHOW_RX_DESC1;
478               if (unformat (input, "%u", &slot))
479                 {
480                   vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, 0);
481
482                   if (slot >= rxq->size)
483                     {
484                       error = clib_error_return (0,
485                                                  "slot size must be < rx queue "
486                                                  "size %u", rxq->size);
487                       goto done;
488                     }
489                   show_one_slot = 1;
490                 }
491             }
492           else if (unformat (input, "tx-comp"))
493             {
494               show_one_table = 1;
495               which = VMXNET3_SHOW_TX_COMP;
496               if (unformat (input, "%u", &slot))
497                 {
498                   vmxnet3_txq_t *txq = vec_elt_at_index (vd->txqs, 0);
499
500                   if (slot >= txq->size)
501                     {
502                       error = clib_error_return (0,
503                                                  "slot size must be < tx queue "
504                                                  "size %u", txq->size);
505                       goto done;
506                     }
507                   show_one_slot = 1;
508                 }
509             }
510           else if (unformat (input, "tx-desc"))
511             {
512               show_one_table = 1;
513               which = VMXNET3_SHOW_TX_DESC;
514               if (unformat (input, "%u", &slot))
515                 {
516                   vmxnet3_txq_t *txq = vec_elt_at_index (vd->txqs, 0);
517
518                   if (slot >= txq->size)
519                     {
520                       error = clib_error_return (0,
521                                                  "slot size must be < tx queue "
522                                                  "size %u", txq->size);
523                       goto done;
524                     }
525                   show_one_slot = 1;
526                 }
527             }
528           else
529             {
530               error = clib_error_return (0, "unknown input `%U'",
531                                          format_unformat_error, input);
532               goto done;
533             }
534         }
535       else
536         {
537           error = clib_error_return (0, "unknown input `%U'",
538                                      format_unformat_error, input);
539           goto done;
540         }
541     }
542
543   if (vec_len (hw_if_indices) == 0)
544     {
545       pool_foreach (vd, vmxm->devices,
546                     vec_add1 (hw_if_indices, vd->hw_if_index);
547         );
548     }
549
550   show_vmxnet3 (vm, hw_if_indices, show_descr, show_one_table, which,
551                 show_one_slot, slot);
552
553 done:
554   vec_free (hw_if_indices);
555   return error;
556 }
557
558 /* *INDENT-OFF* */
559 VLIB_CLI_COMMAND (show_vmxnet3_command, static) = {
560   .path = "show vmxnet3",
561   .short_help = "show vmxnet3 [[<interface>] ([desc] | ([rx-comp] | "
562   "[rx-desc-0] | [rx-desc-1] | [tx-comp] | [tx-desc]) [<slot>])]",
563   .function = show_vmxnet3_fn,
564 };
565 /* *INDENT-ON* */
566
567 clib_error_t *
568 vmxnet3_cli_init (vlib_main_t * vm)
569 {
570   /* initialize binary API */
571   vmxnet3_plugin_api_hookup (vm);
572
573   return 0;
574 }
575
576 VLIB_INIT_FUNCTION (vmxnet3_cli_init);
577
578 /*
579  * fd.io coding-style-patch-verification: ON
580  *
581  * Local Variables:
582  * eval: (c-set-style "gnu")
583  * End:
584  */