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