classify: add bpf support to pcap classifier
[vpp.git] / src / vnet / interface_test.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2021 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 <vat/vat.h>
19 #include <vlibapi/api.h>
20 #include <vlibmemory/api.h>
21 #include <vppinfra/error.h>
22 #include <vpp/api/types.h>
23
24 #include <vnet/ip/ip_types_api.h>
25
26 #define __plugin_msg_base interface_test_main.msg_id_base
27 #include <vlibapi/vat_helper_macros.h>
28
29 /* Declare message IDs */
30 #include <vnet/format_fns.h>
31 #include <vnet/interface.api_enum.h>
32 #include <vnet/interface.api_types.h>
33 #include <vlibmemory/vlib.api_types.h>
34 #include <vlibmemory/memclnt.api_enum.h>
35
36 #define vl_endianfun /* define message structures */
37 #include <vnet/interface.api.h>
38 #undef vl_endianfun
39
40 typedef struct
41 {
42   /* API message ID base */
43   u16 msg_id_base;
44   vat_main_t *vat_main;
45 } interface_test_main_t;
46
47 static interface_test_main_t interface_test_main;
48
49 static int
50 api_sw_interface_set_flags (vat_main_t *vam)
51 {
52   unformat_input_t *i = vam->input;
53   vl_api_sw_interface_set_flags_t *mp;
54   u32 sw_if_index;
55   u8 sw_if_index_set = 0;
56   u8 admin_up = 0;
57   int ret;
58
59   /* Parse args required to build the message */
60   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
61     {
62       if (unformat (i, "admin-up"))
63         admin_up = 1;
64       else if (unformat (i, "admin-down"))
65         admin_up = 0;
66       else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
67         sw_if_index_set = 1;
68       else if (unformat (i, "sw_if_index %d", &sw_if_index))
69         sw_if_index_set = 1;
70       else
71         break;
72     }
73
74   if (sw_if_index_set == 0)
75     {
76       errmsg ("missing interface name or sw_if_index");
77       return -99;
78     }
79
80   /* Construct the API message */
81   M (SW_INTERFACE_SET_FLAGS, mp);
82   mp->sw_if_index = ntohl (sw_if_index);
83   mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
84
85   /* send it... */
86   S (mp);
87
88   /* Wait for a reply, return the good/bad news... */
89   W (ret);
90   return ret;
91 }
92
93 static int
94 api_hw_interface_set_mtu (vat_main_t *vam)
95 {
96   unformat_input_t *i = vam->input;
97   vl_api_hw_interface_set_mtu_t *mp;
98   u32 sw_if_index = ~0;
99   u32 mtu = 0;
100   int ret;
101
102   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
103     {
104       if (unformat (i, "mtu %d", &mtu))
105         ;
106       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
107         ;
108       else if (unformat (i, "sw_if_index %d", &sw_if_index))
109         ;
110       else
111         break;
112     }
113
114   if (sw_if_index == ~0)
115     {
116       errmsg ("missing interface name or sw_if_index");
117       return -99;
118     }
119
120   if (mtu == 0)
121     {
122       errmsg ("no mtu specified");
123       return -99;
124     }
125
126   /* Construct the API message */
127   M (HW_INTERFACE_SET_MTU, mp);
128   mp->sw_if_index = ntohl (sw_if_index);
129   mp->mtu = ntohs ((u16) mtu);
130
131   S (mp);
132   W (ret);
133   return ret;
134 }
135
136 static int
137 api_sw_interface_tag_add_del (vat_main_t *vam)
138 {
139   unformat_input_t *i = vam->input;
140   vl_api_sw_interface_tag_add_del_t *mp;
141   u32 sw_if_index = ~0;
142   u8 *tag = 0;
143   u8 enable = 1;
144   int ret;
145
146   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
147     {
148       if (unformat (i, "tag %s", &tag))
149         ;
150       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
151         ;
152       else if (unformat (i, "sw_if_index %d", &sw_if_index))
153         ;
154       else if (unformat (i, "del"))
155         enable = 0;
156       else
157         break;
158     }
159
160   if (sw_if_index == ~0)
161     {
162       errmsg ("missing interface name or sw_if_index");
163       return -99;
164     }
165
166   if (enable && (tag == 0))
167     {
168       errmsg ("no tag specified");
169       return -99;
170     }
171
172   /* Construct the API message */
173   M (SW_INTERFACE_TAG_ADD_DEL, mp);
174   mp->sw_if_index = ntohl (sw_if_index);
175   mp->is_add = enable;
176   if (enable)
177     strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
178   vec_free (tag);
179
180   S (mp);
181   W (ret);
182   return ret;
183 }
184
185 static int
186 api_sw_interface_add_del_mac_address (vat_main_t *vam)
187 {
188   unformat_input_t *i = vam->input;
189   vl_api_mac_address_t mac = { 0 };
190   vl_api_sw_interface_add_del_mac_address_t *mp;
191   u32 sw_if_index = ~0;
192   u8 is_add = 1;
193   u8 mac_set = 0;
194   int ret;
195
196   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
197     {
198       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
199         ;
200       else if (unformat (i, "sw_if_index %d", &sw_if_index))
201         ;
202       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
203         mac_set++;
204       else if (unformat (i, "del"))
205         is_add = 0;
206       else
207         break;
208     }
209
210   if (sw_if_index == ~0)
211     {
212       errmsg ("missing interface name or sw_if_index");
213       return -99;
214     }
215
216   if (!mac_set)
217     {
218       errmsg ("missing MAC address");
219       return -99;
220     }
221
222   /* Construct the API message */
223   M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
224   mp->sw_if_index = ntohl (sw_if_index);
225   mp->is_add = is_add;
226   clib_memcpy (&mp->addr, &mac, sizeof (mac));
227
228   S (mp);
229   W (ret);
230   return ret;
231 }
232
233 static void
234 vl_api_sw_interface_details_t_handler (vl_api_sw_interface_details_t *mp)
235 {
236   vat_main_t *vam = &vat_main;
237   u8 *s = format (0, "%s%c", mp->interface_name, 0);
238
239   hash_set_mem (vam->sw_if_index_by_interface_name, s,
240                 ntohl (mp->sw_if_index));
241
242   /* In sub interface case, fill the sub interface table entry */
243   if (mp->sw_if_index != mp->sup_sw_if_index)
244     {
245       sw_interface_subif_t *sub = NULL;
246
247       vec_add2 (vam->sw_if_subif_table, sub, 1);
248
249       vec_validate (sub->interface_name, strlen ((char *) s) + 1);
250       strncpy ((char *) sub->interface_name, (char *) s,
251                vec_len (sub->interface_name));
252       sub->sw_if_index = ntohl (mp->sw_if_index);
253       sub->sub_id = ntohl (mp->sub_id);
254
255       sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
256
257       sub->sub_number_of_tags = mp->sub_number_of_tags;
258       sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
259       sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
260
261       /* vlan tag rewrite */
262       sub->vtr_op = ntohl (mp->vtr_op);
263       sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
264       sub->vtr_tag1 = ntohl (mp->vtr_tag1);
265       sub->vtr_tag2 = ntohl (mp->vtr_tag2);
266     }
267 }
268
269 static int
270 api_sw_interface_get_mac_address (vat_main_t *vat)
271 {
272   return -1;
273 }
274
275 static void
276 vl_api_sw_interface_get_mac_address_reply_t_handler (
277   vl_api_sw_interface_get_mac_address_reply_t *mp)
278 {
279 }
280
281 static int
282 api_sw_interface_add_del_address (vat_main_t *vam)
283 {
284   unformat_input_t *i = vam->input;
285   vl_api_sw_interface_add_del_address_t *mp;
286   u32 sw_if_index;
287   u8 sw_if_index_set = 0;
288   u8 is_add = 1, del_all = 0;
289   u32 address_length = 0;
290   u8 v4_address_set = 0;
291   u8 v6_address_set = 0;
292   ip4_address_t v4address;
293   ip6_address_t v6address;
294   int ret;
295
296   /* Parse args required to build the message */
297   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
298     {
299       if (unformat (i, "del-all"))
300         del_all = 1;
301       else if (unformat (i, "del"))
302         is_add = 0;
303       else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
304         sw_if_index_set = 1;
305       else if (unformat (i, "sw_if_index %d", &sw_if_index))
306         sw_if_index_set = 1;
307       else if (unformat (i, "%U/%d", unformat_ip4_address, &v4address,
308                          &address_length))
309         v4_address_set = 1;
310       else if (unformat (i, "%U/%d", unformat_ip6_address, &v6address,
311                          &address_length))
312         v6_address_set = 1;
313       else
314         break;
315     }
316
317   if (sw_if_index_set == 0)
318     {
319       errmsg ("missing interface name or sw_if_index");
320       return -99;
321     }
322   if (v4_address_set && v6_address_set)
323     {
324       errmsg ("both v4 and v6 addresses set");
325       return -99;
326     }
327   if (!v4_address_set && !v6_address_set && !del_all)
328     {
329       errmsg ("no addresses set");
330       return -99;
331     }
332
333   /* Construct the API message */
334   M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
335
336   mp->sw_if_index = ntohl (sw_if_index);
337   mp->is_add = is_add;
338   mp->del_all = del_all;
339   if (v6_address_set)
340     {
341       mp->prefix.address.af = ADDRESS_IP6;
342       clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
343     }
344   else
345     {
346       mp->prefix.address.af = ADDRESS_IP4;
347       clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
348     }
349   mp->prefix.len = address_length;
350
351   /* send it... */
352   S (mp);
353
354   /* Wait for a reply, return good/bad news  */
355   W (ret);
356   return ret;
357 }
358
359 static int
360 api_sw_interface_get_table (vat_main_t *vam)
361 {
362   unformat_input_t *i = vam->input;
363   vl_api_sw_interface_get_table_t *mp;
364   u32 sw_if_index;
365   u8 sw_if_index_set = 0;
366   u8 is_ipv6 = 0;
367   int ret;
368
369   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
370     {
371       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
372         sw_if_index_set = 1;
373       else if (unformat (i, "sw_if_index %d", &sw_if_index))
374         sw_if_index_set = 1;
375       else if (unformat (i, "ipv6"))
376         is_ipv6 = 1;
377       else
378         break;
379     }
380
381   if (sw_if_index_set == 0)
382     {
383       errmsg ("missing interface name or sw_if_index");
384       return -99;
385     }
386
387   M (SW_INTERFACE_GET_TABLE, mp);
388   mp->sw_if_index = htonl (sw_if_index);
389   mp->is_ipv6 = is_ipv6;
390
391   S (mp);
392   W (ret);
393   return ret;
394 }
395
396 static int
397 api_sw_interface_set_rx_mode (vat_main_t *vam)
398 {
399   unformat_input_t *i = vam->input;
400   vl_api_sw_interface_set_rx_mode_t *mp;
401   u32 sw_if_index;
402   u8 sw_if_index_set = 0;
403   int ret;
404   u8 queue_id_valid = 0;
405   u32 queue_id;
406   vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
407
408   /* Parse args required to build the message */
409   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
410     {
411       if (unformat (i, "queue %d", &queue_id))
412         queue_id_valid = 1;
413       else if (unformat (i, "polling"))
414         mode = VNET_HW_IF_RX_MODE_POLLING;
415       else if (unformat (i, "interrupt"))
416         mode = VNET_HW_IF_RX_MODE_INTERRUPT;
417       else if (unformat (i, "adaptive"))
418         mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
419       else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
420         sw_if_index_set = 1;
421       else if (unformat (i, "sw_if_index %d", &sw_if_index))
422         sw_if_index_set = 1;
423       else
424         break;
425     }
426
427   if (sw_if_index_set == 0)
428     {
429       errmsg ("missing interface name or sw_if_index");
430       return -99;
431     }
432   if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
433     {
434       errmsg ("missing rx-mode");
435       return -99;
436     }
437
438   /* Construct the API message */
439   M (SW_INTERFACE_SET_RX_MODE, mp);
440   mp->sw_if_index = ntohl (sw_if_index);
441   mp->mode = (vl_api_rx_mode_t) mode;
442   mp->queue_id_valid = queue_id_valid;
443   mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0;
444
445   /* send it... */
446   S (mp);
447
448   /* Wait for a reply, return the good/bad news... */
449   W (ret);
450   return ret;
451 }
452
453 static int
454 api_sw_interface_set_unnumbered (vat_main_t *vam)
455 {
456   unformat_input_t *i = vam->input;
457   vl_api_sw_interface_set_unnumbered_t *mp;
458   u32 sw_if_index;
459   u32 unnum_sw_index = ~0;
460   u8 is_add = 1;
461   u8 sw_if_index_set = 0;
462   int ret;
463
464   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
465     {
466       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
467         sw_if_index_set = 1;
468       else if (unformat (i, "sw_if_index %d", &sw_if_index))
469         sw_if_index_set = 1;
470       else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
471         ;
472       else if (unformat (i, "del"))
473         is_add = 0;
474       else
475         {
476           clib_warning ("parse error '%U'", format_unformat_error, i);
477           return -99;
478         }
479     }
480
481   if (sw_if_index_set == 0)
482     {
483       errmsg ("missing interface name or sw_if_index");
484       return -99;
485     }
486
487   M (SW_INTERFACE_SET_UNNUMBERED, mp);
488
489   mp->sw_if_index = ntohl (sw_if_index);
490   mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
491   mp->is_add = is_add;
492
493   S (mp);
494   W (ret);
495   return ret;
496 }
497
498 static void
499 vl_api_sw_interface_get_table_reply_t_handler (
500   vl_api_sw_interface_get_table_reply_t *mp)
501 {
502   vat_main_t *vam = interface_test_main.vat_main;
503
504   fformat (vam->ofp, "%d", ntohl (mp->vrf_id));
505
506   vam->retval = ntohl (mp->retval);
507   vam->result_ready = 1;
508 }
509
510 static int
511 api_sw_interface_address_replace_begin (vat_main_t *vam)
512 {
513   return -1;
514 }
515
516 static int
517 api_sw_interface_set_mac_address (vat_main_t *vam)
518 {
519   return -1;
520 }
521
522 static int
523 api_sw_interface_set_rx_placement (vat_main_t *vam)
524 {
525   unformat_input_t *i = vam->input;
526   vl_api_sw_interface_set_rx_placement_t *mp;
527   u32 sw_if_index;
528   u8 sw_if_index_set = 0;
529   int ret;
530   u8 is_main = 0;
531   u32 queue_id, thread_index;
532
533   /* Parse args required to build the message */
534   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
535     {
536       if (unformat (i, "queue %d", &queue_id))
537         ;
538       else if (unformat (i, "main"))
539         is_main = 1;
540       else if (unformat (i, "worker %d", &thread_index))
541         ;
542       else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
543         sw_if_index_set = 1;
544       else if (unformat (i, "sw_if_index %d", &sw_if_index))
545         sw_if_index_set = 1;
546       else
547         break;
548     }
549
550   if (sw_if_index_set == 0)
551     {
552       errmsg ("missing interface name or sw_if_index");
553       return -99;
554     }
555
556   if (is_main)
557     thread_index = 0;
558   /* Construct the API message */
559   M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
560   mp->sw_if_index = ntohl (sw_if_index);
561   mp->worker_id = ntohl (thread_index);
562   mp->queue_id = ntohl (queue_id);
563   mp->is_main = is_main;
564
565   /* send it... */
566   S (mp);
567   /* Wait for a reply, return the good/bad news... */
568   W (ret);
569   return ret;
570 }
571
572 static int
573 api_sw_interface_set_tx_placement (vat_main_t *vam)
574 {
575   unformat_input_t *i = vam->input;
576   vl_api_sw_interface_set_tx_placement_t *mp;
577   u32 sw_if_index;
578   u8 sw_if_index_set = 0;
579   int ret;
580   uword *bitmap = 0;
581   u32 queue_id, n_bits = 0;
582   u32 v;
583
584   /* Parse args required to build the message */
585   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
586     {
587       if (unformat (i, "queue %d", &queue_id))
588         ;
589       else if (unformat (i, "threads %U", unformat_bitmap_list, &bitmap))
590         ;
591       else if (unformat (i, "mask %U", unformat_bitmap_mask, &bitmap))
592         ;
593       else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
594         sw_if_index_set = 1;
595       else if (unformat (i, "sw_if_index %d", &sw_if_index))
596         sw_if_index_set = 1;
597       else
598         break;
599     }
600
601   if (sw_if_index_set == 0)
602     {
603       errmsg ("missing interface name or sw_if_index");
604       return -99;
605     }
606
607   n_bits = clib_bitmap_count_set_bits (bitmap);
608   /* Construct the API message */
609   M2 (SW_INTERFACE_SET_TX_PLACEMENT, mp, sizeof (u32) * n_bits);
610   mp->sw_if_index = htonl (sw_if_index);
611   mp->queue_id = htonl (queue_id);
612   mp->array_size = htonl (n_bits);
613
614   v = clib_bitmap_first_set (bitmap);
615   for (u32 j = 0; j < n_bits; j++)
616     {
617       mp->threads[j] = htonl (v);
618       v = clib_bitmap_next_set (bitmap, v + 1);
619     }
620
621   /* send it... */
622   S (mp);
623   /* Wait for a reply, return the good/bad news... */
624   W (ret);
625   clib_bitmap_free (bitmap);
626   return ret;
627 }
628
629 static int
630 api_interface_name_renumber (vat_main_t *vam)
631 {
632   unformat_input_t *line_input = vam->input;
633   vl_api_interface_name_renumber_t *mp;
634   u32 sw_if_index = ~0;
635   u32 new_show_dev_instance = ~0;
636   int ret;
637
638   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
639     {
640       if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
641                     &sw_if_index))
642         ;
643       else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
644         ;
645       else if (unformat (line_input, "new_show_dev_instance %d",
646                          &new_show_dev_instance))
647         ;
648       else
649         break;
650     }
651
652   if (sw_if_index == ~0)
653     {
654       errmsg ("missing interface name or sw_if_index");
655       return -99;
656     }
657
658   if (new_show_dev_instance == ~0)
659     {
660       errmsg ("missing new_show_dev_instance");
661       return -99;
662     }
663
664   M (INTERFACE_NAME_RENUMBER, mp);
665
666   mp->sw_if_index = ntohl (sw_if_index);
667   mp->new_show_dev_instance = ntohl (new_show_dev_instance);
668
669   S (mp);
670   W (ret);
671   return ret;
672 }
673
674 static int
675 api_delete_subif (vat_main_t *vam)
676 {
677   unformat_input_t *i = vam->input;
678   vl_api_delete_subif_t *mp;
679   u32 sw_if_index = ~0;
680   int ret;
681
682   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
683     {
684       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
685         ;
686       if (unformat (i, "sw_if_index %d", &sw_if_index))
687         ;
688       else
689         break;
690     }
691
692   if (sw_if_index == ~0)
693     {
694       errmsg ("missing sw_if_index");
695       return -99;
696     }
697
698   /* Construct the API message */
699   M (DELETE_SUBIF, mp);
700   mp->sw_if_index = ntohl (sw_if_index);
701
702   S (mp);
703   W (ret);
704   return ret;
705 }
706
707 static int
708 api_delete_loopback (vat_main_t *vam)
709 {
710   unformat_input_t *i = vam->input;
711   vl_api_delete_loopback_t *mp;
712   u32 sw_if_index = ~0;
713   int ret;
714
715   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
716     {
717       if (unformat (i, "sw_if_index %d", &sw_if_index))
718         ;
719       else
720         break;
721     }
722
723   if (sw_if_index == ~0)
724     {
725       errmsg ("missing sw_if_index");
726       return -99;
727     }
728
729   /* Construct the API message */
730   M (DELETE_LOOPBACK, mp);
731   mp->sw_if_index = ntohl (sw_if_index);
732
733   S (mp);
734   W (ret);
735   return ret;
736 }
737
738 static int
739 api_create_loopback_instance (vat_main_t *vat)
740 {
741   return -1;
742 }
743
744 static int
745 api_create_loopback (vat_main_t *vam)
746 {
747   unformat_input_t *i = vam->input;
748   vl_api_create_loopback_t *mp;
749   vl_api_create_loopback_instance_t *mp_lbi;
750   u8 mac_address[6];
751   u8 mac_set = 0;
752   u8 is_specified = 0;
753   u32 user_instance = 0;
754   int ret;
755
756   clib_memset (mac_address, 0, sizeof (mac_address));
757
758   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
759     {
760       if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
761         mac_set = 1;
762       if (unformat (i, "instance %d", &user_instance))
763         is_specified = 1;
764       else
765         break;
766     }
767
768   if (is_specified)
769     {
770       M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
771       mp_lbi->is_specified = is_specified;
772       if (is_specified)
773         mp_lbi->user_instance = htonl (user_instance);
774       if (mac_set)
775         clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
776       S (mp_lbi);
777     }
778   else
779     {
780       /* Construct the API message */
781       M (CREATE_LOOPBACK, mp);
782       if (mac_set)
783         clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
784       S (mp);
785     }
786
787   W (ret);
788   return ret;
789 }
790
791 static void
792 vl_api_create_subif_reply_t_handler (vl_api_create_subif_reply_t *mp)
793 {
794   vat_main_t *vam = interface_test_main.vat_main;
795   vam->result_ready = 1;
796 }
797
798 #define foreach_create_subif_bit                                              \
799   _ (no_tags)                                                                 \
800   _ (one_tag)                                                                 \
801   _ (two_tags)                                                                \
802   _ (dot1ad)                                                                  \
803   _ (exact_match)                                                             \
804   _ (default_sub)                                                             \
805   _ (outer_vlan_id_any)                                                       \
806   _ (inner_vlan_id_any)
807
808 #define foreach_create_subif_flag                                             \
809   _ (0, "no_tags")                                                            \
810   _ (1, "one_tag")                                                            \
811   _ (2, "two_tags")                                                           \
812   _ (3, "dot1ad")                                                             \
813   _ (4, "exact_match")                                                        \
814   _ (5, "default_sub")                                                        \
815   _ (6, "outer_vlan_id_any")                                                  \
816   _ (7, "inner_vlan_id_any")
817
818 static int
819 api_create_subif (vat_main_t *vam)
820 {
821   unformat_input_t *i = vam->input;
822   vl_api_create_subif_t *mp;
823   u32 sw_if_index;
824   u8 sw_if_index_set = 0;
825   u32 sub_id;
826   u8 sub_id_set = 0;
827   u32 __attribute__ ((unused)) no_tags = 0;
828   u32 __attribute__ ((unused)) one_tag = 0;
829   u32 __attribute__ ((unused)) two_tags = 0;
830   u32 __attribute__ ((unused)) dot1ad = 0;
831   u32 __attribute__ ((unused)) exact_match = 0;
832   u32 __attribute__ ((unused)) default_sub = 0;
833   u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
834   u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
835   u32 tmp;
836   u16 outer_vlan_id = 0;
837   u16 inner_vlan_id = 0;
838   int ret;
839
840   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
841     {
842       if (unformat (i, "sw_if_index %d", &sw_if_index))
843         sw_if_index_set = 1;
844       else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
845         sw_if_index_set = 1;
846       else if (unformat (i, "sub_id %d", &sub_id))
847         sub_id_set = 1;
848       else if (unformat (i, "outer_vlan_id %d", &tmp))
849         outer_vlan_id = tmp;
850       else if (unformat (i, "inner_vlan_id %d", &tmp))
851         inner_vlan_id = tmp;
852
853 #define _(a) else if (unformat (i, #a)) a = 1;
854       foreach_create_subif_bit
855 #undef _
856         else
857       {
858         clib_warning ("parse error '%U'", format_unformat_error, i);
859         return -99;
860       }
861     }
862
863   if (sw_if_index_set == 0)
864     {
865       errmsg ("missing interface name or sw_if_index");
866       return -99;
867     }
868
869   if (sub_id_set == 0)
870     {
871       errmsg ("missing sub_id");
872       return -99;
873     }
874   M (CREATE_SUBIF, mp);
875
876   mp->sw_if_index = ntohl (sw_if_index);
877   mp->sub_id = ntohl (sub_id);
878
879 #define _(a, b) mp->sub_if_flags |= (1 << a);
880   foreach_create_subif_flag;
881 #undef _
882
883   mp->outer_vlan_id = ntohs (outer_vlan_id);
884   mp->inner_vlan_id = ntohs (inner_vlan_id);
885
886   S (mp);
887   W (ret);
888   return ret;
889 }
890
891 static void
892 vl_api_sw_interface_rx_placement_details_t_handler (
893   vl_api_sw_interface_rx_placement_details_t *mp)
894 {
895   vat_main_t *vam = interface_test_main.vat_main;
896   u32 worker_id = ntohl (mp->worker_id);
897
898   print (vam->ofp, "\n%-11d %-11s %-6d %-5d %-9s", ntohl (mp->sw_if_index),
899          (worker_id == 0) ? "main" : "worker", worker_id, ntohl (mp->queue_id),
900          (mp->mode == 1) ? "polling" :
901                            ((mp->mode == 2) ? "interrupt" : "adaptive"));
902 }
903
904 static __clib_unused void
905 vl_api_sw_interface_tx_placement_details_t_handler (
906   vl_api_sw_interface_tx_placement_details_t *mp)
907 {
908   vat_main_t *vam = interface_test_main.vat_main;
909   u32 size = ntohl (mp->array_size);
910   uword *bitmap = 0;
911
912   for (u32 i = 0; i < size; i++)
913     {
914       u32 thread_index = ntohl (mp->threads[i]);
915       bitmap = clib_bitmap_set (bitmap, thread_index, 1);
916     }
917
918   print (vam->ofp, "\n%-11d %-6d %-7s %U", ntohl (mp->sw_if_index),
919          ntohl (mp->queue_id), (mp->shared == 1) ? "yes" : "no",
920          format_bitmap_list, bitmap);
921 }
922
923 static void
924 vl_api_create_vlan_subif_reply_t_handler (vl_api_create_vlan_subif_reply_t *mp)
925 {
926   vat_main_t *vam = interface_test_main.vat_main;
927   vam->result_ready = 1;
928 }
929
930 static void
931 vl_api_create_loopback_reply_t_handler (vl_api_create_loopback_reply_t *mp)
932 {
933   vat_main_t *vam = interface_test_main.vat_main;
934   vam->result_ready = 1;
935 }
936
937 static void
938 vl_api_create_loopback_instance_reply_t_handler (
939   vl_api_create_loopback_instance_reply_t *mp)
940 {
941   vat_main_t *vam = interface_test_main.vat_main;
942   vam->result_ready = 1;
943 }
944
945 static int
946 api_create_vlan_subif (vat_main_t *vam)
947 {
948   unformat_input_t *i = vam->input;
949   vl_api_create_vlan_subif_t *mp;
950   u32 sw_if_index;
951   u8 sw_if_index_set = 0;
952   u32 vlan_id;
953   u8 vlan_id_set = 0;
954   int ret;
955
956   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
957     {
958       if (unformat (i, "sw_if_index %d", &sw_if_index))
959         sw_if_index_set = 1;
960       else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
961         sw_if_index_set = 1;
962       else if (unformat (i, "vlan %d", &vlan_id))
963         vlan_id_set = 1;
964       else
965         {
966           clib_warning ("parse error '%U'", format_unformat_error, i);
967           return -99;
968         }
969     }
970
971   if (sw_if_index_set == 0)
972     {
973       errmsg ("missing interface name or sw_if_index");
974       return -99;
975     }
976
977   if (vlan_id_set == 0)
978     {
979       errmsg ("missing vlan_id");
980       return -99;
981     }
982   M (CREATE_VLAN_SUBIF, mp);
983
984   mp->sw_if_index = ntohl (sw_if_index);
985   mp->vlan_id = ntohl (vlan_id);
986
987   S (mp);
988   W (ret);
989   return ret;
990 }
991
992 static int
993 api_collect_detailed_interface_stats (vat_main_t *vam)
994 {
995   return -1;
996 }
997
998 static int
999 api_sw_interface_rx_placement_dump (vat_main_t *vam)
1000 {
1001   unformat_input_t *i = vam->input;
1002   vl_api_sw_interface_rx_placement_dump_t *mp;
1003   vl_api_control_ping_t *mp_ping;
1004   int ret;
1005   u32 sw_if_index;
1006   u8 sw_if_index_set = 0;
1007
1008   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1009     {
1010       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1011         sw_if_index_set++;
1012       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1013         sw_if_index_set++;
1014       else
1015         break;
1016     }
1017
1018   fformat (vam->ofp, "\n%-11s %-11s %-6s %-5s %-4s", "sw_if_index",
1019            "main/worker", "thread", "queue", "mode");
1020
1021   /* Dump Interface rx placement */
1022   M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
1023
1024   if (sw_if_index_set)
1025     mp->sw_if_index = htonl (sw_if_index);
1026   else
1027     mp->sw_if_index = ~0;
1028
1029   S (mp);
1030
1031   /* Use a control ping for synchronization */
1032   PING (&interface_test_main, mp_ping);
1033   S (mp_ping);
1034
1035   W (ret);
1036   return ret;
1037 }
1038
1039 static int
1040 api_sw_interface_tx_placement_get (vat_main_t *vam)
1041 {
1042   unformat_input_t *i = vam->input;
1043   vl_api_sw_interface_tx_placement_get_t *mp;
1044   vl_api_control_ping_t *mp_ping;
1045   int ret;
1046   u32 sw_if_index;
1047   u8 sw_if_index_set = 0;
1048
1049   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1050     {
1051       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1052         sw_if_index_set++;
1053       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1054         sw_if_index_set++;
1055       else
1056         break;
1057     }
1058
1059   fformat (vam->ofp, "\n%-11s %-6s %-7s %-11s", "sw_if_index", "queue",
1060            "shared", "threads");
1061
1062   /* Dump Interface tx placement */
1063   M (SW_INTERFACE_TX_PLACEMENT_GET, mp);
1064
1065   if (sw_if_index_set)
1066     mp->sw_if_index = htonl (sw_if_index);
1067   else
1068     mp->sw_if_index = ~0;
1069
1070   S (mp);
1071
1072   /* Use a control ping for synchronization */
1073   PING (&interface_test_main, mp_ping);
1074   S (mp_ping);
1075
1076   W (ret);
1077   return ret;
1078 }
1079
1080 static void
1081 vl_api_sw_interface_tx_placement_get_reply_t_handler ()
1082 {
1083 }
1084
1085 static int
1086 api_sw_interface_clear_stats (vat_main_t *vam)
1087 {
1088   unformat_input_t *i = vam->input;
1089   vl_api_sw_interface_clear_stats_t *mp;
1090   u32 sw_if_index;
1091   u8 sw_if_index_set = 0;
1092   int ret;
1093
1094   /* Parse args required to build the message */
1095   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1096     {
1097       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1098         sw_if_index_set = 1;
1099       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1100         sw_if_index_set = 1;
1101       else
1102         break;
1103     }
1104
1105   /* Construct the API message */
1106   M (SW_INTERFACE_CLEAR_STATS, mp);
1107
1108   if (sw_if_index_set == 1)
1109     mp->sw_if_index = ntohl (sw_if_index);
1110   else
1111     mp->sw_if_index = ~0;
1112
1113   /* send it... */
1114   S (mp);
1115
1116   /* Wait for a reply, return the good/bad news... */
1117   W (ret);
1118   return ret;
1119 }
1120
1121 static int
1122 api_sw_interface_set_table (vat_main_t *vam)
1123 {
1124   unformat_input_t *i = vam->input;
1125   vl_api_sw_interface_set_table_t *mp;
1126   u32 sw_if_index, vrf_id = 0;
1127   u8 sw_if_index_set = 0;
1128   u8 is_ipv6 = 0;
1129   int ret;
1130
1131   /* Parse args required to build the message */
1132   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1133     {
1134       if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1135         sw_if_index_set = 1;
1136       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1137         sw_if_index_set = 1;
1138       else if (unformat (i, "vrf %d", &vrf_id))
1139         ;
1140       else if (unformat (i, "ipv6"))
1141         is_ipv6 = 1;
1142       else
1143         break;
1144     }
1145
1146   if (sw_if_index_set == 0)
1147     {
1148       errmsg ("missing interface name or sw_if_index");
1149       return -99;
1150     }
1151
1152   /* Construct the API message */
1153   M (SW_INTERFACE_SET_TABLE, mp);
1154
1155   mp->sw_if_index = ntohl (sw_if_index);
1156   mp->is_ipv6 = is_ipv6;
1157   mp->vrf_id = ntohl (vrf_id);
1158
1159   /* send it... */
1160   S (mp);
1161
1162   /* Wait for a reply... */
1163   W (ret);
1164   return ret;
1165 }
1166
1167 static int
1168 api_sw_interface_address_replace_end (vat_main_t *vam)
1169 {
1170   return -1;
1171 }
1172
1173 static int
1174 api_sw_interface_set_ip_directed_broadcast (vat_main_t *vam)
1175 {
1176   return -1;
1177 }
1178
1179 static int
1180 api_sw_interface_set_mtu (vat_main_t *vam)
1181 {
1182   return -1;
1183 }
1184
1185 static int
1186 api_sw_interface_set_promisc (vat_main_t *vam)
1187 {
1188   return -1;
1189 }
1190
1191 static int
1192 api_want_interface_events (vat_main_t *vam)
1193 {
1194   unformat_input_t *i = vam->input;
1195   vl_api_want_interface_events_t *mp;
1196   int enable = -1;
1197   int ret;
1198
1199   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1200     {
1201       if (unformat (i, "enable"))
1202         enable = 1;
1203       else if (unformat (i, "disable"))
1204         enable = 0;
1205       else
1206         break;
1207     }
1208
1209   if (enable == -1)
1210     {
1211       errmsg ("missing enable|disable");
1212       return -99;
1213     }
1214
1215   M (WANT_INTERFACE_EVENTS, mp);
1216   mp->enable_disable = enable;
1217
1218   vam->interface_event_display = enable;
1219
1220   S (mp);
1221   W (ret);
1222   return ret;
1223 }
1224
1225 typedef struct
1226 {
1227   u8 *name;
1228   u32 value;
1229 } name_sort_t;
1230
1231 int
1232 api_sw_interface_dump (vat_main_t *vam)
1233 {
1234   vl_api_sw_interface_dump_t *mp;
1235   vl_api_control_ping_t *mp_ping;
1236   hash_pair_t *p;
1237   name_sort_t *nses = 0, *ns;
1238   sw_interface_subif_t *sub = NULL;
1239   int ret;
1240
1241   /* Toss the old name table */
1242   hash_foreach_pair (p, vam->sw_if_index_by_interface_name, ({
1243                        vec_add2 (nses, ns, 1);
1244                        ns->name = (u8 *) (p->key);
1245                        ns->value = (u32) p->value[0];
1246                      }));
1247
1248   hash_free (vam->sw_if_index_by_interface_name);
1249
1250   vec_foreach (ns, nses)
1251     vec_free (ns->name);
1252
1253   vec_free (nses);
1254
1255   vec_foreach (sub, vam->sw_if_subif_table)
1256     {
1257       vec_free (sub->interface_name);
1258     }
1259   vec_free (vam->sw_if_subif_table);
1260
1261   /* recreate the interface name hash table */
1262   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
1263
1264   /*
1265    * Ask for all interface names. Otherwise, the epic catalog of
1266    * name filters becomes ridiculously long, and vat ends up needing
1267    * to be taught about new interface types.
1268    */
1269   M (SW_INTERFACE_DUMP, mp);
1270   S (mp);
1271
1272   /* Use a control ping for synchronization */
1273   PING (&interface_test_main, mp_ping);
1274   S (mp_ping);
1275
1276   W (ret);
1277   return ret;
1278 }
1279
1280 static int
1281 api_sw_interface_set_interface_name (vat_main_t *vam)
1282 {
1283   return -1;
1284 }
1285
1286 static int
1287 api_pcap_set_filter_function (vat_main_t *vam)
1288 {
1289   vl_api_pcap_set_filter_function_t *mp;
1290   int ret;
1291
1292   M (PCAP_SET_FILTER_FUNCTION, mp);
1293   S (mp);
1294   W (ret);
1295   return ret;
1296 }
1297
1298 static int
1299 api_pcap_trace_on (vat_main_t *vam)
1300 {
1301   return -1;
1302 }
1303
1304 static int
1305 api_pcap_trace_off (vat_main_t *vam)
1306 {
1307   return -1;
1308 }
1309
1310 #include <vnet/interface.api_test.c>
1311
1312 /*
1313  * Local Variables:
1314  * eval: (c-set-style "gnu")
1315  * End:
1316  */