FD.io VPP  v16.09
Vector Packet Processing
l2_bd.c
Go to the documentation of this file.
1 /*
2  * l2_bd.c : layer 2 bridge domain
3  *
4  * Copyright (c) 2013 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vlib/vlib.h>
19 #include <vnet/vnet.h>
20 #include <vlib/cli.h>
21 #include <vnet/ethernet/ethernet.h>
22 #include <vnet/ip/format.h>
23 #include <vnet/l2/l2_input.h>
24 #include <vnet/l2/feat_bitmap.h>
25 #include <vnet/l2/l2_bd.h>
26 #include <vnet/l2/l2_fib.h>
27 #include <vnet/l2/l2_vtr.h>
28 #include <vnet/ip/ip4_packet.h>
29 #include <vnet/ip/ip6_packet.h>
30 
31 #include <vppinfra/error.h>
32 #include <vppinfra/hash.h>
33 #include <vppinfra/vec.h>
34 
36 
37 /**
38  Init bridge domain if not done already.
39  For feature bitmap, set all bits except ARP termination
40 */
41 void
43 {
44  if (!bd_is_valid (bd_config))
45  {
46  bd_config->feature_bitmap = ~L2INPUT_FEAT_ARP_TERM;
47  bd_config->bvi_sw_if_index = ~0;
48  bd_config->members = 0;
49  bd_config->mac_by_ip4 = 0;
50  }
51 }
52 
53 u32
55 {
56  uword *p;
57  u32 rv;
58 
59  if (bd_id == ~0)
60  {
61  bd_id = 0;
62  while (hash_get (bdm->bd_index_by_bd_id, bd_id))
63  bd_id++;
64  }
65  else
66  {
67  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
68  if (p)
69  return (p[0]);
70  }
71 
73 
74  /* mark this index busy */
75  bdm->bd_index_bitmap = clib_bitmap_set (bdm->bd_index_bitmap, rv, 1);
76 
77  hash_set (bdm->bd_index_by_bd_id, bd_id, rv);
78 
80  l2input_main.bd_configs[rv].bd_id = bd_id;
81 
82  return rv;
83 }
84 
85 int
87 {
88  uword *p;
89  u32 bd_index;
90 
91  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
92  if (p == 0)
93  return -1;
94 
95  bd_index = p[0];
96 
97  /* mark this index clear */
98  bdm->bd_index_bitmap = clib_bitmap_set (bdm->bd_index_bitmap, bd_index, 0);
99  hash_unset (bdm->bd_index_by_bd_id, bd_id);
100 
101  l2input_main.bd_configs[bd_index].bd_id = ~0;
102  l2input_main.bd_configs[bd_index].feature_bitmap = 0;
103 
104  return 0;
105 }
106 
107 void
109 {
110  /*
111  * Add one element to the vector
112  *
113  * When flooding, the bvi interface (if present) must be the last member
114  * processed due to how BVI processing can change the packet. To enable
115  * this order, we make the bvi interface the first in the vector and
116  * flooding walks the vector in reverse.
117  */
118  if ((member->flags == L2_FLOOD_MEMBER_NORMAL) ||
119  (vec_len (bd_config->members) == 0))
120  {
121  vec_add1 (bd_config->members, *member);
122 
123  }
124  else
125  {
126  /* Move 0th element to the end */
127  vec_add1 (bd_config->members, bd_config->members[0]);
128  bd_config->members[0] = *member;
129  }
130 }
131 
132 
133 #define BD_REMOVE_ERROR_OK 0
134 #define BD_REMOVE_ERROR_NOT_FOUND 1
135 
136 u32
137 bd_remove_member (l2_bridge_domain_t * bd_config, u32 sw_if_index)
138 {
139  u32 ix;
140 
141  /* Find and delete the member */
142  vec_foreach_index (ix, bd_config->members)
143  {
144  if (vec_elt (bd_config->members, ix).sw_if_index == sw_if_index)
145  {
146  vec_del1 (bd_config->members, ix);
147  return BD_REMOVE_ERROR_OK;
148  }
149  }
150 
152 }
153 
154 
155 clib_error_t *
157 {
158  bd_main_t *bdm = &bd_main;
159  u32 bd_index;
160  bdm->bd_index_by_bd_id = hash_create (0, sizeof (uword));
161  /*
162  * create a dummy bd with bd_id of 0 and bd_index of 0 with feature set
163  * to packet drop only. Thus, packets received from any L2 interface with
164  * uninitialized bd_index of 0 can be dropped safely.
165  */
166  bd_index = bd_find_or_add_bd_index (bdm, 0);
167  ASSERT (bd_index == 0);
168  l2input_main.bd_configs[0].feature_bitmap = L2INPUT_FEAT_DROP;
169  return 0;
170 }
171 
173 
174 
175 /**
176  Set the learn/forward/flood flags for the bridge domain.
177  Return 0 if ok, non-zero if for an error.
178 */
179 u32
180 bd_set_flags (vlib_main_t * vm, u32 bd_index, u32 flags, u32 enable)
181 {
182 
183  l2_bridge_domain_t *bd_config;
184  u32 feature_bitmap = 0;
185 
187  bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
188 
189  bd_validate (bd_config);
190 
191  if (flags & L2_LEARN)
192  {
193  feature_bitmap |= L2INPUT_FEAT_LEARN;
194  }
195  if (flags & L2_FWD)
196  {
197  feature_bitmap |= L2INPUT_FEAT_FWD;
198  }
199  if (flags & L2_FLOOD)
200  {
201  feature_bitmap |= L2INPUT_FEAT_FLOOD;
202  }
203  if (flags & L2_UU_FLOOD)
204  {
205  feature_bitmap |= L2INPUT_FEAT_UU_FLOOD;
206  }
207  if (flags & L2_ARP_TERM)
208  {
209  feature_bitmap |= L2INPUT_FEAT_ARP_TERM;
210  }
211 
212  if (enable)
213  {
214  bd_config->feature_bitmap |= feature_bitmap;
215  }
216  else
217  {
218  bd_config->feature_bitmap &= ~feature_bitmap;
219  }
220 
221  return 0;
222 }
223 
224 /**
225  Set bridge-domain learn enable/disable.
226  The CLI format is:
227  set bridge-domain learn <bd_id> [disable]
228 */
229 static clib_error_t *
231  unformat_input_t * input, vlib_cli_command_t * cmd)
232 {
233  bd_main_t *bdm = &bd_main;
234  clib_error_t *error = 0;
235  u32 bd_index, bd_id;
236  u32 enable;
237  uword *p;
238 
239  if (!unformat (input, "%d", &bd_id))
240  {
241  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
242  format_unformat_error, input);
243  goto done;
244  }
245 
246  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
247 
248  if (p == 0)
249  return clib_error_return (0, "No such bridge domain %d", bd_id);
250 
251  bd_index = p[0];
252 
253  enable = 1;
254  if (unformat (input, "disable"))
255  {
256  enable = 0;
257  }
258 
259  /* set the bridge domain flag */
260  if (bd_set_flags (vm, bd_index, L2_LEARN, enable))
261  {
262  error =
263  clib_error_return (0, "bridge-domain id %d out of range", bd_index);
264  goto done;
265  }
266 
267 done:
268  return error;
269 }
270 
271 /* *INDENT-OFF* */
272 VLIB_CLI_COMMAND (bd_learn_cli, static) = {
273  .path = "set bridge-domain learn",
274  .short_help = "set bridge-domain learn <bridge-domain-id> [disable]",
275  .function = bd_learn,
276 };
277 /* *INDENT-ON* */
278 
279 /**
280  Set bridge-domain forward enable/disable.
281  The CLI format is:
282  set bridge-domain forward <bd_index> [disable]
283 */
284 static clib_error_t *
286 {
287  bd_main_t *bdm = &bd_main;
288  clib_error_t *error = 0;
289  u32 bd_index, bd_id;
290  u32 enable;
291  uword *p;
292 
293  if (!unformat (input, "%d", &bd_id))
294  {
295  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
296  format_unformat_error, input);
297  goto done;
298  }
299 
300  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
301 
302  if (p == 0)
303  return clib_error_return (0, "No such bridge domain %d", bd_id);
304 
305  bd_index = p[0];
306 
307  enable = 1;
308  if (unformat (input, "disable"))
309  {
310  enable = 0;
311  }
312 
313  /* set the bridge domain flag */
314  if (bd_set_flags (vm, bd_index, L2_FWD, enable))
315  {
316  error =
317  clib_error_return (0, "bridge-domain id %d out of range", bd_index);
318  goto done;
319  }
320 
321 done:
322  return error;
323 }
324 
325 /* *INDENT-OFF* */
326 VLIB_CLI_COMMAND (bd_fwd_cli, static) = {
327  .path = "set bridge-domain forward",
328  .short_help = "set bridge-domain forward <bridge-domain-id> [disable]",
329  .function = bd_fwd,
330 };
331 /* *INDENT-ON* */
332 
333 /**
334  Set bridge-domain flood enable/disable.
335  The CLI format is:
336  set bridge-domain flood <bd_index> [disable]
337 */
338 static clib_error_t *
340  unformat_input_t * input, vlib_cli_command_t * cmd)
341 {
342  bd_main_t *bdm = &bd_main;
343  clib_error_t *error = 0;
344  u32 bd_index, bd_id;
345  u32 enable;
346  uword *p;
347 
348  if (!unformat (input, "%d", &bd_id))
349  {
350  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
351  format_unformat_error, input);
352  goto done;
353  }
354 
355  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
356 
357  if (p == 0)
358  return clib_error_return (0, "No such bridge domain %d", bd_id);
359 
360  bd_index = p[0];
361 
362  enable = 1;
363  if (unformat (input, "disable"))
364  {
365  enable = 0;
366  }
367 
368  /* set the bridge domain flag */
369  if (bd_set_flags (vm, bd_index, L2_FLOOD, enable))
370  {
371  error =
372  clib_error_return (0, "bridge-domain id %d out of range", bd_index);
373  goto done;
374  }
375 
376 done:
377  return error;
378 }
379 
380 /* *INDENT-OFF* */
381 VLIB_CLI_COMMAND (bd_flood_cli, static) = {
382  .path = "set bridge-domain flood",
383  .short_help = "set bridge-domain flood <bridge-domain-id> [disable]",
384  .function = bd_flood,
385 };
386 /* *INDENT-ON* */
387 
388 /**
389  Set bridge-domain unkown-unicast flood enable/disable.
390  The CLI format is:
391  set bridge-domain uu-flood <bd_index> [disable]
392 */
393 static clib_error_t *
395  unformat_input_t * input, vlib_cli_command_t * cmd)
396 {
397  bd_main_t *bdm = &bd_main;
398  clib_error_t *error = 0;
399  u32 bd_index, bd_id;
400  u32 enable;
401  uword *p;
402 
403  if (!unformat (input, "%d", &bd_id))
404  {
405  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
406  format_unformat_error, input);
407  goto done;
408  }
409 
410  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
411 
412  if (p == 0)
413  return clib_error_return (0, "No such bridge domain %d", bd_id);
414 
415  bd_index = p[0];
416 
417  enable = 1;
418  if (unformat (input, "disable"))
419  {
420  enable = 0;
421  }
422 
423  /* set the bridge domain flag */
424  if (bd_set_flags (vm, bd_index, L2_UU_FLOOD, enable))
425  {
426  error =
427  clib_error_return (0, "bridge-domain id %d out of range", bd_index);
428  goto done;
429  }
430 
431 done:
432  return error;
433 }
434 
435 /* *INDENT-OFF* */
436 VLIB_CLI_COMMAND (bd_uu_flood_cli, static) = {
437  .path = "set bridge-domain uu-flood",
438  .short_help = "set bridge-domain uu-flood <bridge-domain-id> [disable]",
439  .function = bd_uu_flood,
440 };
441 /* *INDENT-ON* */
442 
443 /**
444  Set bridge-domain arp term enable/disable.
445  The CLI format is:
446  set bridge-domain arp term <bridge-domain-id> [disable]
447 */
448 static clib_error_t *
450  unformat_input_t * input, vlib_cli_command_t * cmd)
451 {
452  bd_main_t *bdm = &bd_main;
453  clib_error_t *error = 0;
454  u32 bd_index, bd_id;
455  u32 enable;
456  uword *p;
457 
458  if (!unformat (input, "%d", &bd_id))
459  {
460  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
461  format_unformat_error, input);
462  goto done;
463  }
464 
465  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
466  if (p)
467  bd_index = *p;
468  else
469  return clib_error_return (0, "No such bridge domain %d", bd_id);
470 
471  enable = 1;
472  if (unformat (input, "disable"))
473  enable = 0;
474 
475  /* set the bridge domain flag */
476  if (bd_set_flags (vm, bd_index, L2_ARP_TERM, enable))
477  {
478  error =
479  clib_error_return (0, "bridge-domain id %d out of range", bd_index);
480  goto done;
481  }
482 
483 done:
484  return error;
485 }
486 
487 /* *INDENT-OFF* */
488 VLIB_CLI_COMMAND (bd_arp_term_cli, static) = {
489  .path = "set bridge-domain arp term",
490  .short_help = "set bridge-domain arp term <bridge-domain-id> [disable]",
491  .function = bd_arp_term,
492 };
493 /* *INDENT-ON* */
494 
495 
496 /**
497  * Add/delete IP address to MAC address mapping.
498  *
499  * The clib hash implementation stores uword entries in the hash table.
500  * The hash table mac_by_ip4 is keyed via IP4 address and store the
501  * 6-byte MAC address directly in the hash table entry uword.
502  *
503  * @warning This only works for 64-bit processor with 8-byte uword;
504  * which means this code *WILL NOT WORK* for a 32-bit prcessor with
505  * 4-byte uword.
506  */
507 u32
509  u8 * ip_addr, u8 * mac_addr, u8 is_ip6, u8 is_add)
510 {
511  l2input_main_t *l2im = &l2input_main;
512  l2_bridge_domain_t *bd_cfg = l2input_bd_config_from_index (l2im, bd_index);
513  u64 new_mac = *(u64 *) mac_addr;
514  u64 *old_mac;
515  u16 *mac16 = (u16 *) & new_mac;
516 
517  ASSERT (sizeof (uword) == sizeof (u64)); /* make sure uword is 8 bytes */
518 
519  mac16[3] = 0; // Clear last 2 unsed bytes of the 8-byte MAC address
520  if (is_ip6)
521  {
522  /* not yet implemented */
523  return 1;
524  }
525  else
526  {
527  ip4_address_t ip4_addr = *(ip4_address_t *) ip_addr;
528  old_mac = (u64 *) hash_get (bd_cfg->mac_by_ip4, ip4_addr.as_u32);
529  if (is_add)
530  {
531  /* mac entry already exist? */
532  if (old_mac && (*old_mac == new_mac))
533  return 0;
534  hash_set (bd_cfg->mac_by_ip4, ip4_addr.as_u32, new_mac);
535  }
536  else
537  {
538  /* Mac entry match? */
539  if (old_mac && (*old_mac == new_mac))
540  {
541  /* clear entry */
542  hash_unset (bd_cfg->mac_by_ip4, ip4_addr.as_u32);
543  }
544  else
545  {
546  return 1;
547  }
548  }
549  return 0;
550  }
551 }
552 
553 /**
554  Set bridge-domain arp entry add/delete.
555  The CLI format is:
556  set bridge-domain arp entry <bd-id> <ip-addr> <mac-addr> [del]
557 */
558 static clib_error_t *
560  unformat_input_t * input, vlib_cli_command_t * cmd)
561 {
562  bd_main_t *bdm = &bd_main;
563  clib_error_t *error = 0;
564  u32 bd_index, bd_id;
565  u8 is_add = 1;
566  u8 is_ip6 = 0;
567  u8 ip_addr[16];
568  u8 mac_addr[6];
569  uword *p;
570 
571  if (!unformat (input, "%d", &bd_id))
572  {
573  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
574  format_unformat_error, input);
575  goto done;
576  }
577 
578  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
579 
580  if (p)
581  bd_index = *p;
582  else
583  return clib_error_return (0, "No such bridge domain %d", bd_id);
584 
585  if (unformat (input, "%U", unformat_ip4_address, ip_addr))
586  {
587  is_ip6 = 0;
588  }
589  else if (unformat (input, "%U", unformat_ip6_address, ip_addr))
590  {
591  is_ip6 = 1;
592  }
593  else
594  {
595  error = clib_error_return (0, "expecting IP address but got `%U'",
596  format_unformat_error, input);
597  goto done;
598  }
599 
600  if (!unformat (input, "%U", unformat_ethernet_address, mac_addr))
601  {
602  error = clib_error_return (0, "expecting MAC address but got `%U'",
603  format_unformat_error, input);
604  goto done;
605  }
606 
607  if (unformat (input, "del"))
608  {
609  is_add = 0;
610  }
611 
612  /* set the bridge domain flagAdd IP-MAC entry into bridge domain */
613  if (bd_add_del_ip_mac (bd_index, ip_addr, mac_addr, is_ip6, is_add))
614  {
615  error = clib_error_return (0, "MAC %s for IP %U and MAC %U failed",
616  is_add ? "add" : "del",
617  format_ip4_address, ip_addr,
618  format_ethernet_address, mac_addr);
619  }
620 
621 done:
622  return error;
623 }
624 
625 /* *INDENT-OFF* */
626 VLIB_CLI_COMMAND (bd_arp_entry_cli, static) = {
627  .path = "set bridge-domain arp entry",
628  .short_help = "set bridge-domain arp entry <bd-id> <ip-addr> <mac-addr> [del]",
629  .function = bd_arp_entry,
630 };
631 /* *INDENT-ON* */
632 
633 u8 *
634 format_vtr (u8 * s, va_list * args)
635 {
636  u32 vtr_op = va_arg (*args, u32);
637  u32 dot1q = va_arg (*args, u32);
638  u32 tag1 = va_arg (*args, u32);
639  u32 tag2 = va_arg (*args, u32);
640  switch (vtr_op)
641  {
642  case L2_VTR_DISABLED:
643  return format (s, "none");
644  case L2_VTR_PUSH_1:
645  return format (s, "push-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1);
646  case L2_VTR_PUSH_2:
647  return format (s, "push-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", tag1,
648  tag2);
649  case L2_VTR_POP_1:
650  return format (s, "pop-1");
651  case L2_VTR_POP_2:
652  return format (s, "pop-2");
654  return format (s, "trans-1-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1);
656  return format (s, "trans-1-2 %s %d %d", dot1q ? "dot1q" : "dot1ad",
657  tag1, tag2);
659  return format (s, "trans-2-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1);
661  return format (s, "trans-2-2 %s %d %d", dot1q ? "dot1q" : "dot1ad",
662  tag1, tag2);
663  default:
664  return format (s, "none");
665  }
666 }
667 
668 /**
669  Show bridge-domain state.
670  The CLI format is:
671  show bridge-domain [<bd_index>]
672 */
673 static clib_error_t *
675 {
676  vnet_main_t *vnm = vnet_get_main ();
677  bd_main_t *bdm = &bd_main;
678  clib_error_t *error = 0;
679  u32 bd_index = ~0;
680  l2_bridge_domain_t *bd_config;
681  u32 start, end;
682  u32 printed;
683  u32 detail = 0;
684  u32 intf = 0;
685  u32 arp = 0;
686  u32 bd_id = ~0;
687  uword *p;
688 
689  start = 0;
691 
692  if (unformat (input, "%d", &bd_id))
693  {
694  if (unformat (input, "detail"))
695  detail = 1;
696  else if (unformat (input, "det"))
697  detail = 1;
698  if (unformat (input, "int"))
699  intf = 1;
700  if (unformat (input, "arp"))
701  arp = 1;
702 
703  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
704  if (p)
705  bd_index = *p;
706  else
707  return clib_error_return (0, "No such bridge domain %d", bd_id);
708 
710  bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
711  if (bd_is_valid (bd_config))
712  {
713  start = bd_index;
714  end = start + 1;
715  }
716  else
717  {
718  vlib_cli_output (vm, "bridge-domain %d not in use", bd_id);
719  goto done;
720  }
721  }
722 
723  /* Show all bridge-domains that have been initialized */
724  printed = 0;
725  for (bd_index = start; bd_index < end; bd_index++)
726  {
727  bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
728  if (bd_is_valid (bd_config))
729  {
730  if (!printed)
731  {
732  printed = 1;
733  vlib_cli_output (vm,
734  "%=5s %=7s %=10s %=10s %=10s %=10s %=10s %=14s",
735  "ID", "Index", "Learning", "U-Forwrd",
736  "UU-Flood", "Flooding", "ARP-Term",
737  "BVI-Intf");
738  }
739 
740  vlib_cli_output (vm,
741  "%=5d %=7d %=10s %=10s %=10s %=10s %=10s %=14U",
742  bd_config->bd_id, bd_index,
743  bd_config->feature_bitmap & L2INPUT_FEAT_LEARN ?
744  "on" : "off",
745  bd_config->feature_bitmap & L2INPUT_FEAT_FWD ? "on"
746  : "off",
747  bd_config->feature_bitmap & L2INPUT_FEAT_UU_FLOOD ?
748  "on" : "off",
749  bd_config->feature_bitmap & L2INPUT_FEAT_FLOOD ?
750  "on" : "off",
751  bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM ?
753  vnm, bd_config->bvi_sw_if_index);
754 
755  if (detail || intf)
756  {
757  /* Show all member interfaces */
758 
759  l2_flood_member_t *member;
760  u32 header = 0;
761 
762  vec_foreach (member, bd_config->members)
763  {
764  u32 vtr_opr, dot1q, tag1, tag2;
765  if (!header)
766  {
767  header = 1;
768  vlib_cli_output (vm, "\n%=30s%=7s%=5s%=5s%=30s",
769  "Interface", "Index", "SHG", "BVI",
770  "VLAN-Tag-Rewrite");
771  }
772  l2vtr_get (vm, vnm, member->sw_if_index, &vtr_opr, &dot1q,
773  &tag1, &tag2);
774  vlib_cli_output (vm, "%=30U%=7d%=5d%=5s%=30U",
776  member->sw_if_index, member->sw_if_index,
777  member->shg,
778  member->flags & L2_FLOOD_MEMBER_BVI ? "*" :
779  "-", format_vtr, vtr_opr, dot1q, tag1, tag2);
780  }
781  }
782 
783  if ((detail || arp) &&
784  (bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM))
785  {
786  u32 ip4_addr;
787  u64 mac_addr;
788  vlib_cli_output (vm,
789  "\n IP4 to MAC table for ARP Termination");
790 
791  /* *INDENT-OFF* */
792  hash_foreach (ip4_addr, mac_addr, bd_config->mac_by_ip4,
793  ({
794  vlib_cli_output (vm, "%=20U => %=20U",
795  format_ip4_address, &ip4_addr,
796  format_ethernet_address, &mac_addr);
797  }));
798  /* *INDENT-ON* */
799  }
800  }
801  }
802 
803  if (!printed)
804  {
805  vlib_cli_output (vm, "no bridge-domains in use");
806  }
807 
808 done:
809  return error;
810 }
811 
812 /* *INDENT-OFF* */
813 VLIB_CLI_COMMAND (bd_show_cli, static) = {
814  .path = "show bridge-domain",
815  .short_help = "show bridge-domain [bridge-domain-id [detail|int|arp]]",
816  .function = bd_show,
817 };
818 /* *INDENT-ON* */
819 
820 /*
821  * fd.io coding-style-patch-verification: ON
822  *
823  * Local Variables:
824  * eval: (c-set-style "gnu")
825  * End:
826  */
void bd_validate(l2_bridge_domain_t *bd_config)
Init bridge domain if not done already.
Definition: l2_bd.c:42
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:396
u32 bd_set_flags(vlib_main_t *vm, u32 bd_index, u32 flags, u32 enable)
Set the learn/forward/flood flags for the bridge domain.
Definition: l2_bd.c:180
#define vec_foreach_index(var, v)
Iterate over vector indices.
#define hash_set(h, key, value)
Definition: hash.h:254
#define L2_FLOOD_MEMBER_NORMAL
Definition: l2_bd.h:41
u8 * format_vnet_sw_if_index_name_with_NA(u8 *s, va_list *args)
Format sw_if_index.
Definition: l2_fib.c:49
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
#define hash_unset(h, key)
Definition: hash.h:260
u32 bvi_sw_if_index
Definition: l2_bd.h:65
#define L2_FLOOD
Definition: l2_bd.h:98
#define L2_FWD
Definition: l2_bd.h:97
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
l2_flood_member_t * members
Definition: l2_bd.h:71
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
u32 bd_remove_member(l2_bridge_domain_t *bd_config, u32 sw_if_index)
Definition: l2_bd.c:137
#define L2_FLOOD_MEMBER_BVI
Definition: l2_bd.h:42
format_function_t format_ip4_address
Definition: format.h:71
format_function_t format_vnet_sw_if_index_name
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
int bd_delete_bd_index(bd_main_t *bdm, u32 bd_id)
Delete a bridge domain.
Definition: l2_bd.c:86
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
void bd_add_member(l2_bridge_domain_t *bd_config, l2_flood_member_t *member)
Definition: l2_bd.c:108
static clib_error_t * bd_fwd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set bridge-domain forward enable/disable.
Definition: l2_bd.c:285
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:407
clib_error_t * l2bd_init(vlib_main_t *vm)
Definition: l2_bd.c:156
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define L2_UU_FLOOD
Definition: l2_bd.h:99
unsigned long u64
Definition: types.h:89
uword * bd_index_by_bd_id
Definition: l2_bd.h:27
unformat_function_t unformat_ip4_address
Definition: format.h:68
#define BD_REMOVE_ERROR_OK
Definition: l2_bd.c:133
#define hash_get(h, key)
Definition: hash.h:248
static clib_error_t * bd_arp_entry(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set bridge-domain arp entry add/delete.
Definition: l2_bd.c:559
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:765
static clib_error_t * bd_flood(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set bridge-domain flood enable/disable.
Definition: l2_bd.c:339
uword * bd_index_bitmap
Definition: l2_bd.h:30
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
static u32 bd_is_valid(l2_bridge_domain_t *bd_config)
Definition: l2_bd.h:81
unformat_function_t unformat_ip6_address
Definition: format.h:86
#define BD_REMOVE_ERROR_NOT_FOUND
Definition: l2_bd.c:134
u32 bd_add_del_ip_mac(u32 bd_index, u8 *ip_addr, u8 *mac_addr, u8 is_ip6, u8 is_add)
Add/delete IP address to MAC address mapping.
Definition: l2_bd.c:508
static clib_error_t * bd_learn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set bridge-domain learn enable/disable.
Definition: l2_bd.c:230
static clib_error_t * bd_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Show bridge-domain state.
Definition: l2_bd.c:674
#define hash_create(elts, value_bytes)
Definition: hash.h:647
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:206
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
static_always_inline l2_bridge_domain_t * l2input_bd_config_from_index(l2input_main_t *l2im, u32 bd_index)
Definition: l2_input.h:81
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
static clib_error_t * bd_arp_term(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set bridge-domain arp term enable/disable.
Definition: l2_bd.c:449
u64 uword
Definition: types.h:112
#define vec_elt(v, i)
Get vector value at index i.
unsigned short u16
Definition: types.h:57
l2input_main_t l2input_main
Definition: l2_input.c:76
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
u32 bd_find_or_add_bd_index(bd_main_t *bdm, u32 bd_id)
Get or create a bridge domain.
Definition: l2_bd.c:54
u32 feature_bitmap
Definition: l2_bd.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
#define L2_ARP_TERM
Definition: l2_bd.h:100
l2_bridge_domain_t * bd_configs
Definition: l2_input.h:69
static clib_error_t * bd_uu_flood(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set bridge-domain unkown-unicast flood enable/disable.
Definition: l2_bd.c:394
u8 * format_vtr(u8 *s, va_list *args)
Definition: l2_bd.c:634
u32 l2vtr_get(vlib_main_t *vlib_main, vnet_main_t *vnet_main, u32 sw_if_index, u32 *vtr_op, u32 *push_dot1q, u32 *vtr_tag1, u32 *vtr_tag2)
Get vtag tag rewrite on the given interface.
Definition: l2_vtr.c:261
#define vec_foreach(var, vec)
Vector iterator.
uword * mac_by_ip4
Definition: l2_bd.h:74
u32 sw_if_index
Definition: l2_bd.h:46
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t
static uword clib_bitmap_first_clear(uword *ai)
Return the lowest numbered clear bit in a bitmap.
Definition: bitmap.h:424
u32 flags
Definition: vhost-user.h:76
bd_main_t bd_main
Definition: l2_bd.c:35
#define L2_LEARN
Definition: l2_bd.h:96
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".