FD.io VPP  v21.01.1
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_learn.h>
27 #include <vnet/l2/l2_fib.h>
28 #include <vnet/l2/l2_vtr.h>
29 #include <vnet/ip/ip4_packet.h>
30 #include <vnet/ip/ip6_packet.h>
31 
32 #include <vppinfra/error.h>
33 #include <vppinfra/hash.h>
34 #include <vppinfra/vec.h>
35 
36 /**
37  * @file
38  * @brief Ethernet Bridge Domain.
39  *
40  * Code in this file manages Layer 2 bridge domains.
41  *
42  */
43 
45 
46 /**
47  Init bridge domain if not done already.
48  For feature bitmap, set all bits except ARP termination
49 */
50 void
52 {
53  if (bd_is_valid (bd_config))
54  return;
55  bd_config->feature_bitmap =
56  ~(L2INPUT_FEAT_ARP_TERM | L2INPUT_FEAT_UU_FWD | L2INPUT_FEAT_ARP_UFWD);
57  bd_config->bvi_sw_if_index = ~0;
58  bd_config->uu_fwd_sw_if_index = ~0;
59  bd_config->members = 0;
60  bd_config->flood_count = 0;
61  bd_config->tun_master_count = 0;
62  bd_config->tun_normal_count = 0;
63  bd_config->no_flood_count = 0;
64  bd_config->mac_by_ip4 = 0;
65  bd_config->mac_by_ip6 = hash_create_mem (0, sizeof (ip6_address_t),
66  sizeof (uword));
67 }
68 
69 u32
71 {
72  u32 *p = (u32 *) hash_get (bdm->bd_index_by_bd_id, bd_id);
73  if (!p)
74  return ~0;
75  return p[0];
76 }
77 
78 u32
80 {
81  ASSERT (!hash_get (bdm->bd_index_by_bd_id, bd_id));
83 
84  /* mark this index taken */
85  bdm->bd_index_bitmap = clib_bitmap_set (bdm->bd_index_bitmap, rv, 1);
86 
87  hash_set (bdm->bd_index_by_bd_id, bd_id, rv);
88 
91 
92  return rv;
93 }
94 
95 static inline void
97 {
98  u64 mac_addr;
99  ip6_address_t *ip6_addr_key;
100 
101  hash_free (bd->mac_by_ip4);
102  /* *INDENT-OFF* */
103  hash_foreach_mem (ip6_addr_key, mac_addr, bd->mac_by_ip6,
104  ({
105  clib_mem_free (ip6_addr_key); /* free memory used for ip6 addr key */
106  }));
107  /* *INDENT-ON* */
108  hash_free (bd->mac_by_ip6);
109 }
110 
111 static int
112 bd_delete (bd_main_t * bdm, u32 bd_index)
113 {
114  l2_bridge_domain_t *bd = &l2input_main.bd_configs[bd_index];
115  u32 bd_id = bd->bd_id;
116 
117  /* flush non-static MACs in BD and removed bd_id from hash table */
118  l2fib_flush_bd_mac (vlib_get_main (), bd_index);
119  hash_unset (bdm->bd_index_by_bd_id, bd_id);
120 
121  /* mark this index clear */
122  bdm->bd_index_bitmap = clib_bitmap_set (bdm->bd_index_bitmap, bd_index, 0);
123 
124  /* clear BD config for reuse: bd_id to -1 and clear feature_bitmap */
125  bd->bd_id = ~0;
126  bd->feature_bitmap = 0;
127 
128  /* free BD tag */
129  vec_free (bd->bd_tag);
130 
131  /* free memory used by BD */
132  vec_free (bd->members);
134 
135  return 0;
136 }
137 
138 static void
140 {
141  bd_config->flood_count = (vec_len (bd_config->members) -
142  (bd_config->tun_master_count ?
143  bd_config->tun_normal_count : 0));
144  bd_config->flood_count -= bd_config->no_flood_count;
145 }
146 
147 void
149 {
150  u32 ix = 0;
152  (vnet_get_main (), member->sw_if_index);
153 
154  /*
155  * Add one element to the vector
156  * vector is ordered [ bvi, normal/tun_masters..., tun_normals... no_flood]
157  * When flooding, the bvi interface (if present) must be the last member
158  * processed due to how BVI processing can change the packet. To enable
159  * this order, we make the bvi interface the first in the vector and
160  * flooding walks the vector in reverse. The flood-count determines where
161  * in the member list to start the walk from.
162  */
163  switch (sw_if->flood_class)
164  {
166  bd_config->no_flood_count++;
167  ix = vec_len (bd_config->members);
168  break;
170  ix = 0;
171  break;
173  bd_config->tun_master_count++;
174  /* Fall through */
176  ix = (vec_len (bd_config->members) -
177  bd_config->tun_normal_count - bd_config->no_flood_count);
178  break;
180  ix = (vec_len (bd_config->members) - bd_config->no_flood_count);
181  bd_config->tun_normal_count++;
182  break;
183  }
184 
185  vec_insert_elts (bd_config->members, member, 1, ix);
186  update_flood_count (bd_config);
187 }
188 
189 #define BD_REMOVE_ERROR_OK 0
190 #define BD_REMOVE_ERROR_NOT_FOUND 1
191 
192 u32
194 {
195  u32 ix;
196 
197  /* Find and delete the member */
198  vec_foreach_index (ix, bd_config->members)
199  {
200  l2_flood_member_t *m = vec_elt_at_index (bd_config->members, ix);
201  if (m->sw_if_index == sw_if_index)
202  {
204  (vnet_get_main (), sw_if_index);
205 
206  if (sw_if->flood_class != VNET_FLOOD_CLASS_NORMAL)
207  {
209  bd_config->tun_master_count--;
210  else if (sw_if->flood_class == VNET_FLOOD_CLASS_TUNNEL_NORMAL)
211  bd_config->tun_normal_count--;
212  else if (sw_if->flood_class == VNET_FLOOD_CLASS_NO_FLOOD)
213  bd_config->no_flood_count--;
214  }
215  vec_delete (bd_config->members, 1, ix);
216  update_flood_count (bd_config);
217 
218  return BD_REMOVE_ERROR_OK;
219  }
220  }
221 
223 }
224 
225 
226 clib_error_t *
228 {
229  bd_main_t *bdm = &bd_main;
230  bdm->bd_index_by_bd_id = hash_create (0, sizeof (uword));
231  /*
232  * create a placeholder bd with bd_id of 0 and bd_index of 0 with feature set
233  * to packet drop only. Thus, packets received from any L2 interface with
234  * uninitialized bd_index of 0 can be dropped safely.
235  */
236  u32 bd_index = bd_add_bd_index (bdm, 0);
237  ASSERT (bd_index == 0);
238  l2input_main.bd_configs[0].feature_bitmap = L2INPUT_FEAT_DROP;
239 
240  bdm->vlib_main = vm;
241  return 0;
242 }
243 
245 
247 bd_get (u32 bd_index)
248 {
249  if (bd_index < vec_len (l2input_main.bd_configs))
250  return (vec_elt_at_index (l2input_main.bd_configs, bd_index));
251  return (NULL);
252 }
253 
254 u32
256 {
257  l2_flood_member_t *member;
258  l2_bridge_domain_t *bd;
260 
261  sw_if_index = ~0;
262  bd = bd_get (bd_index);
263 
264  ASSERT (bd);
265 
266  vec_foreach (member, bd->members)
267  {
268  if (WALK_STOP == fn (bd_index, member->sw_if_index))
269  {
270  sw_if_index = member->sw_if_index;
271  break;
272  }
273  }
274 
275  return (sw_if_index);
276 }
277 
278 static void
280 {
281  bd_input_walk (bd_index, l2input_recache, NULL);
282 }
283 
284 /**
285  Set the learn/forward/flood flags for the bridge domain.
286  Return 0 if ok, non-zero if for an error.
287 */
288 u32
290 {
291 
292  l2_bridge_domain_t *bd_config = l2input_bd_config (bd_index);
293  bd_validate (bd_config);
294  u32 feature_bitmap = 0;
295 
296  if (flags & L2_LEARN)
297  {
298  feature_bitmap |= L2INPUT_FEAT_LEARN;
299  }
300  if (flags & L2_FWD)
301  {
302  feature_bitmap |= L2INPUT_FEAT_FWD;
303  }
304  if (flags & L2_FLOOD)
305  {
306  feature_bitmap |= L2INPUT_FEAT_FLOOD;
307  }
308  if (flags & L2_UU_FLOOD)
309  {
310  feature_bitmap |= L2INPUT_FEAT_UU_FLOOD;
311  }
312  if (flags & L2_ARP_TERM)
313  {
314  feature_bitmap |= L2INPUT_FEAT_ARP_TERM;
315  }
316  if (flags & L2_ARP_UFWD)
317  {
318  feature_bitmap |= L2INPUT_FEAT_ARP_UFWD;
319  }
320 
321  if (enable)
322  {
323  bd_config->feature_bitmap |= feature_bitmap;
324  }
325  else
326  {
327  bd_config->feature_bitmap &= ~feature_bitmap;
328  }
329 
330  b2_input_recache (bd_index);
331 
332  return bd_config->feature_bitmap;
333 }
334 
335 /**
336  Set the mac age for the bridge domain.
337 */
338 void
339 bd_set_mac_age (vlib_main_t * vm, u32 bd_index, u8 age)
340 {
341  l2_bridge_domain_t *bd_config;
342  int enable = 0;
343 
345  bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
346  bd_config->mac_age = age;
347  b2_input_recache (bd_index);
348 
349  /* check if there is at least one bd with mac aging enabled */
350  vec_foreach (bd_config, l2input_main.bd_configs)
351  enable |= bd_config->bd_id != ~0 && bd_config->mac_age != 0;
352 
356 }
357 
358 /**
359  Set the tag for the bridge domain.
360 */
361 
362 static void
363 bd_set_bd_tag (vlib_main_t * vm, u32 bd_index, u8 * bd_tag)
364 {
365  u8 *old;
366  l2_bridge_domain_t *bd_config;
368  bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
369 
370  old = bd_config->bd_tag;
371 
372  if (bd_tag[0])
373  {
374  bd_config->bd_tag = format (0, "%s%c", bd_tag, 0);
375  }
376  else
377  {
378  bd_config->bd_tag = NULL;
379  }
380 
381  vec_free (old);
382 }
383 
384 /**
385  Set bridge-domain learn enable/disable.
386  The CLI format is:
387  set bridge-domain learn <bd_id> [disable]
388 */
389 static clib_error_t *
391  unformat_input_t * input, vlib_cli_command_t * cmd)
392 {
393  bd_main_t *bdm = &bd_main;
394  clib_error_t *error = 0;
395  u32 bd_index, bd_id;
396  u32 enable;
397  uword *p;
398 
399  if (!unformat (input, "%d", &bd_id))
400  {
401  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
402  format_unformat_error, input);
403  goto done;
404  }
405 
406  if (bd_id == 0)
407  return clib_error_return (0,
408  "No operations on the default bridge domain are supported");
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  bd_set_flags (vm, bd_index, L2_LEARN, enable);
425 
426 done:
427  return error;
428 }
429 
430 /*?
431  * Layer 2 learning can be enabled and disabled on each
432  * interface and on each bridge-domain. Use this command to
433  * manage bridge-domains. It is enabled by default.
434  *
435  * @cliexpar
436  * Example of how to enable learning (where 200 is the bridge-domain-id):
437  * @cliexcmd{set bridge-domain learn 200}
438  * Example of how to disable learning (where 200 is the bridge-domain-id):
439  * @cliexcmd{set bridge-domain learn 200 disable}
440 ?*/
441 /* *INDENT-OFF* */
442 VLIB_CLI_COMMAND (bd_learn_cli, static) = {
443  .path = "set bridge-domain learn",
444  .short_help = "set bridge-domain learn <bridge-domain-id> [disable]",
445  .function = bd_learn,
446 };
447 /* *INDENT-ON* */
448 
449 /**
450  Set bridge-domain forward enable/disable.
451  The CLI format is:
452  set bridge-domain forward <bd_index> [disable]
453 */
454 static clib_error_t *
456 {
457  bd_main_t *bdm = &bd_main;
458  clib_error_t *error = 0;
459  u32 bd_index, bd_id;
460  u32 enable;
461  uword *p;
462 
463  if (!unformat (input, "%d", &bd_id))
464  {
465  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
466  format_unformat_error, input);
467  goto done;
468  }
469 
470  if (bd_id == 0)
471  return clib_error_return (0,
472  "No operations on the default bridge domain are supported");
473 
474  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
475 
476  if (p == 0)
477  return clib_error_return (0, "No such bridge domain %d", bd_id);
478 
479  bd_index = p[0];
480 
481  enable = 1;
482  if (unformat (input, "disable"))
483  {
484  enable = 0;
485  }
486 
487  /* set the bridge domain flag */
488  bd_set_flags (vm, bd_index, L2_FWD, enable);
489 
490 done:
491  return error;
492 }
493 
494 
495 /*?
496  * Layer 2 unicast forwarding can be enabled and disabled on each
497  * interface and on each bridge-domain. Use this command to
498  * manage bridge-domains. It is enabled by default.
499  *
500  * @cliexpar
501  * Example of how to enable forwarding (where 200 is the bridge-domain-id):
502  * @cliexcmd{set bridge-domain forward 200}
503  * Example of how to disable forwarding (where 200 is the bridge-domain-id):
504  * @cliexcmd{set bridge-domain forward 200 disable}
505 ?*/
506 /* *INDENT-OFF* */
507 VLIB_CLI_COMMAND (bd_fwd_cli, static) = {
508  .path = "set bridge-domain forward",
509  .short_help = "set bridge-domain forward <bridge-domain-id> [disable]",
510  .function = bd_fwd,
511 };
512 /* *INDENT-ON* */
513 
514 /**
515  Set bridge-domain flood enable/disable.
516  The CLI format is:
517  set bridge-domain flood <bd_index> [disable]
518 */
519 static clib_error_t *
521  unformat_input_t * input, vlib_cli_command_t * cmd)
522 {
523  bd_main_t *bdm = &bd_main;
524  clib_error_t *error = 0;
525  u32 bd_index, bd_id;
526  u32 enable;
527  uword *p;
528 
529  if (!unformat (input, "%d", &bd_id))
530  {
531  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
532  format_unformat_error, input);
533  goto done;
534  }
535 
536  if (bd_id == 0)
537  return clib_error_return (0,
538  "No operations on the default bridge domain are supported");
539 
540  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
541 
542  if (p == 0)
543  return clib_error_return (0, "No such bridge domain %d", bd_id);
544 
545  bd_index = p[0];
546 
547  enable = 1;
548  if (unformat (input, "disable"))
549  {
550  enable = 0;
551  }
552 
553  /* set the bridge domain flag */
554  bd_set_flags (vm, bd_index, L2_FLOOD, enable);
555 
556 done:
557  return error;
558 }
559 
560 /*?
561  * Layer 2 flooding can be enabled and disabled on each
562  * interface and on each bridge-domain. Use this command to
563  * manage bridge-domains. It is enabled by default.
564  *
565  * @cliexpar
566  * Example of how to enable flooding (where 200 is the bridge-domain-id):
567  * @cliexcmd{set bridge-domain flood 200}
568  * Example of how to disable flooding (where 200 is the bridge-domain-id):
569  * @cliexcmd{set bridge-domain flood 200 disable}
570 ?*/
571 /* *INDENT-OFF* */
572 VLIB_CLI_COMMAND (bd_flood_cli, static) = {
573  .path = "set bridge-domain flood",
574  .short_help = "set bridge-domain flood <bridge-domain-id> [disable]",
575  .function = bd_flood,
576 };
577 /* *INDENT-ON* */
578 
579 /**
580  Set bridge-domain unknown-unicast flood enable/disable.
581  The CLI format is:
582  set bridge-domain uu-flood <bd_index> [disable]
583 */
584 static clib_error_t *
586  unformat_input_t * input, vlib_cli_command_t * cmd)
587 {
588  bd_main_t *bdm = &bd_main;
589  clib_error_t *error = 0;
590  u32 bd_index, bd_id;
591  u32 enable;
592  uword *p;
593 
594  if (!unformat (input, "%d", &bd_id))
595  {
596  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
597  format_unformat_error, input);
598  goto done;
599  }
600 
601  if (bd_id == 0)
602  return clib_error_return (0,
603  "No operations on the default bridge domain are supported");
604 
605  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
606 
607  if (p == 0)
608  return clib_error_return (0, "No such bridge domain %d", bd_id);
609 
610  bd_index = p[0];
611 
612  enable = 1;
613  if (unformat (input, "disable"))
614  {
615  enable = 0;
616  }
617 
618  /* set the bridge domain flag */
619  bd_set_flags (vm, bd_index, L2_UU_FLOOD, enable);
620 
621 done:
622  return error;
623 }
624 
625 /*?
626  * Layer 2 unknown-unicast flooding can be enabled and disabled on each
627  * bridge-domain. It is enabled by default.
628  *
629  * @cliexpar
630  * Example of how to enable unknown-unicast flooding (where 200 is the
631  * bridge-domain-id):
632  * @cliexcmd{set bridge-domain uu-flood 200}
633  * Example of how to disable unknown-unicast flooding (where 200 is the bridge-domain-id):
634  * @cliexcmd{set bridge-domain uu-flood 200 disable}
635 ?*/
636 /* *INDENT-OFF* */
637 VLIB_CLI_COMMAND (bd_uu_flood_cli, static) = {
638  .path = "set bridge-domain uu-flood",
639  .short_help = "set bridge-domain uu-flood <bridge-domain-id> [disable]",
640  .function = bd_uu_flood,
641 };
642 /* *INDENT-ON* */
643 
644 /**
645  Set bridge-domain arp-unicast forward enable/disable.
646  The CLI format is:
647  set bridge-domain arp-ufwd <bd_index> [disable]
648 */
649 static clib_error_t *
651  unformat_input_t * input, vlib_cli_command_t * cmd)
652 {
653  bd_main_t *bdm = &bd_main;
654  clib_error_t *error = 0;
655  u32 bd_index, bd_id;
656  u32 enable;
657  uword *p;
658 
659  if (!unformat (input, "%d", &bd_id))
660  {
661  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
662  format_unformat_error, input);
663  goto done;
664  }
665 
666  if (bd_id == 0)
667  return clib_error_return (0,
668  "No operations on the default bridge domain are supported");
669 
670  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
671 
672  if (p == 0)
673  return clib_error_return (0, "No such bridge domain %d", bd_id);
674 
675  bd_index = p[0];
676 
677  enable = 1;
678  if (unformat (input, "disable"))
679  {
680  enable = 0;
681  }
682 
683  /* set the bridge domain flag */
684  bd_set_flags (vm, bd_index, L2_ARP_UFWD, enable);
685 
686 done:
687  return error;
688 }
689 
690 /*?
691  * Layer 2 arp-unicast forwarding can be enabled and disabled on each
692  * bridge-domain. It is disabled by default.
693  *
694  * @cliexpar
695  * Example of how to enable arp-unicast forwarding (where 200 is the
696  * bridge-domain-id):
697  * @cliexcmd{set bridge-domain arp-ufwd 200}
698  * Example of how to disable arp-unicast forwarding (where 200 is the bridge-domain-id):
699  * @cliexcmd{set bridge-domain arp-ufwd 200 disable}
700 ?*/
701 /* *INDENT-OFF* */
702 VLIB_CLI_COMMAND (bd_arp_ufwd_cli, static) = {
703  .path = "set bridge-domain arp-ufwd",
704  .short_help = "set bridge-domain arp-ufwd <bridge-domain-id> [disable]",
705  .function = bd_arp_ufwd,
706 };
707 /* *INDENT-ON* */
708 
709 /**
710  Set bridge-domain arp term enable/disable.
711  The CLI format is:
712  set bridge-domain arp term <bridge-domain-id> [disable]
713 */
714 static clib_error_t *
716  unformat_input_t * input, vlib_cli_command_t * cmd)
717 {
718  bd_main_t *bdm = &bd_main;
719  clib_error_t *error = 0;
720  u32 bd_index, bd_id;
721  u32 enable;
722  uword *p;
723 
724  if (!unformat (input, "%d", &bd_id))
725  {
726  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
727  format_unformat_error, input);
728  goto done;
729  }
730 
731  if (bd_id == 0)
732  return clib_error_return (0,
733  "No operations on the default bridge domain are supported");
734 
735  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
736  if (p)
737  bd_index = *p;
738  else
739  return clib_error_return (0, "No such bridge domain %d", bd_id);
740 
741  enable = 1;
742  if (unformat (input, "disable"))
743  enable = 0;
744 
745  /* set the bridge domain flag */
746  bd_set_flags (vm, bd_index, L2_ARP_TERM, enable);
747 
748 done:
749  return error;
750 }
751 
752 static clib_error_t *
754  unformat_input_t * input, vlib_cli_command_t * cmd)
755 {
756  bd_main_t *bdm = &bd_main;
757  clib_error_t *error = 0;
758  u32 bd_index, bd_id;
759  u32 age;
760  uword *p;
761 
762  if (!unformat (input, "%d", &bd_id))
763  {
764  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
765  format_unformat_error, input);
766  goto done;
767  }
768 
769  if (bd_id == 0)
770  return clib_error_return (0,
771  "No operations on the default bridge domain are supported");
772 
773  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
774 
775  if (p == 0)
776  return clib_error_return (0, "No such bridge domain %d", bd_id);
777 
778  bd_index = p[0];
779 
780  if (!unformat (input, "%u", &age))
781  {
782  error =
783  clib_error_return (0, "expecting ageing time in minutes but got `%U'",
784  format_unformat_error, input);
785  goto done;
786  }
787 
788  /* set the bridge domain flag */
789  if (age > 255)
790  {
791  error =
792  clib_error_return (0, "mac aging time cannot be bigger than 255");
793  goto done;
794  }
795  bd_set_mac_age (vm, bd_index, (u8) age);
796 
797 done:
798  return error;
799 }
800 
801 /*?
802  * Layer 2 mac aging can be enabled and disabled on each
803  * bridge-domain. Use this command to set or disable mac aging
804  * on specific bridge-domains. It is disabled by default.
805  *
806  * @cliexpar
807  * Example of how to set mac aging (where 200 is the bridge-domain-id and
808  * 5 is aging time in minutes):
809  * @cliexcmd{set bridge-domain mac-age 200 5}
810  * Example of how to disable mac aging (where 200 is the bridge-domain-id):
811  * @cliexcmd{set bridge-domain flood 200 0}
812 ?*/
813 /* *INDENT-OFF* */
814 VLIB_CLI_COMMAND (bd_mac_age_cli, static) = {
815  .path = "set bridge-domain mac-age",
816  .short_help = "set bridge-domain mac-age <bridge-domain-id> <mins>",
817  .function = bd_mac_age,
818 };
819 /* *INDENT-ON* */
820 
821 /*?
822  * Modify whether or not an existing bridge-domain should terminate and respond
823  * to ARP Requests. ARP Termination is disabled by default.
824  *
825  * @cliexpar
826  * Example of how to enable ARP termination (where 200 is the bridge-domain-id):
827  * @cliexcmd{set bridge-domain arp term 200}
828  * Example of how to disable ARP termination (where 200 is the bridge-domain-id):
829  * @cliexcmd{set bridge-domain arp term 200 disable}
830 ?*/
831 /* *INDENT-OFF* */
832 VLIB_CLI_COMMAND (bd_arp_term_cli, static) = {
833  .path = "set bridge-domain arp term",
834  .short_help = "set bridge-domain arp term <bridge-domain-id> [disable]",
835  .function = bd_arp_term,
836 };
837 /* *INDENT-ON* */
838 
839 
840 /**
841  * Add/delete IP address to MAC address mapping.
842  *
843  * The clib hash implementation stores uword entries in the hash table.
844  * The hash table mac_by_ip4 is keyed via IP4 address and store the
845  * 6-byte MAC address directly in the hash table entry uword.
846  *
847  * @warning This only works for 64-bit processor with 8-byte uword;
848  * which means this code *WILL NOT WORK* for a 32-bit processor with
849  * 4-byte uword.
850  */
851 u32
854  const ip46_address_t * ip,
855  const mac_address_t * mac, u8 is_add)
856 {
857  l2_bridge_domain_t *bd_cfg = l2input_bd_config (bd_index);
858  u64 new_mac = mac_address_as_u64 (mac);
859  u64 *old_mac;
860 
861  /* make sure uword is 8 bytes */
862  ASSERT (sizeof (uword) == sizeof (u64));
863  ASSERT (bd_is_valid (bd_cfg));
864 
865  if (IP46_TYPE_IP6 == type)
866  {
867  ip6_address_t *ip6_addr_key;
868  hash_pair_t *hp;
869  old_mac = (u64 *) hash_get_mem (bd_cfg->mac_by_ip6, &ip->ip6);
870  if (is_add)
871  {
872  if (old_mac == NULL)
873  {
874  /* new entry - allocate and create ip6 address key */
875  ip6_addr_key = clib_mem_alloc (sizeof (ip6_address_t));
876  clib_memcpy (ip6_addr_key, &ip->ip6, sizeof (ip6_address_t));
877  }
878  else if (*old_mac == new_mac)
879  {
880  /* same mac entry already exist for ip6 address */
881  return 0;
882  }
883  else
884  {
885  /* update mac for ip6 address */
886  hp = hash_get_pair (bd_cfg->mac_by_ip6, &ip->ip6);
887  ip6_addr_key = (ip6_address_t *) hp->key;
888  }
889  hash_set_mem (bd_cfg->mac_by_ip6, ip6_addr_key, new_mac);
890  }
891  else
892  {
893  if (old_mac && (*old_mac == new_mac))
894  {
895  hp = hash_get_pair (bd_cfg->mac_by_ip6, &ip->ip6);
896  ip6_addr_key = (ip6_address_t *) hp->key;
897  hash_unset_mem (bd_cfg->mac_by_ip6, &ip->ip6);
898  clib_mem_free (ip6_addr_key);
899  }
900  else
901  return 1;
902  }
903  }
904  else
905  {
906  old_mac = (u64 *) hash_get (bd_cfg->mac_by_ip4, ip->ip4.as_u32);
907  if (is_add)
908  {
909  if (old_mac && (*old_mac == new_mac))
910  /* mac entry already exist */
911  return 0;
912  hash_set (bd_cfg->mac_by_ip4, ip->ip4.as_u32, new_mac);
913  }
914  else
915  {
916  if (old_mac && (*old_mac == new_mac))
917  hash_unset (bd_cfg->mac_by_ip4, ip->ip4.as_u32);
918  else
919  return 1;
920  }
921  }
922  return 0;
923 }
924 
925 /**
926  * Flush IP address to MAC address mapping tables in a BD.
927  */
928 void
930 {
931  l2_bridge_domain_t *bd = l2input_bd_config (bd_index);
932  ASSERT (bd_is_valid (bd));
934  bd->mac_by_ip4 = 0;
935  bd->mac_by_ip6 =
936  hash_create_mem (0, sizeof (ip6_address_t), sizeof (uword));
937 }
938 
939 /**
940  Set bridge-domain arp entry add/delete.
941  The CLI format is:
942  set bridge-domain arp entry <bridge-domain-id> <ip-addr> <mac-addr> [del]
943 */
944 static clib_error_t *
946  unformat_input_t * input, vlib_cli_command_t * cmd)
947 {
948  ip46_address_t ip_addr = ip46_address_initializer;
950  bd_main_t *bdm = &bd_main;
951  clib_error_t *error = 0;
952  u32 bd_index, bd_id;
954  u8 is_add = 1;
955  uword *p;
956 
957  if (!unformat (input, "%d", &bd_id))
958  {
959  error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
960  format_unformat_error, input);
961  goto done;
962  }
963 
964  if (bd_id == 0)
965  return clib_error_return (0,
966  "No operations on the default bridge domain are supported");
967 
968  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
969 
970  if (p)
971  bd_index = *p;
972  else
973  return clib_error_return (0, "No such bridge domain %d", bd_id);
974 
975  if (unformat (input, "%U", unformat_ip4_address, &ip_addr.ip4))
976  {
977  type = IP46_TYPE_IP4;
978  }
979  else if (unformat (input, "%U", unformat_ip6_address, &ip_addr.ip6))
980  {
981  type = IP46_TYPE_IP6;
982  }
983  else if (unformat (input, "del-all"))
984  {
985  bd_flush_ip_mac (bd_index);
986  goto done;
987  }
988  else
989  {
990  error = clib_error_return (0, "expecting IP address but got `%U'",
991  format_unformat_error, input);
992  goto done;
993  }
994 
995  if (!unformat (input, "%U", unformat_mac_address_t, &mac))
996  {
997  error = clib_error_return (0, "expecting MAC address but got `%U'",
998  format_unformat_error, input);
999  goto done;
1000  }
1001 
1002  if (unformat (input, "del"))
1003  {
1004  is_add = 0;
1005  }
1006 
1007  /* set the bridge domain flagAdd IP-MAC entry into bridge domain */
1008  if (bd_add_del_ip_mac (bd_index, type, &ip_addr, &mac, is_add))
1009  {
1010  error = clib_error_return (0, "MAC %s for IP %U and MAC %U failed",
1011  is_add ? "add" : "del",
1013  format_mac_address_t, &mac);
1014  }
1015 
1016 done:
1017  return error;
1018 }
1019 
1020 /*?
1021  * Add an ARP entry to an existing bridge-domain.
1022  *
1023  * @cliexpar
1024  * Example of how to add an ARP entry (where 200 is the bridge-domain-id):
1025  * @cliexcmd{set bridge-domain arp entry 200 192.168.72.45 52:54:00:3b:83:1a}
1026  * Example of how to delete an ARP entry (where 200 is the bridge-domain-id):
1027  * @cliexcmd{set bridge-domain arp entry 200 192.168.72.45 52:54:00:3b:83:1a del}
1028 ?*/
1029 /* *INDENT-OFF* */
1030 VLIB_CLI_COMMAND (bd_arp_entry_cli, static) = {
1031  .path = "set bridge-domain arp entry",
1032  .short_help = "set bridge-domain arp entry <bridge-domain-id> [<ip-addr> <mac-addr> [del] | del-all]",
1033  .function = bd_arp_entry,
1034 };
1035 /* *INDENT-ON* */
1036 
1037 static u8 *
1038 format_uu_cfg (u8 * s, va_list * args)
1039 {
1040  l2_bridge_domain_t *bd_config = va_arg (*args, l2_bridge_domain_t *);
1041 
1042  if (bd_config->feature_bitmap & L2INPUT_FEAT_UU_FWD)
1043  return (format (s, "%U", format_vnet_sw_if_index_name_with_NA,
1044  vnet_get_main (), bd_config->uu_fwd_sw_if_index));
1045  else if (bd_config->feature_bitmap & L2INPUT_FEAT_UU_FLOOD)
1046  return (format (s, "flood"));
1047  else
1048  return (format (s, "drop"));
1049 }
1050 
1051 /**
1052  Show bridge-domain state.
1053  The CLI format is:
1054  show bridge-domain [<bd_index>]
1055 */
1056 static clib_error_t *
1058 {
1059  vnet_main_t *vnm = vnet_get_main ();
1060  bd_main_t *bdm = &bd_main;
1061  clib_error_t *error = 0;
1062  u32 bd_index = ~0;
1063  l2_bridge_domain_t *bd_config;
1064  u32 start, end;
1065  u32 detail = 0;
1066  u32 intf = 0;
1067  u32 arp = 0;
1068  u32 bd_tag = 0;
1069  u32 bd_id = ~0;
1070  uword *p;
1071 
1072  start = 1;
1074 
1075  if (unformat (input, "%d", &bd_id))
1076  {
1077  if (unformat (input, "detail"))
1078  detail = 1;
1079  else if (unformat (input, "det"))
1080  detail = 1;
1081  if (unformat (input, "int"))
1082  intf = 1;
1083  if (unformat (input, "arp"))
1084  arp = 1;
1085  if (unformat (input, "bd-tag"))
1086  bd_tag = 1;
1087 
1088  if (bd_id == 0)
1089  return clib_error_return (0,
1090  "No operations on the default bridge domain are supported");
1091 
1092  p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1093  if (p)
1094  bd_index = *p;
1095  else
1096  return clib_error_return (0, "No such bridge domain %d", bd_id);
1097 
1098  vec_validate (l2input_main.bd_configs, bd_index);
1099  bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
1100  if (bd_is_valid (bd_config))
1101  {
1102  start = bd_index;
1103  end = start + 1;
1104  }
1105  else
1106  {
1107  vlib_cli_output (vm, "bridge-domain %d not in use", bd_id);
1108  goto done;
1109  }
1110  }
1111 
1112  /* Show all bridge-domains that have been initialized */
1113  u32 printed = 0;
1114  u8 *as = 0;
1115  for (bd_index = start; bd_index < end; bd_index++)
1116  {
1117  bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
1118  if (bd_is_valid (bd_config))
1119  {
1120  if (!printed)
1121  {
1122  printed = 1;
1123  vlib_cli_output (vm,
1124  "%=8s %=7s %=4s %=9s %=9s %=9s %=11s %=9s %=9s %=9s %=11s",
1125  "BD-ID", "Index", "BSN", "Age(min)",
1126  "Learning", "U-Forwrd", "UU-Flood",
1127  "Flooding", "ARP-Term", "arp-ufwd",
1128  "BVI-Intf");
1129  }
1130 
1131  if (bd_config->mac_age)
1132  as = format (as, "%d", bd_config->mac_age);
1133  else
1134  as = format (as, "off");
1135  vlib_cli_output (vm,
1136  "%=8d %=7d %=9v %=9s %=9s %=11U %=9s %=9s %=9s %=11U",
1137  bd_config->bd_id, bd_index, as,
1138  bd_config->feature_bitmap & L2INPUT_FEAT_LEARN ?
1139  "on" : "off",
1140  bd_config->feature_bitmap & L2INPUT_FEAT_FWD ?
1141  "on" : "off",
1142  format_uu_cfg, bd_config,
1143  bd_config->feature_bitmap & L2INPUT_FEAT_FLOOD ?
1144  "on" : "off",
1145  bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM ?
1146  "on" : "off",
1147  bd_config->feature_bitmap & L2INPUT_FEAT_ARP_UFWD ?
1148  "on" : "off",
1150  vnm, bd_config->bvi_sw_if_index);
1152  bd_config->feature_bitmap);
1153  vec_reset_length (as);
1154 
1155  if (detail || intf)
1156  {
1157  /* Show all member interfaces */
1158  int i;
1159  vec_foreach_index (i, bd_config->members)
1160  {
1161  l2_flood_member_t *member =
1162  vec_elt_at_index (bd_config->members, i);
1163  u8 swif_seq_num = l2_input_seq_num (member->sw_if_index);
1164  u32 vtr_opr, dot1q, tag1, tag2;
1165  if (i == 0)
1166  {
1167  vlib_cli_output (vm, "\n%=30s%=7s%=5s%=5s%=5s%=9s%=30s",
1168  "Interface", "If-idx", "ISN", "SHG",
1169  "BVI", "TxFlood", "VLAN-Tag-Rewrite");
1170  }
1171  l2vtr_get (vm, vnm, member->sw_if_index, &vtr_opr, &dot1q,
1172  &tag1, &tag2);
1173  vlib_cli_output (vm, "%=30U%=7d%=5d%=5d%=5s%=9s%=30U",
1175  member->sw_if_index, member->sw_if_index,
1176  swif_seq_num, member->shg,
1177  member->flags & L2_FLOOD_MEMBER_BVI ? "*" :
1178  "-", i < bd_config->flood_count ? "*" : "-",
1179  format_vtr, vtr_opr, dot1q, tag1, tag2);
1180  }
1181  if (~0 != bd_config->uu_fwd_sw_if_index)
1182  vlib_cli_output (vm, "%=30U%=7d%=5d%=5d%=5s%=9s%=30s",
1184  bd_config->uu_fwd_sw_if_index,
1185  bd_config->uu_fwd_sw_if_index,
1186  0, 0, "uu", "-", "None");
1187 
1188  }
1189 
1190  if ((detail || arp) &&
1191  (bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM))
1192  {
1193  u32 ip4_addr;
1194  ip6_address_t *ip6_addr;
1195  u64 mac_addr;
1196  vlib_cli_output (vm,
1197  "\n IP4/IP6 to MAC table for ARP Termination");
1198 
1199  /* *INDENT-OFF* */
1200  hash_foreach (ip4_addr, mac_addr, bd_config->mac_by_ip4,
1201  ({
1202  vlib_cli_output (vm, "%=40U => %=20U",
1203  format_ip4_address, &ip4_addr,
1204  format_ethernet_address, &mac_addr);
1205  }));
1206 
1207  hash_foreach_mem (ip6_addr, mac_addr, bd_config->mac_by_ip6,
1208  ({
1209  vlib_cli_output (vm, "%=40U => %=20U",
1210  format_ip6_address, ip6_addr,
1211  format_ethernet_address, &mac_addr);
1212  }));
1213  /* *INDENT-ON* */
1214  }
1215 
1216  if ((detail || bd_tag) && (bd_config->bd_tag))
1217  {
1218  vlib_cli_output (vm, "\n BD-Tag: %s", bd_config->bd_tag);
1219 
1220  }
1221  }
1222  }
1223  vec_free (as);
1224 
1225  if (!printed)
1226  {
1227  vlib_cli_output (vm, "no bridge-domains in use");
1228  }
1229 
1230 done:
1231  return error;
1232 }
1233 
1234 /*?
1235  * Show a summary of all the bridge-domain instances or detailed view of a
1236  * single bridge-domain. Bridge-domains are created by adding an interface
1237  * to a bridge using the '<em>set interface l2 bridge</em>' command.
1238  *
1239  * @cliexpar
1240  * @parblock
1241  * Example of displaying all bridge-domains:
1242  * @cliexstart{show bridge-domain}
1243  * ID Index Learning U-Forwrd UU-Flood Flooding ARP-Term BVI-Intf
1244  * 0 0 off off off off off local0
1245  * 200 1 on on on on off N/A
1246  * @cliexend
1247  *
1248  * Example of displaying details of a single bridge-domains:
1249  * @cliexstart{show bridge-domain 200 detail}
1250  * ID Index Learning U-Forwrd UU-Flood Flooding ARP-Term BVI-Intf
1251  * 200 1 on on on on off N/A
1252  *
1253  * Interface Index SHG BVI VLAN-Tag-Rewrite
1254  * GigabitEthernet0/8/0.200 3 0 - none
1255  * GigabitEthernet0/9/0.200 4 0 - none
1256  * @cliexend
1257  * @endparblock
1258 ?*/
1259 /* *INDENT-OFF* */
1260 VLIB_CLI_COMMAND (bd_show_cli, static) = {
1261  .path = "show bridge-domain",
1262  .short_help = "show bridge-domain [bridge-domain-id [detail|int|arp|bd-tag]]",
1263  .function = bd_show,
1264 };
1265 /* *INDENT-ON* */
1266 
1267 int
1269 {
1270  bd_main_t *bdm = &bd_main;
1272  vlib_main_t *vm = bdm->vlib_main;
1273  int rv = 0;
1274 
1275  if (fm->mac_table_initialized == 0)
1276  l2fib_table_init ();
1277 
1278  u32 bd_index = bd_find_index (bdm, a->bd_id);
1279  if (a->is_add)
1280  {
1281  if (bd_index != ~0)
1282  return VNET_API_ERROR_BD_ALREADY_EXISTS;
1283  if (a->bd_id > L2_BD_ID_MAX)
1284  return VNET_API_ERROR_BD_ID_EXCEED_MAX;
1285  bd_index = bd_add_bd_index (bdm, a->bd_id);
1286 
1287  bd_flags_t enable_flags = 0, disable_flags = 0;
1288  if (a->flood)
1289  enable_flags |= L2_FLOOD;
1290  else
1291  disable_flags |= L2_FLOOD;
1292 
1293  if (a->uu_flood)
1294  enable_flags |= L2_UU_FLOOD;
1295  else
1296  disable_flags |= L2_UU_FLOOD;
1297 
1298  if (a->forward)
1299  enable_flags |= L2_FWD;
1300  else
1301  disable_flags |= L2_FWD;
1302 
1303  if (a->learn)
1304  enable_flags |= L2_LEARN;
1305  else
1306  disable_flags |= L2_LEARN;
1307 
1308  if (a->arp_term)
1309  enable_flags |= L2_ARP_TERM;
1310  else
1311  disable_flags |= L2_ARP_TERM;
1312 
1313  if (a->arp_ufwd)
1314  enable_flags |= L2_ARP_UFWD;
1315  else
1316  disable_flags |= L2_ARP_UFWD;
1317 
1318  if (enable_flags)
1319  bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */ );
1320 
1321  if (disable_flags)
1322  bd_set_flags (vm, bd_index, disable_flags, 0 /* disable */ );
1323 
1324  bd_set_mac_age (vm, bd_index, a->mac_age);
1325 
1326  if (a->bd_tag)
1327  bd_set_bd_tag (vm, bd_index, a->bd_tag);
1328 
1329  }
1330  else
1331  {
1332  if (bd_index == ~0)
1333  return VNET_API_ERROR_NO_SUCH_ENTRY;
1334  if (bd_index == 0)
1335  return VNET_API_ERROR_BD_NOT_MODIFIABLE;
1336  if (vec_len (l2input_main.bd_configs[bd_index].members))
1337  return VNET_API_ERROR_BD_IN_USE;
1338  rv = bd_delete (bdm, bd_index);
1339  }
1340 
1341  return rv;
1342 }
1343 
1344 /**
1345  Create or delete bridge-domain.
1346  The CLI format:
1347  create bridge-domain <bd_index> [learn <0|1>] [forward <0|1>] [uu-flood <0|1>] [flood <0|1>]
1348  [arp-term <0|1>] [mac-age <nn>] [bd-tag <tag>] [del]
1349 */
1350 
1351 static clib_error_t *
1353  vlib_cli_command_t * cmd)
1354 {
1355  unformat_input_t _line_input, *line_input = &_line_input;
1356  clib_error_t *error = 0;
1357  u8 is_add = 1;
1358  u32 bd_id = ~0;
1359  u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term =
1360  0, arp_ufwd = 0;
1361  u32 mac_age = 0;
1362  u8 *bd_tag = NULL;
1364  int rv;
1365 
1366  /* Get a line of input. */
1367  if (!unformat_user (input, unformat_line_input, line_input))
1368  return 0;
1369 
1370  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1371  {
1372  if (unformat (line_input, "%d", &bd_id))
1373  ;
1374  else if (unformat (line_input, "flood %d", &flood))
1375  ;
1376  else if (unformat (line_input, "uu-flood %d", &uu_flood))
1377  ;
1378  else if (unformat (line_input, "forward %d", &forward))
1379  ;
1380  else if (unformat (line_input, "learn %d", &learn))
1381  ;
1382  else if (unformat (line_input, "arp-term %d", &arp_term))
1383  ;
1384  else if (unformat (line_input, "arp-ufwd %d", &arp_ufwd))
1385  ;
1386  else if (unformat (line_input, "mac-age %d", &mac_age))
1387  ;
1388  else if (unformat (line_input, "bd-tag %s", &bd_tag))
1389  ;
1390  else if (unformat (line_input, "del"))
1391  {
1392  is_add = 0;
1393  flood = uu_flood = forward = learn = 0;
1394  }
1395  else
1396  break;
1397  }
1398 
1399  if (bd_id == ~0)
1400  {
1401  error = clib_error_return (0, "bridge-domain-id not specified");
1402  goto done;
1403  }
1404 
1405  if (bd_id == 0)
1406  {
1407  error = clib_error_return (0, "bridge domain 0 can not be modified");
1408  goto done;
1409  }
1410 
1411  if (mac_age > 255)
1412  {
1413  error = clib_error_return (0, "mac age must be less than 256");
1414  goto done;
1415  }
1416  if ((bd_tag) && (strlen ((char *) bd_tag) > 63))
1417  {
1418  error = clib_error_return (0, "bd-tag cannot be longer than 63");
1419  goto done;
1420  }
1421 
1422  clib_memset (a, 0, sizeof (*a));
1423  a->is_add = is_add;
1424  a->bd_id = bd_id;
1425  a->flood = (u8) flood;
1426  a->uu_flood = (u8) uu_flood;
1427  a->forward = (u8) forward;
1428  a->learn = (u8) learn;
1429  a->arp_term = (u8) arp_term;
1430  a->arp_ufwd = (u8) arp_ufwd;
1431  a->mac_age = (u8) mac_age;
1432  a->bd_tag = bd_tag;
1433 
1434  rv = bd_add_del (a);
1435 
1436  switch (rv)
1437  {
1438  case 0:
1439  if (is_add)
1440  vlib_cli_output (vm, "bridge-domain %d", bd_id);
1441  break;
1442  case VNET_API_ERROR_BD_IN_USE:
1443  error = clib_error_return (0, "bridge domain in use - remove members");
1444  goto done;
1445  case VNET_API_ERROR_NO_SUCH_ENTRY:
1446  error = clib_error_return (0, "bridge domain ID does not exist");
1447  goto done;
1448  case VNET_API_ERROR_BD_NOT_MODIFIABLE:
1449  error = clib_error_return (0, "bridge domain 0 can not be modified");
1450  goto done;
1451  case VNET_API_ERROR_BD_ID_EXCEED_MAX:
1452  error = clib_error_return (0, "bridge domain ID exceed 16M limit");
1453  goto done;
1454  default:
1455  error = clib_error_return (0, "bd_add_del returned %d", rv);
1456  goto done;
1457  }
1458 
1459 done:
1460  vec_free (bd_tag);
1461  unformat_free (line_input);
1462 
1463  return error;
1464 }
1465 
1466 
1467 /*?
1468  * Create/Delete bridge-domain instance
1469  *
1470  * @cliexpar
1471  * @parblock
1472  * Example of creating bridge-domain 1:
1473  * @cliexstart{create bridge-domain 1}
1474  * bridge-domain 1
1475  * @cliexend
1476  *
1477  * Example of creating bridge-domain 2 with enabling arp-term, mac-age 60:
1478  * @cliexstart{create bridge-domain 2 arp-term 1 mac-age 60}
1479  * bridge-domain 2
1480  *
1481  * vpp# show bridge-domain
1482  * ID Index BSN Age(min) Learning U-Forwrd UU-Flood Flooding ARP-Term BVI-Intf
1483  * 0 0 0 off off off off off off local0
1484  * 1 1 0 off on on off on off N/A
1485  * 2 2 0 60 on on off on on N/A
1486  *
1487  * @cliexend
1488  *
1489  * Example of delete bridge-domain 1:
1490  * @cliexstart{create bridge-domain 1 del}
1491  * @cliexend
1492  * @endparblock
1493 ?*/
1494 
1495 /* *INDENT-OFF* */
1496 VLIB_CLI_COMMAND (bd_create_cli, static) = {
1497  .path = "create bridge-domain",
1498  .short_help = "create bridge-domain <bridge-domain-id>"
1499  " [learn <0|1>] [forward <0|1>] [uu-flood <0|1>] [flood <0|1>] [arp-term <0|1>]"
1500  " [arp-ufwd <0|1>] [mac-age <nn>] [bd-tag <tag>] [del]",
1501  .function = bd_add_del_command_fn,
1502 };
1503 /* *INDENT-ON* */
1504 
1505 
1506 
1507 /*
1508  * fd.io coding-style-patch-verification: ON
1509  *
1510  * Local Variables:
1511  * eval: (c-set-style "gnu")
1512  * End:
1513  */
void bd_validate(l2_bridge_domain_t *bd_config)
Init bridge domain if not done already.
Definition: l2_bd.c:51
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
#define vec_foreach_index(var, v)
Iterate over vector indices.
#define hash_set(h, key, value)
Definition: hash.h:255
u32 uu_fwd_sw_if_index
Definition: l2_bd.h:80
u8 * format_vnet_sw_if_index_name_with_NA(u8 *s, va_list *args)
Format sw_if_index.
Definition: l2_fib.c:90
static clib_error_t * bd_arp_ufwd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set bridge-domain arp-unicast forward enable/disable.
Definition: l2_bd.c:650
vl_api_mac_address_t mac
Definition: l2.api:502
#define hash_unset(h, key)
Definition: hash.h:261
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
a
Definition: bitmap.h:544
u32 bd_add_del_ip_mac(u32 bd_index, ip46_type_t type, const ip46_address_t *ip, const mac_address_t *mac, u8 is_add)
Add/delete IP address to MAC address mapping.
Definition: l2_bd.c:852
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
u32 bvi_sw_if_index
Definition: l2_bd.h:74
unsigned long u64
Definition: types.h:89
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
Definition: l2_bd.h:151
static void update_flood_count(l2_bridge_domain_t *bd_config)
Definition: l2_bd.c:139
l2_flood_member_t * members
Definition: l2_bd.h:86
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
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
#define hash_set_mem(h, key, value)
Definition: hash.h:275
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
vlib_main_t * vm
Definition: in2out_ed.c:1580
int bd_add_del(l2_bridge_domain_add_del_args_t *a)
Definition: l2_bd.c:1268
u32 bd_remove_member(l2_bridge_domain_t *bd_config, u32 sw_if_index)
Definition: l2_bd.c:193
#define L2_FLOOD_MEMBER_BVI
Definition: l2_bd.h:51
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
u8 data[128]
Definition: ipsec_types.api:90
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
#define fm
#define clib_memcpy(d, s, n)
Definition: string.h:180
l2_bridge_domain_t * bd_get(u32 bd_index)
Definition: l2_bd.c:247
vnet_flood_class_t flood_class
Definition: interface.h:764
unformat_function_t unformat_ip4_address
Definition: format.h:68
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
void bd_add_member(l2_bridge_domain_t *bd_config, l2_flood_member_t *member)
Definition: l2_bd.c:148
description fragment has unexpected format
Definition: map.api:433
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:455
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:442
clib_error_t * l2bd_init(vlib_main_t *vm)
Definition: l2_bd.c:227
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define clib_error_return(e, args...)
Definition: error.h:99
#define hash_get_pair(h, key)
Definition: hash.h:252
unsigned int u32
Definition: types.h:88
u32 bd_input_walk(u32 bd_index, bd_input_walk_fn_t fn, void *data)
Definition: l2_bd.c:255
static void bd_set_bd_tag(vlib_main_t *vm, u32 bd_index, u8 *bd_tag)
Set the tag for the bridge domain.
Definition: l2_bd.c:363
l2input_main_t l2input_main
Definition: l2_input_node.c:78
uword * bd_index_by_bd_id
Definition: l2_bd.h:36
unformat_function_t unformat_line_input
Definition: format.h:282
vl_api_fib_path_type_t type
Definition: fib_types.api:123
#define BD_REMOVE_ERROR_OK
Definition: l2_bd.c:189
Definition: cJSON.c:84
#define hash_create_mem(elts, key_bytes, value_bytes)
Definition: hash.h:661
#define hash_get(h, key)
Definition: hash.h:249
#define hash_unset_mem(h, key)
Definition: hash.h:291
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:1015
u32 bd_id
Definition: gbp.api:188
struct _unformat_input_t unformat_input_t
#define hash_free(h)
Definition: hash.h:310
u8 mac_table_initialized
Definition: l2_fib.h:55
void l2fib_flush_bd_mac(vlib_main_t *vm, u32 bd_index)
Flush all non static MACs in a bridge domain.
Definition: l2_fib.c:865
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:945
static clib_error_t * bd_add_del_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Create or delete bridge-domain.
Definition: l2_bd.c:1352
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:520
uword * bd_index_bitmap
Definition: l2_bd.h:39
#define hash_foreach_mem(key_var, value_var, h, body)
Definition: hash.h:461
static u8 * format_uu_cfg(u8 *s, va_list *args)
Definition: l2_bd.c:1038
u8 * format_l2_input_feature_bitmap(u8 *s, va_list *args)
Definition: l2_input.c:65
l2fib_main_t l2fib_main
Definition: l2_fib.c:54
static u32 bd_is_valid(l2_bridge_domain_t *bd_config)
Definition: l2_bd.h:134
uword unformat_mac_address_t(unformat_input_t *input, va_list *args)
Definition: mac_address.c:37
#define BD_REMOVE_ERROR_NOT_FOUND
Definition: l2_bd.c:190
format_function_t format_ip46_address
Definition: ip46_address.h:50
static int bd_delete(bd_main_t *bdm, u32 bd_index)
Definition: l2_bd.c:112
unformat_function_t unformat_ip6_address
Definition: format.h:89
void bd_set_mac_age(vlib_main_t *vm, u32 bd_index, u8 age)
Set the mac age for the bridge domain.
Definition: l2_bd.c:339
u32 no_flood_count
Definition: l2_bd.h:98
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u32 tun_master_count
Definition: l2_bd.h:92
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
u32 bd_set_flags(vlib_main_t *vm, u32 bd_index, bd_flags_t flags, u32 enable)
Set the learn/forward/flood flags for the bridge domain.
Definition: l2_bd.c:289
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:390
static void bd_free_ip_mac_tables(l2_bridge_domain_t *bd)
Definition: l2_bd.c:96
uword * mac_by_ip6
Definition: l2_bd.h:102
static_always_inline l2_bridge_domain_t * l2input_bd_config(u32 bd_index)
Definition: l2_input.h:114
void bd_flush_ip_mac(u32 bd_index)
Flush IP address to MAC address mapping tables in a BD.
Definition: l2_bd.c:929
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
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:1057
#define hash_create(elts, value_bytes)
Definition: hash.h:696
#define L2_BD_ID_MAX
Definition: l2_bd.h:116
#define ASSERT(truth)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:854
#define vec_insert_elts(V, E, N, M)
Insert N vector elements starting at element M, insert given elements (no header, unspecified alignme...
Definition: vec.h:833
static void clib_mem_free(void *p)
Definition: mem.h:311
u32 tun_normal_count
Definition: l2_bd.h:95
walk_rc_t(* bd_input_walk_fn_t)(u32 bd_index, u32 sw_if_index)
Walk all the input interfaces in the BD.
Definition: l2_bd.h:206
static void * clib_mem_alloc(uword size)
Definition: mem.h:253
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
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:715
vlib_main_t * vlib_main
Definition: l2_bd.h:42
static clib_error_t * bd_mac_age(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: l2_bd.c:753
vl_api_address_t ip
Definition: l2.api:501
static_always_inline u64 mac_address_as_u64(const mac_address_t *mac)
Definition: mac_address.h:112
walk_rc_t l2input_recache(u32 bd_index, u32 sw_if_index)
Definition: l2_input.c:222
u32 feature_bitmap
Definition: l2_bd.h:69
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vl_api_mac_address_t mac_addr
Definition: l2.api:180
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
l2_bridge_domain_t * bd_configs
Definition: l2_input.h:93
static clib_error_t * bd_uu_flood(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Set bridge-domain unknown-unicast flood enable/disable.
Definition: l2_bd.c:585
#define hash_get_mem(h, key)
Definition: hash.h:269
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:347
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
u8 * format_mac_address_t(u8 *s, va_list *args)
Definition: mac_address.c:27
#define vec_foreach(var, vec)
Vector iterator.
uword * mac_by_ip4
Definition: l2_bd.h:101
f64 end
end of the time range
Definition: mactime.api:44
static_always_inline u8 l2_input_seq_num(u32 sw_if_index)
Definition: l2_input.h:252
u32 sw_if_index
Definition: l2_bd.h:55
u32 bd_find_index(bd_main_t *bdm, u32 bd_id)
Get a bridge domain.
Definition: l2_bd.c:70
void l2fib_table_init(void)
Definition: l2_fib.c:370
static uword clib_bitmap_first_clear(uword *ai)
Return the lowest numbered clear bit in a bitmap.
Definition: bitmap.h:451
bd_main_t bd_main
Definition: l2_bd.c:44
vlib_node_registration_t l2fib_mac_age_scanner_process_node
(constructor) VLIB_REGISTER_NODE (l2fib_mac_age_scanner_process_node)
Definition: l2_fib.c:1307
u32 bd_add_bd_index(bd_main_t *bdm, u32 bd_id)
Create a bridge domain.
Definition: l2_bd.c:79
static void b2_input_recache(u32 bd_index)
Definition: l2_bd.c:279
format_function_t format_vtr
#define ip46_address_initializer
Definition: ip46_address.h:52
uword key
Definition: hash.h:162
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
enum bd_flags_t_ bd_flags_t
ip46_type_t
Definition: ip46_address.h:22