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