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