l2: Add bridge_domain_add_del_v2 to l2 api
[vpp.git] / src / vnet / l2 / l2_test.c
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright(c) 2021 Cisco Systems, Inc.
3  * Copyright(c) 2022 Nordix Foundation.
4  */
5
6 #include <vat/vat.h>
7 #include <vlibapi/api.h>
8 #include <vlibmemory/api.h>
9 #include <vppinfra/error.h>
10 #include <vpp/api/types.h>
11 #include <inttypes.h>
12
13 #include <vnet/l2/l2_classify.h>
14 #include <vnet/l2/l2_vtr.h>
15 #include <vnet/ip/ip_types_api.h>
16
17 #define __plugin_msg_base l2_test_main.msg_id_base
18 #include <vlibapi/vat_helper_macros.h>
19
20 #include <vlibmemory/vlib.api_enum.h>
21 #include <vlibmemory/vlib.api_types.h>
22
23 /* Declare message IDs */
24 #include <vnet/format_fns.h>
25 #include <vnet/l2/l2.api_enum.h>
26 #include <vnet/l2/l2.api_types.h>
27
28 #define vl_endianfun /* define message structures */
29 #include <vnet/l2/l2.api.h>
30 #undef vl_endianfun
31
32 #define vl_calcsizefun
33 #include <vnet/l2/l2.api.h>
34 #undef vl_calcsizefun
35
36 typedef struct
37 {
38   /* API message ID base */
39   u16 msg_id_base;
40   u32 ping_id;
41   vat_main_t *vat_main;
42 } l2_test_main_t;
43
44 static l2_test_main_t l2_test_main;
45
46 static void
47 vl_api_l2_fib_table_details_t_handler (vl_api_l2_fib_table_details_t *mp)
48 {
49   vat_main_t *vam = l2_test_main.vat_main;
50
51   fformat (
52     vam->ofp, "%3" PRIu32 "    %U    %3" PRIu32 "       %d       %d     %d",
53     ntohl (mp->bd_id), format_ethernet_address, mp->mac,
54     ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac, mp->bvi_mac);
55 }
56
57 static int
58 api_l2_fib_table_dump (vat_main_t *vam)
59 {
60   unformat_input_t *i = vam->input;
61   vl_api_l2_fib_table_dump_t *mp;
62   vl_api_control_ping_t *mp_ping;
63   u32 bd_id;
64   u8 bd_id_set = 0;
65   int ret;
66
67   /* Parse args required to build the message */
68   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
69     {
70       if (unformat (i, "bd_id %d", &bd_id))
71         bd_id_set = 1;
72       else
73         break;
74     }
75
76   if (bd_id_set == 0)
77     {
78       errmsg ("missing bridge domain");
79       return -99;
80     }
81
82   fformat (vam->ofp, "BD-ID     Mac Address      sw-ndx  Static  Filter  BVI");
83
84   /* Get list of l2 fib entries */
85   M (L2_FIB_TABLE_DUMP, mp);
86
87   mp->bd_id = ntohl (bd_id);
88   S (mp);
89
90   /* Use a control ping for synchronization */
91   PING (&l2_test_main, mp_ping);
92   S (mp_ping);
93
94   W (ret);
95   return ret;
96 }
97
98 static void
99 vl_api_l2_xconnect_details_t_handler (vl_api_l2_xconnect_details_t *mp)
100 {
101   vat_main_t *vam = l2_test_main.vat_main;
102   fformat (vam->ofp, "%15d%15d", ntohl (mp->rx_sw_if_index),
103            ntohl (mp->tx_sw_if_index));
104 }
105
106 static int
107 api_l2_xconnect_dump (vat_main_t *vam)
108 {
109   vl_api_l2_xconnect_dump_t *mp;
110   vl_api_control_ping_t *mp_ping;
111   int ret;
112
113   if (!vam->json_output)
114     {
115       print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index");
116     }
117
118   M (L2_XCONNECT_DUMP, mp);
119
120   S (mp);
121
122   /* Use a control ping for synchronization */
123   PING (&l2_test_main, mp_ping);
124   S (mp_ping);
125
126   W (ret);
127   return ret;
128 }
129
130 static int
131 api_want_l2_arp_term_events (vat_main_t *vam)
132 {
133   return -1;
134 }
135
136 static int
137 api_want_l2_macs_events (vat_main_t *vam)
138 {
139   unformat_input_t *line_input = vam->input;
140   vl_api_want_l2_macs_events_t *mp;
141   u8 enable_disable = 1;
142   u32 scan_delay = 0;
143   u32 max_macs_in_event = 0;
144   u32 learn_limit = 0;
145   int ret;
146
147   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
148     {
149       if (unformat (line_input, "learn-limit %d", &learn_limit))
150         ;
151       else if (unformat (line_input, "scan-delay %d", &scan_delay))
152         ;
153       else if (unformat (line_input, "max-entries %d", &max_macs_in_event))
154         ;
155       else if (unformat (line_input, "disable"))
156         enable_disable = 0;
157       else
158         break;
159     }
160
161   M (WANT_L2_MACS_EVENTS, mp);
162   mp->enable_disable = enable_disable;
163   mp->pid = htonl (getpid ());
164   mp->learn_limit = htonl (learn_limit);
165   mp->scan_delay = (u8) scan_delay;
166   mp->max_macs_in_event = (u8) (max_macs_in_event / 10);
167   S (mp);
168   W (ret);
169   return ret;
170 }
171
172 static int
173 api_l2fib_flush_all (vat_main_t *vam)
174 {
175   return -1;
176 }
177
178 static void
179 increment_mac_address (u8 *mac)
180 {
181   u64 tmp = *((u64 *) mac);
182   tmp = clib_net_to_host_u64 (tmp);
183   tmp += 1 << 16; /* skip unused (least significant) octets */
184   tmp = clib_host_to_net_u64 (tmp);
185
186   clib_memcpy (mac, &tmp, 6);
187 }
188
189 static int
190 api_l2fib_add_del (vat_main_t *vam)
191 {
192   vnet_main_t *vnm = vnet_get_main ();
193   unformat_input_t *i = vam->input;
194   vl_api_l2fib_add_del_t *mp;
195   f64 timeout;
196   u8 mac[8] = { 0 };
197   u8 mac_set = 0;
198   u32 bd_id;
199   u8 bd_id_set = 0;
200   u32 sw_if_index = 0;
201   u8 sw_if_index_set = 0;
202   u8 is_add = 1;
203   u8 static_mac = 0;
204   u8 filter_mac = 0;
205   u8 bvi_mac = 0;
206   int count = 1;
207   f64 before = 0;
208   int j;
209
210   /* Parse args required to build the message */
211   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
212     {
213       if (unformat (i, "mac %U", unformat_ethernet_address, mac))
214         mac_set = 1;
215       else if (unformat (i, "bd_id %d", &bd_id))
216         bd_id_set = 1;
217       else if (unformat (i, "sw_if_index %d", &sw_if_index))
218         sw_if_index_set = 1;
219       else if (unformat (i, "sw_if"))
220         {
221           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
222             {
223               if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
224                             &sw_if_index))
225                 sw_if_index_set = 1;
226             }
227           else
228             break;
229         }
230       else if (unformat (i, "static"))
231         static_mac = 1;
232       else if (unformat (i, "filter"))
233         {
234           filter_mac = 1;
235           static_mac = 1;
236         }
237       else if (unformat (i, "bvi"))
238         {
239           bvi_mac = 1;
240           static_mac = 1;
241         }
242       else if (unformat (i, "del"))
243         is_add = 0;
244       else if (unformat (i, "count %d", &count))
245         ;
246       else
247         break;
248     }
249
250   if (mac_set == 0)
251     {
252       errmsg ("missing mac address");
253       return -99;
254     }
255
256   if (bd_id_set == 0)
257     {
258       errmsg ("missing bridge domain");
259       return -99;
260     }
261
262   if (is_add && sw_if_index_set == 0 && filter_mac == 0)
263     {
264       errmsg ("missing interface name or sw_if_index");
265       return -99;
266     }
267
268   if (count > 1)
269     {
270       /* Turn on async mode */
271       vam->async_mode = 1;
272       vam->async_errors = 0;
273       before = vat_time_now (vam);
274     }
275
276   for (j = 0; j < count; j++)
277     {
278       M (L2FIB_ADD_DEL, mp);
279
280       clib_memcpy (mp->mac, mac, 6);
281       mp->bd_id = ntohl (bd_id);
282       mp->is_add = is_add;
283       mp->sw_if_index = ntohl (sw_if_index);
284
285       if (is_add)
286         {
287           mp->static_mac = static_mac;
288           mp->filter_mac = filter_mac;
289           mp->bvi_mac = bvi_mac;
290         }
291       increment_mac_address (mac);
292       /* send it... */
293       S (mp);
294     }
295
296   if (count > 1)
297     {
298       vl_api_control_ping_t *mp_ping;
299       f64 after;
300
301       /* Shut off async mode */
302       vam->async_mode = 0;
303
304       PING (&l2_test_main, mp_ping);
305       S (mp_ping);
306
307       timeout = vat_time_now (vam) + 1.0;
308       while (vat_time_now (vam) < timeout)
309         if (vam->result_ready == 1)
310           goto out;
311       vam->retval = -99;
312
313     out:
314       if (vam->retval == -99)
315         errmsg ("timeout");
316
317       if (vam->async_errors > 0)
318         {
319           errmsg ("%d asynchronous errors", vam->async_errors);
320           vam->retval = -98;
321         }
322       vam->async_errors = 0;
323       after = vat_time_now (vam);
324
325       print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec", count,
326              after - before, count / (after - before));
327     }
328   else
329     {
330       int ret;
331
332       /* Wait for a reply... */
333       W (ret);
334       return ret;
335     }
336   /* Return the good/bad news */
337   return (vam->retval);
338 }
339
340 static int
341 api_l2fib_flush_int (vat_main_t *vam)
342 {
343   vnet_main_t *vnm = vnet_get_main ();
344   unformat_input_t *i = vam->input;
345   vl_api_l2fib_flush_int_t *mp;
346   u32 sw_if_index = ~0;
347   int ret;
348
349   /* Parse args required to build the message */
350   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
351     {
352       if (unformat (i, "sw_if_index %d", &sw_if_index))
353         ;
354       else if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
355                          &sw_if_index))
356         ;
357       else
358         break;
359     }
360
361   if (sw_if_index == ~0)
362     {
363       errmsg ("missing interface name or sw_if_index");
364       return -99;
365     }
366
367   M (L2FIB_FLUSH_INT, mp);
368
369   mp->sw_if_index = ntohl (sw_if_index);
370
371   S (mp);
372   W (ret);
373   return ret;
374 }
375
376 static int
377 api_l2_fib_clear_table (vat_main_t *vam)
378 {
379   vl_api_l2_fib_clear_table_t *mp;
380   int ret;
381
382   M (L2_FIB_CLEAR_TABLE, mp);
383
384   S (mp);
385   W (ret);
386   return ret;
387 }
388
389 static int
390 api_bridge_domain_set_mac_age (vat_main_t *vam)
391 {
392   unformat_input_t *i = vam->input;
393   vl_api_bridge_domain_set_mac_age_t *mp;
394   u32 bd_id = ~0;
395   u32 mac_age = 0;
396   int ret;
397
398   /* Parse args required to build the message */
399   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
400     {
401       if (unformat (i, "bd_id %d", &bd_id))
402         ;
403       else if (unformat (i, "mac-age %d", &mac_age))
404         ;
405       else
406         break;
407     }
408
409   if (bd_id == ~0)
410     {
411       errmsg ("missing bridge domain");
412       return -99;
413     }
414
415   if (mac_age > 255)
416     {
417       errmsg ("mac age must be less than 256 ");
418       return -99;
419     }
420
421   M (BRIDGE_DOMAIN_SET_MAC_AGE, mp);
422
423   mp->bd_id = htonl (bd_id);
424   mp->mac_age = (u8) mac_age;
425
426   S (mp);
427   W (ret);
428   return ret;
429 }
430
431 static int
432 api_l2fib_set_scan_delay (vat_main_t *vam)
433 {
434   return -1;
435 }
436
437 static int
438 api_want_l2_macs_events2 (vat_main_t *vam)
439 {
440   return -1;
441 }
442
443 static int
444 api_l2_flags (vat_main_t *vam)
445 {
446   vnet_main_t *vnm = vnet_get_main ();
447   unformat_input_t *i = vam->input;
448   vl_api_l2_flags_t *mp;
449   u32 sw_if_index;
450   u32 flags = 0;
451   u8 sw_if_index_set = 0;
452   u8 is_set = 0;
453   int ret;
454
455   /* Parse args required to build the message */
456   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
457     {
458       if (unformat (i, "sw_if_index %d", &sw_if_index))
459         sw_if_index_set = 1;
460       else if (unformat (i, "sw_if"))
461         {
462           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
463             {
464               if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
465                             &sw_if_index))
466                 sw_if_index_set = 1;
467             }
468           else
469             break;
470         }
471       else if (unformat (i, "learn"))
472         flags |= L2_LEARN;
473       else if (unformat (i, "forward"))
474         flags |= L2_FWD;
475       else if (unformat (i, "flood"))
476         flags |= L2_FLOOD;
477       else if (unformat (i, "uu-flood"))
478         flags |= L2_UU_FLOOD;
479       else if (unformat (i, "arp-term"))
480         flags |= L2_ARP_TERM;
481       else if (unformat (i, "off"))
482         is_set = 0;
483       else if (unformat (i, "disable"))
484         is_set = 0;
485       else
486         break;
487     }
488
489   if (sw_if_index_set == 0)
490     {
491       errmsg ("missing interface name or sw_if_index");
492       return -99;
493     }
494
495   M (L2_FLAGS, mp);
496
497   mp->sw_if_index = ntohl (sw_if_index);
498   mp->feature_bitmap = ntohl (flags);
499   mp->is_set = is_set;
500
501   S (mp);
502   W (ret);
503   return ret;
504 }
505
506 static void
507 vl_api_l2_flags_reply_t_handler (vl_api_l2_flags_reply_t *mp)
508 {
509   vat_main_t *vam = l2_test_main.vat_main;
510   i32 retval = ntohl (mp->retval);
511   if (vam->async_mode)
512     {
513       vam->async_errors += (retval < 0);
514     }
515   else
516     {
517       vam->retval = retval;
518       vam->result_ready = 1;
519     }
520 }
521
522 static int
523 api_l2fib_flush_bd (vat_main_t *vam)
524 {
525   unformat_input_t *i = vam->input;
526   vl_api_l2fib_flush_bd_t *mp;
527   u32 bd_id = ~0;
528   int ret;
529
530   /* Parse args required to build the message */
531   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
532     {
533       if (unformat (i, "bd_id %d", &bd_id))
534         ;
535       else
536         break;
537     }
538
539   if (bd_id == ~0)
540     {
541       errmsg ("missing bridge domain");
542       return -99;
543     }
544
545   M (L2FIB_FLUSH_BD, mp);
546
547   mp->bd_id = htonl (bd_id);
548
549   S (mp);
550   W (ret);
551   return ret;
552 }
553
554 static int
555 api_bridge_domain_add_del (vat_main_t *vam)
556 {
557   unformat_input_t *i = vam->input;
558   vl_api_bridge_domain_add_del_t *mp;
559   u32 bd_id = ~0;
560   u8 is_add = 1;
561   u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0;
562   u8 *bd_tag = NULL;
563   u32 mac_age = 0;
564   int ret;
565
566   /* Parse args required to build the message */
567   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
568     {
569       if (unformat (i, "bd_id %d", &bd_id))
570         ;
571       else if (unformat (i, "flood %d", &flood))
572         ;
573       else if (unformat (i, "uu-flood %d", &uu_flood))
574         ;
575       else if (unformat (i, "forward %d", &forward))
576         ;
577       else if (unformat (i, "learn %d", &learn))
578         ;
579       else if (unformat (i, "arp-term %d", &arp_term))
580         ;
581       else if (unformat (i, "mac-age %d", &mac_age))
582         ;
583       else if (unformat (i, "bd-tag %s", &bd_tag))
584         ;
585       else if (unformat (i, "del"))
586         {
587           is_add = 0;
588           flood = uu_flood = forward = learn = 0;
589         }
590       else
591         break;
592     }
593
594   if (bd_id == ~0)
595     {
596       errmsg ("missing bridge domain");
597       ret = -99;
598       goto done;
599     }
600
601   if (mac_age > 255)
602     {
603       errmsg ("mac age must be less than 256 ");
604       ret = -99;
605       goto done;
606     }
607
608   if ((bd_tag) && (vec_len (bd_tag) > 63))
609     {
610       errmsg ("bd-tag cannot be longer than 63");
611       ret = -99;
612       goto done;
613     }
614
615   M (BRIDGE_DOMAIN_ADD_DEL, mp);
616
617   mp->bd_id = ntohl (bd_id);
618   mp->flood = flood;
619   mp->uu_flood = uu_flood;
620   mp->forward = forward;
621   mp->learn = learn;
622   mp->arp_term = arp_term;
623   mp->is_add = is_add;
624   mp->mac_age = (u8) mac_age;
625   if (bd_tag)
626     {
627       clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
628       mp->bd_tag[vec_len (bd_tag)] = 0;
629     }
630   S (mp);
631   W (ret);
632
633 done:
634   vec_free (bd_tag);
635   return ret;
636 }
637
638 static int
639 api_bridge_domain_add_del_v2 (vat_main_t *vam)
640 {
641   return -1;
642 }
643
644 static void
645 vl_api_bridge_domain_add_del_v2_reply_t_handler (
646   vl_api_bridge_domain_add_del_v2_reply_t *mp)
647 {
648 }
649
650 #define foreach_pbb_vtr_op                                                    \
651   _ ("disable", L2_VTR_DISABLED)                                              \
652   _ ("pop", L2_VTR_POP_2)                                                     \
653   _ ("push", L2_VTR_PUSH_2)
654
655 static int
656 api_l2_interface_pbb_tag_rewrite (vat_main_t *vam)
657 {
658   vnet_main_t *vnm = vnet_get_main ();
659   unformat_input_t *i = vam->input;
660   vl_api_l2_interface_pbb_tag_rewrite_t *mp;
661   u32 sw_if_index = ~0, vtr_op = ~0;
662   u16 outer_tag = ~0;
663   u8 dmac[6], smac[6];
664   u8 dmac_set = 0, smac_set = 0;
665   u16 vlanid = 0;
666   u32 sid = ~0;
667   u32 tmp;
668   int ret;
669
670   /* Shut up coverity */
671   clib_memset (dmac, 0, sizeof (dmac));
672   clib_memset (smac, 0, sizeof (smac));
673
674   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
675     {
676       if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
677         ;
678       else if (unformat (i, "sw_if_index %d", &sw_if_index))
679         ;
680       else if (unformat (i, "vtr_op %d", &vtr_op))
681         ;
682 #define _(n, v)                                                               \
683   else if (unformat (i, n)) { vtr_op = v; }
684       foreach_pbb_vtr_op
685 #undef _
686         else if (unformat (i, "translate_pbb_stag"))
687       {
688         if (unformat (i, "%d", &tmp))
689           {
690             vtr_op = L2_VTR_TRANSLATE_2_1;
691             outer_tag = tmp;
692           }
693         else
694           {
695             errmsg (
696               "translate_pbb_stag operation requires outer tag definition");
697             return -99;
698           }
699       }
700       else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac))
701         dmac_set++;
702       else if (unformat (i, "smac %U", unformat_ethernet_address, smac))
703         smac_set++;
704       else if (unformat (i, "sid %d", &sid));
705       else if (unformat (i, "vlanid %d", &tmp)) vlanid = tmp;
706       else
707       {
708         clib_warning ("parse error '%U'", format_unformat_error, i);
709         return -99;
710       }
711     }
712
713   if ((sw_if_index == ~0) || (vtr_op == ~0))
714     {
715       errmsg ("missing sw_if_index or vtr operation");
716       return -99;
717     }
718   if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2)) &&
719       ((dmac_set == 0) || (smac_set == 0) || (sid == ~0)))
720     {
721       errmsg ("push and translate_qinq operations require dmac, smac, sid and "
722               "optionally vlanid");
723       return -99;
724     }
725
726   M (L2_INTERFACE_PBB_TAG_REWRITE, mp);
727   mp->sw_if_index = ntohl (sw_if_index);
728   mp->vtr_op = ntohl (vtr_op);
729   mp->outer_tag = ntohs (outer_tag);
730   clib_memcpy (mp->b_dmac, dmac, sizeof (dmac));
731   clib_memcpy (mp->b_smac, smac, sizeof (smac));
732   mp->b_vlanid = ntohs (vlanid);
733   mp->i_sid = ntohl (sid);
734
735   S (mp);
736   W (ret);
737   return ret;
738 }
739
740 static int
741 api_sw_interface_set_l2_xconnect (vat_main_t *vam)
742 {
743   vnet_main_t *vnm = vnet_get_main ();
744   unformat_input_t *i = vam->input;
745   vl_api_sw_interface_set_l2_xconnect_t *mp;
746   u32 rx_sw_if_index;
747   u8 rx_sw_if_index_set = 0;
748   u32 tx_sw_if_index;
749   u8 tx_sw_if_index_set = 0;
750   u8 enable = 1;
751   int ret;
752
753   /* Parse args required to build the message */
754   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
755     {
756       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
757         rx_sw_if_index_set = 1;
758       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
759         tx_sw_if_index_set = 1;
760       else if (unformat (i, "rx"))
761         {
762           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
763             {
764               if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
765                             &rx_sw_if_index))
766                 rx_sw_if_index_set = 1;
767             }
768           else
769             break;
770         }
771       else if (unformat (i, "tx"))
772         {
773           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
774             {
775               if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
776                             &tx_sw_if_index))
777                 tx_sw_if_index_set = 1;
778             }
779           else
780             break;
781         }
782       else if (unformat (i, "enable"))
783         enable = 1;
784       else if (unformat (i, "disable"))
785         enable = 0;
786       else
787         break;
788     }
789
790   if (rx_sw_if_index_set == 0)
791     {
792       errmsg ("missing rx interface name or rx_sw_if_index");
793       return -99;
794     }
795
796   if (enable && (tx_sw_if_index_set == 0))
797     {
798       errmsg ("missing tx interface name or tx_sw_if_index");
799       return -99;
800     }
801
802   M (SW_INTERFACE_SET_L2_XCONNECT, mp);
803
804   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
805   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
806   mp->enable = enable;
807
808   S (mp);
809   W (ret);
810   return ret;
811 }
812
813 static int
814 api_l2_interface_efp_filter (vat_main_t *vam)
815 {
816   vnet_main_t *vnm = vnet_get_main ();
817   unformat_input_t *i = vam->input;
818   vl_api_l2_interface_efp_filter_t *mp;
819   u32 sw_if_index;
820   u8 enable = 1;
821   u8 sw_if_index_set = 0;
822   int ret;
823
824   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
825     {
826       if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
827         sw_if_index_set = 1;
828       else if (unformat (i, "sw_if_index %d", &sw_if_index))
829         sw_if_index_set = 1;
830       else if (unformat (i, "enable"))
831         enable = 1;
832       else if (unformat (i, "disable"))
833         enable = 0;
834       else
835         {
836           clib_warning ("parse error '%U'", format_unformat_error, i);
837           return -99;
838         }
839     }
840
841   if (sw_if_index_set == 0)
842     {
843       errmsg ("missing sw_if_index");
844       return -99;
845     }
846
847   M (L2_INTERFACE_EFP_FILTER, mp);
848
849   mp->sw_if_index = ntohl (sw_if_index);
850   mp->enable_disable = enable;
851
852   S (mp);
853   W (ret);
854   return ret;
855 }
856
857 static void
858 vl_api_bd_ip_mac_details_t_handler (vl_api_bd_ip_mac_details_t *mp)
859 {
860   vat_main_t *vam = &vat_main;
861
862   print (vam->ofp, "\n%-5d %U %U", ntohl (mp->entry.bd_id),
863          format_vl_api_mac_address, mp->entry.mac, format_vl_api_address,
864          &mp->entry.ip);
865 }
866
867 static void
868 vl_api_bvi_create_reply_t_handler (vl_api_bvi_create_reply_t *mp)
869 {
870 }
871
872 static int
873 api_sw_interface_set_l2_bridge (vat_main_t *vam)
874 {
875   vnet_main_t *vnm = vnet_get_main ();
876   unformat_input_t *i = vam->input;
877   vl_api_sw_interface_set_l2_bridge_t *mp;
878   vl_api_l2_port_type_t port_type;
879   u32 rx_sw_if_index;
880   u8 rx_sw_if_index_set = 0;
881   u32 bd_id;
882   u8 bd_id_set = 0;
883   u32 shg = 0;
884   u8 enable = 1;
885   int ret;
886
887   port_type = L2_API_PORT_TYPE_NORMAL;
888
889   /* Parse args required to build the message */
890   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
891     {
892       if (unformat (i, "sw_if_index %d", &rx_sw_if_index))
893         rx_sw_if_index_set = 1;
894       else if (unformat (i, "bd_id %d", &bd_id))
895         bd_id_set = 1;
896       else if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
897                          &rx_sw_if_index))
898         rx_sw_if_index_set = 1;
899       else if (unformat (i, "shg %d", &shg))
900         ;
901       else if (unformat (i, "bvi"))
902         port_type = L2_API_PORT_TYPE_BVI;
903       else if (unformat (i, "uu-fwd"))
904         port_type = L2_API_PORT_TYPE_UU_FWD;
905       else if (unformat (i, "enable"))
906         enable = 1;
907       else if (unformat (i, "disable"))
908         enable = 0;
909       else
910         break;
911     }
912
913   if (rx_sw_if_index_set == 0)
914     {
915       errmsg ("missing rx interface name or sw_if_index");
916       return -99;
917     }
918
919   if (enable && (bd_id_set == 0))
920     {
921       errmsg ("missing bridge domain");
922       return -99;
923     }
924
925   M (SW_INTERFACE_SET_L2_BRIDGE, mp);
926
927   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
928   mp->bd_id = ntohl (bd_id);
929   mp->shg = (u8) shg;
930   mp->port_type = ntohl (port_type);
931   mp->enable = enable;
932
933   S (mp);
934   W (ret);
935   return ret;
936 }
937
938 static int
939 api_sw_interface_set_vpath (vat_main_t *vam)
940 {
941   vnet_main_t *vnm = vnet_get_main ();
942   unformat_input_t *i = vam->input;
943   vl_api_sw_interface_set_vpath_t *mp;
944   u32 sw_if_index = 0;
945   u8 sw_if_index_set = 0;
946   u8 is_enable = 0;
947   int ret;
948
949   /* Parse args required to build the message */
950   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
951     {
952       if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
953         sw_if_index_set = 1;
954       else if (unformat (i, "sw_if_index %d", &sw_if_index))
955         sw_if_index_set = 1;
956       else if (unformat (i, "enable"))
957         is_enable = 1;
958       else if (unformat (i, "disable"))
959         is_enable = 0;
960       else
961         break;
962     }
963
964   if (sw_if_index_set == 0)
965     {
966       errmsg ("missing interface name or sw_if_index");
967       return -99;
968     }
969
970   /* Construct the API message */
971   M (SW_INTERFACE_SET_VPATH, mp);
972
973   mp->sw_if_index = ntohl (sw_if_index);
974   mp->enable = is_enable;
975
976   /* send it... */
977   S (mp);
978
979   /* Wait for a reply... */
980   W (ret);
981   return ret;
982 }
983
984 static int
985 api_l2_patch_add_del (vat_main_t *vam)
986 {
987   vnet_main_t *vnm = vnet_get_main ();
988   unformat_input_t *i = vam->input;
989   vl_api_l2_patch_add_del_t *mp;
990   u32 rx_sw_if_index;
991   u8 rx_sw_if_index_set = 0;
992   u32 tx_sw_if_index;
993   u8 tx_sw_if_index_set = 0;
994   u8 is_add = 1;
995   int ret;
996
997   /* Parse args required to build the message */
998   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
999     {
1000       if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index))
1001         rx_sw_if_index_set = 1;
1002       else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index))
1003         tx_sw_if_index_set = 1;
1004       else if (unformat (i, "rx"))
1005         {
1006           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1007             {
1008               if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
1009                             &rx_sw_if_index))
1010                 rx_sw_if_index_set = 1;
1011             }
1012           else
1013             break;
1014         }
1015       else if (unformat (i, "tx"))
1016         {
1017           if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1018             {
1019               if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
1020                             &tx_sw_if_index))
1021                 tx_sw_if_index_set = 1;
1022             }
1023           else
1024             break;
1025         }
1026       else if (unformat (i, "del"))
1027         is_add = 0;
1028       else
1029         break;
1030     }
1031
1032   if (rx_sw_if_index_set == 0)
1033     {
1034       errmsg ("missing rx interface name or rx_sw_if_index");
1035       return -99;
1036     }
1037
1038   if (tx_sw_if_index_set == 0)
1039     {
1040       errmsg ("missing tx interface name or tx_sw_if_index");
1041       return -99;
1042     }
1043
1044   M (L2_PATCH_ADD_DEL, mp);
1045
1046   mp->rx_sw_if_index = ntohl (rx_sw_if_index);
1047   mp->tx_sw_if_index = ntohl (tx_sw_if_index);
1048   mp->is_add = is_add;
1049
1050   S (mp);
1051   W (ret);
1052   return ret;
1053 }
1054
1055 static void
1056 vl_api_bridge_flags_reply_t_handler (vl_api_bridge_flags_reply_t *mp)
1057 {
1058   vat_main_t *vam = &vat_main;
1059   i32 retval = ntohl (mp->retval);
1060   if (vam->async_mode)
1061     {
1062       vam->async_errors += (retval < 0);
1063     }
1064   else
1065     {
1066       vam->retval = retval;
1067       vam->result_ready = 1;
1068     }
1069 }
1070
1071 #define foreach_vtr_op                                                        \
1072   _ ("disable", L2_VTR_DISABLED)                                              \
1073   _ ("push-1", L2_VTR_PUSH_1)                                                 \
1074   _ ("push-2", L2_VTR_PUSH_2)                                                 \
1075   _ ("pop-1", L2_VTR_POP_1)                                                   \
1076   _ ("pop-2", L2_VTR_POP_2)                                                   \
1077   _ ("translate-1-1", L2_VTR_TRANSLATE_1_1)                                   \
1078   _ ("translate-1-2", L2_VTR_TRANSLATE_1_2)                                   \
1079   _ ("translate-2-1", L2_VTR_TRANSLATE_2_1)                                   \
1080   _ ("translate-2-2", L2_VTR_TRANSLATE_2_2)
1081
1082 static int
1083 api_l2_interface_vlan_tag_rewrite (vat_main_t *vam)
1084 {
1085   vnet_main_t *vnm = vnet_get_main ();
1086   unformat_input_t *i = vam->input;
1087   vl_api_l2_interface_vlan_tag_rewrite_t *mp;
1088   u32 sw_if_index;
1089   u8 sw_if_index_set = 0;
1090   u8 vtr_op_set = 0;
1091   u32 vtr_op = 0;
1092   u32 push_dot1q = 1;
1093   u32 tag1 = ~0;
1094   u32 tag2 = ~0;
1095   int ret;
1096
1097   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1098     {
1099       if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
1100         sw_if_index_set = 1;
1101       else if (unformat (i, "sw_if_index %d", &sw_if_index))
1102         sw_if_index_set = 1;
1103       else if (unformat (i, "vtr_op %d", &vtr_op))
1104         vtr_op_set = 1;
1105 #define _(n, v)                                                               \
1106   else if (unformat (i, n))                                                   \
1107   {                                                                           \
1108     vtr_op = v;                                                               \
1109     vtr_op_set = 1;                                                           \
1110   }
1111       foreach_vtr_op
1112 #undef _
1113         else if (unformat (i, "push_dot1q %d", &push_dot1q));
1114       else if (unformat (i, "tag1 %d", &tag1));
1115       else if (unformat (i, "tag2 %d", &tag2));
1116       else
1117       {
1118         clib_warning ("parse error '%U'", format_unformat_error, i);
1119         return -99;
1120       }
1121     }
1122
1123   if ((sw_if_index_set == 0) || (vtr_op_set == 0))
1124     {
1125       errmsg ("missing vtr operation or sw_if_index");
1126       return -99;
1127     }
1128
1129   M (L2_INTERFACE_VLAN_TAG_REWRITE, mp);
1130   mp->sw_if_index = ntohl (sw_if_index);
1131   mp->vtr_op = ntohl (vtr_op);
1132   mp->push_dot1q = ntohl (push_dot1q);
1133   mp->tag1 = ntohl (tag1);
1134   mp->tag2 = ntohl (tag2);
1135
1136   S (mp);
1137   W (ret);
1138   return ret;
1139 }
1140
1141 static int
1142 api_bridge_domain_set_learn_limit (vat_main_t *vam)
1143 {
1144   return -1;
1145 }
1146
1147 static int
1148 api_bd_ip_mac_add_del (vat_main_t *vam)
1149 {
1150   vl_api_address_t ip = VL_API_ZERO_ADDRESS;
1151   vl_api_mac_address_t mac = { 0 };
1152   unformat_input_t *i = vam->input;
1153   vl_api_bd_ip_mac_add_del_t *mp;
1154   u32 bd_id;
1155   u8 is_add = 1;
1156   u8 bd_id_set = 0;
1157   u8 ip_set = 0;
1158   u8 mac_set = 0;
1159   int ret;
1160
1161   /* Parse args required to build the message */
1162   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1163     {
1164       if (unformat (i, "bd_id %d", &bd_id))
1165         {
1166           bd_id_set++;
1167         }
1168       else if (unformat (i, "%U", unformat_vl_api_address, &ip))
1169         {
1170           ip_set++;
1171         }
1172       else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
1173         {
1174           mac_set++;
1175         }
1176       else if (unformat (i, "del"))
1177         is_add = 0;
1178       else
1179         break;
1180     }
1181
1182   if (bd_id_set == 0)
1183     {
1184       errmsg ("missing bridge domain");
1185       return -99;
1186     }
1187   else if (ip_set == 0)
1188     {
1189       errmsg ("missing IP address");
1190       return -99;
1191     }
1192   else if (mac_set == 0)
1193     {
1194       errmsg ("missing MAC address");
1195       return -99;
1196     }
1197
1198   M (BD_IP_MAC_ADD_DEL, mp);
1199
1200   mp->entry.bd_id = ntohl (bd_id);
1201   mp->is_add = is_add;
1202
1203   clib_memcpy (&mp->entry.ip, &ip, sizeof (ip));
1204   clib_memcpy (&mp->entry.mac, &mac, sizeof (mac));
1205
1206   S (mp);
1207   W (ret);
1208   return ret;
1209 }
1210
1211 static void
1212 vl_api_bridge_domain_details_t_handler (vl_api_bridge_domain_details_t *mp)
1213 {
1214   vat_main_t *vam = l2_test_main.vat_main;
1215   u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
1216   int i;
1217
1218   print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-6s %-3s", " ID", "LRN", "FWD",
1219          "FLD", "BVI", "UU-FWD", "#IF");
1220
1221   print (vam->ofp, "%3d %3d %3d %3d %3d %6d %3d", ntohl (mp->bd_id), mp->learn,
1222          mp->forward, mp->flood, ntohl (mp->bvi_sw_if_index),
1223          ntohl (mp->uu_fwd_sw_if_index), n_sw_ifs);
1224
1225   if (n_sw_ifs)
1226     {
1227       vl_api_bridge_domain_sw_if_t *sw_ifs;
1228       print (vam->ofp, "\n\n%s %s  %s", "sw_if_index", "SHG",
1229              "Interface Name");
1230
1231       sw_ifs = mp->sw_if_details;
1232       for (i = 0; i < n_sw_ifs; i++)
1233         {
1234           u8 *sw_if_name = 0;
1235           u32 sw_if_index;
1236           hash_pair_t *p;
1237
1238           sw_if_index = ntohl (sw_ifs->sw_if_index);
1239
1240           hash_foreach_pair (p, vam->sw_if_index_by_interface_name, ({
1241                                if ((u32) p->value[0] == sw_if_index)
1242                                  {
1243                                    sw_if_name = (u8 *) (p->key);
1244                                    break;
1245                                  }
1246                              }));
1247           print (vam->ofp, "%7d     %3d  %s", sw_if_index, sw_ifs->shg,
1248                  sw_if_name ? (char *) sw_if_name : "sw_if_index not found!");
1249
1250           sw_ifs++;
1251         }
1252     }
1253 }
1254
1255 static int
1256 api_bridge_domain_dump (vat_main_t *vam)
1257 {
1258   unformat_input_t *i = vam->input;
1259   vl_api_bridge_domain_dump_t *mp;
1260   vl_api_control_ping_t *mp_ping;
1261   u32 bd_id = ~0;
1262   int ret;
1263
1264   /* Parse args required to build the message */
1265   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1266     {
1267       if (unformat (i, "bd_id %d", &bd_id))
1268         ;
1269       else
1270         break;
1271     }
1272
1273   M (BRIDGE_DOMAIN_DUMP, mp);
1274   mp->bd_id = ntohl (bd_id);
1275   S (mp);
1276
1277   /* Use a control ping for synchronization */
1278   PING (&l2_test_main, mp_ping);
1279   S (mp_ping);
1280
1281   W (ret);
1282   return ret;
1283 }
1284
1285 static int
1286 api_bridge_domain_set_default_learn_limit (vat_main_t *vam)
1287 {
1288   return -1;
1289 }
1290
1291 static int
1292 api_bd_ip_mac_flush (vat_main_t *vam)
1293 {
1294   unformat_input_t *i = vam->input;
1295   vl_api_bd_ip_mac_flush_t *mp;
1296   u32 bd_id;
1297   u8 bd_id_set = 0;
1298   int ret;
1299
1300   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1301     {
1302       if (unformat (i, "bd_id %d", &bd_id))
1303         {
1304           bd_id_set++;
1305         }
1306       else
1307         break;
1308     }
1309
1310   if (bd_id_set == 0)
1311     {
1312       errmsg ("missing bridge domain");
1313       return -99;
1314     }
1315
1316   M (BD_IP_MAC_FLUSH, mp);
1317
1318   mp->bd_id = ntohl (bd_id);
1319
1320   S (mp);
1321   W (ret);
1322   return ret;
1323 }
1324
1325 static int
1326 api_bd_ip_mac_dump (vat_main_t *vam)
1327 {
1328   unformat_input_t *i = vam->input;
1329   vl_api_bd_ip_mac_dump_t *mp;
1330   vl_api_control_ping_t *mp_ping;
1331   int ret;
1332   u32 bd_id;
1333   u8 bd_id_set = 0;
1334
1335   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1336     {
1337       if (unformat (i, "bd_id %d", &bd_id))
1338         {
1339           bd_id_set++;
1340         }
1341       else
1342         break;
1343     }
1344
1345   fformat (vam->ofp, "\n%-5s %-7s %-20s %-30s", "bd_id", "is_ipv6",
1346            "mac_address", "ip_address");
1347
1348   /* Dump Bridge Domain Ip to Mac entries */
1349   M (BD_IP_MAC_DUMP, mp);
1350
1351   if (bd_id_set)
1352     mp->bd_id = htonl (bd_id);
1353   else
1354     mp->bd_id = ~0;
1355
1356   S (mp);
1357
1358   /* Use a control ping for synchronization */
1359   PING (&l2_test_main, mp_ping);
1360   S (mp_ping);
1361
1362   W (ret);
1363   return ret;
1364 }
1365
1366 static int
1367 api_bvi_create (vat_main_t *vam)
1368 {
1369   return -1;
1370 }
1371
1372 static int
1373 api_bvi_delete (vat_main_t *vam)
1374 {
1375   return -1;
1376 }
1377
1378 static int
1379 api_bridge_flags (vat_main_t *vam)
1380 {
1381   unformat_input_t *i = vam->input;
1382   vl_api_bridge_flags_t *mp;
1383   u32 bd_id;
1384   u8 bd_id_set = 0;
1385   u8 is_set = 1;
1386   bd_flags_t flags = 0;
1387   int ret;
1388
1389   /* Parse args required to build the message */
1390   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1391     {
1392       if (unformat (i, "bd_id %d", &bd_id))
1393         bd_id_set = 1;
1394       else if (unformat (i, "learn"))
1395         flags |= BRIDGE_API_FLAG_LEARN;
1396       else if (unformat (i, "forward"))
1397         flags |= BRIDGE_API_FLAG_FWD;
1398       else if (unformat (i, "flood"))
1399         flags |= BRIDGE_API_FLAG_FLOOD;
1400       else if (unformat (i, "uu-flood"))
1401         flags |= BRIDGE_API_FLAG_UU_FLOOD;
1402       else if (unformat (i, "arp-term"))
1403         flags |= BRIDGE_API_FLAG_ARP_TERM;
1404       else if (unformat (i, "off"))
1405         is_set = 0;
1406       else if (unformat (i, "disable"))
1407         is_set = 0;
1408       else
1409         break;
1410     }
1411
1412   if (bd_id_set == 0)
1413     {
1414       errmsg ("missing bridge domain");
1415       return -99;
1416     }
1417
1418   M (BRIDGE_FLAGS, mp);
1419
1420   mp->bd_id = ntohl (bd_id);
1421   mp->flags = ntohl (flags);
1422   mp->is_set = is_set;
1423
1424   S (mp);
1425   W (ret);
1426   return ret;
1427 }
1428
1429 #include <vnet/l2/l2.api_test.c>
1430
1431 /*
1432  * Local Variables:
1433  * eval: (c-set-style "gnu")
1434  * End:
1435  */