blob: b78e388a9f1292b979a8cb56627a30a8db437f4f [file] [log] [blame]
Filip Tehlar1b6fb402021-07-24 18:10:39 +00001/* SPDX-License-Identifier: Apache-2.0
2 * Copyright(c) 2021 Cisco Systems, Inc.
Laszlo Kiraly0f8f4352022-09-16 13:20:07 +02003 * Copyright(c) 2022 Nordix Foundation.
Filip Tehlar1b6fb402021-07-24 18:10:39 +00004 */
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
Klement Sekera9b7e8ac2021-11-22 21:26:20 +010032#define vl_calcsizefun
33#include <vnet/l2/l2.api.h>
34#undef vl_calcsizefun
35
Filip Tehlar1b6fb402021-07-24 18:10:39 +000036typedef 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
44static l2_test_main_t l2_test_main;
45
46static void
47vl_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
57static int
58api_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
98static void
99vl_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
106static int
107api_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
130static int
131api_want_l2_arp_term_events (vat_main_t *vam)
132{
133 return -1;
134}
135
136static int
137api_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
172static int
173api_l2fib_flush_all (vat_main_t *vam)
174{
175 return -1;
176}
177
178static void
179increment_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
189static int
190api_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;
Damjan Marion60706a22021-10-31 19:21:31 +0100196 u8 mac[8] = { 0 };
Filip Tehlar1b6fb402021-07-24 18:10:39 +0000197 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
340static int
341api_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
376static int
377api_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
389static int
390api_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
431static int
432api_l2fib_set_scan_delay (vat_main_t *vam)
433{
434 return -1;
435}
436
437static int
438api_want_l2_macs_events2 (vat_main_t *vam)
439{
440 return -1;
441}
442
443static int
444api_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
506static void
507vl_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
522static int
523api_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
554static int
555api_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
633done:
634 vec_free (bd_tag);
635 return ret;
636}
637
Laszlo Kiraly0f8f4352022-09-16 13:20:07 +0200638static int
639api_bridge_domain_add_del_v2 (vat_main_t *vam)
640{
641 return -1;
642}
643
644static void
645vl_api_bridge_domain_add_del_v2_reply_t_handler (
646 vl_api_bridge_domain_add_del_v2_reply_t *mp)
647{
648}
649
Filip Tehlar1b6fb402021-07-24 18:10:39 +0000650#define foreach_pbb_vtr_op \
651 _ ("disable", L2_VTR_DISABLED) \
652 _ ("pop", L2_VTR_POP_2) \
653 _ ("push", L2_VTR_PUSH_2)
654
655static int
656api_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
740static int
741api_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
813static int
814api_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
857static void
858vl_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
867static void
868vl_api_bvi_create_reply_t_handler (vl_api_bvi_create_reply_t *mp)
869{
870}
871
872static int
873api_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
938static int
939api_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
984static int
985api_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
1055static void
1056vl_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
1082static int
1083api_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
1141static int
1142api_bridge_domain_set_learn_limit (vat_main_t *vam)
1143{
1144 return -1;
1145}
1146
1147static int
1148api_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
1211static void
1212vl_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
1255static int
1256api_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
1285static int
1286api_bridge_domain_set_default_learn_limit (vat_main_t *vam)
1287{
1288 return -1;
1289}
1290
1291static int
1292api_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
1325static int
1326api_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
1366static int
1367api_bvi_create (vat_main_t *vam)
1368{
1369 return -1;
1370}
1371
1372static int
1373api_bvi_delete (vat_main_t *vam)
1374{
1375 return -1;
1376}
1377
1378static int
1379api_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 */