2 * l2_bd.c : layer 2 bridge domain
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <vlib/vlib.h>
19 #include <vnet/vnet.h>
21 #include <vnet/ethernet/ethernet.h>
22 #include <vnet/ip/format.h>
23 #include <vnet/l2/l2_input.h>
24 #include <vnet/l2/feat_bitmap.h>
25 #include <vnet/l2/l2_bd.h>
26 #include <vnet/l2/l2_fib.h>
27 #include <vnet/l2/l2_vtr.h>
28 #include <vnet/ip/ip4_packet.h>
29 #include <vnet/ip/ip6_packet.h>
31 #include <vppinfra/error.h>
32 #include <vppinfra/hash.h>
33 #include <vppinfra/vec.h>
37 * @brief Ethernet Bridge Domain.
39 * Code in this file manages Layer 2 bridge domains.
46 Init bridge domain if not done already.
47 For feature bitmap, set all bits except ARP termination
50 bd_validate (l2_bridge_domain_t * bd_config)
52 if (!bd_is_valid (bd_config))
54 bd_config->feature_bitmap = ~L2INPUT_FEAT_ARP_TERM;
55 bd_config->bvi_sw_if_index = ~0;
56 bd_config->members = 0;
57 bd_config->mac_by_ip4 = 0;
58 bd_config->mac_by_ip6 = hash_create_mem (0, sizeof (ip6_address_t),
64 bd_find_or_add_bd_index (bd_main_t * bdm, u32 bd_id)
72 while (hash_get (bdm->bd_index_by_bd_id, bd_id))
77 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
82 rv = clib_bitmap_first_clear (bdm->bd_index_bitmap);
84 /* mark this index busy */
85 bdm->bd_index_bitmap = clib_bitmap_set (bdm->bd_index_bitmap, rv, 1);
87 hash_set (bdm->bd_index_by_bd_id, bd_id, rv);
89 vec_validate (l2input_main.bd_configs, rv);
90 l2input_main.bd_configs[rv].bd_id = bd_id;
96 bd_delete_bd_index (bd_main_t * bdm, u32 bd_id)
101 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
107 /* mark this index clear */
108 bdm->bd_index_bitmap = clib_bitmap_set (bdm->bd_index_bitmap, bd_index, 0);
109 hash_unset (bdm->bd_index_by_bd_id, bd_id);
111 l2input_main.bd_configs[bd_index].bd_id = ~0;
112 l2input_main.bd_configs[bd_index].feature_bitmap = 0;
118 bd_add_member (l2_bridge_domain_t * bd_config, l2_flood_member_t * member)
121 * Add one element to the vector
123 * When flooding, the bvi interface (if present) must be the last member
124 * processed due to how BVI processing can change the packet. To enable
125 * this order, we make the bvi interface the first in the vector and
126 * flooding walks the vector in reverse.
128 if ((member->flags == L2_FLOOD_MEMBER_NORMAL) ||
129 (vec_len (bd_config->members) == 0))
131 vec_add1 (bd_config->members, *member);
136 /* Move 0th element to the end */
137 vec_add1 (bd_config->members, bd_config->members[0]);
138 bd_config->members[0] = *member;
143 #define BD_REMOVE_ERROR_OK 0
144 #define BD_REMOVE_ERROR_NOT_FOUND 1
147 bd_remove_member (l2_bridge_domain_t * bd_config, u32 sw_if_index)
151 /* Find and delete the member */
152 vec_foreach_index (ix, bd_config->members)
154 if (vec_elt (bd_config->members, ix).sw_if_index == sw_if_index)
156 vec_del1 (bd_config->members, ix);
157 return BD_REMOVE_ERROR_OK;
161 return BD_REMOVE_ERROR_NOT_FOUND;
166 l2bd_init (vlib_main_t * vm)
168 bd_main_t *bdm = &bd_main;
170 bdm->bd_index_by_bd_id = hash_create (0, sizeof (uword));
172 * create a dummy bd with bd_id of 0 and bd_index of 0 with feature set
173 * to packet drop only. Thus, packets received from any L2 interface with
174 * uninitialized bd_index of 0 can be dropped safely.
176 bd_index = bd_find_or_add_bd_index (bdm, 0);
177 ASSERT (bd_index == 0);
178 l2input_main.bd_configs[0].feature_bitmap = L2INPUT_FEAT_DROP;
182 VLIB_INIT_FUNCTION (l2bd_init);
186 Set the learn/forward/flood flags for the bridge domain.
187 Return 0 if ok, non-zero if for an error.
190 bd_set_flags (vlib_main_t * vm, u32 bd_index, u32 flags, u32 enable)
193 l2_bridge_domain_t *bd_config;
194 u32 feature_bitmap = 0;
196 vec_validate (l2input_main.bd_configs, bd_index);
197 bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
199 bd_validate (bd_config);
201 if (flags & L2_LEARN)
203 feature_bitmap |= L2INPUT_FEAT_LEARN;
207 feature_bitmap |= L2INPUT_FEAT_FWD;
209 if (flags & L2_FLOOD)
211 feature_bitmap |= L2INPUT_FEAT_FLOOD;
213 if (flags & L2_UU_FLOOD)
215 feature_bitmap |= L2INPUT_FEAT_UU_FLOOD;
217 if (flags & L2_ARP_TERM)
219 feature_bitmap |= L2INPUT_FEAT_ARP_TERM;
224 bd_config->feature_bitmap |= feature_bitmap;
228 bd_config->feature_bitmap &= ~feature_bitmap;
235 Set bridge-domain learn enable/disable.
237 set bridge-domain learn <bd_id> [disable]
239 static clib_error_t *
240 bd_learn (vlib_main_t * vm,
241 unformat_input_t * input, vlib_cli_command_t * cmd)
243 bd_main_t *bdm = &bd_main;
244 clib_error_t *error = 0;
249 if (!unformat (input, "%d", &bd_id))
251 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
252 format_unformat_error, input);
256 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
259 return clib_error_return (0, "No such bridge domain %d", bd_id);
264 if (unformat (input, "disable"))
269 /* set the bridge domain flag */
270 if (bd_set_flags (vm, bd_index, L2_LEARN, enable))
273 clib_error_return (0, "bridge-domain id %d out of range", bd_index);
282 * Layer 2 learning can be enabled and disabled on each
283 * interface and on each bridge-domain. Use this command to
284 * manage bridge-domains. It is enabled by default.
287 * Example of how to enable learning (where 200 is the bridge-domain-id):
288 * @cliexcmd{set bridge-domain learn 200}
289 * Example of how to disable learning (where 200 is the bridge-domain-id):
290 * @cliexcmd{set bridge-domain learn 200 disable}
293 VLIB_CLI_COMMAND (bd_learn_cli, static) = {
294 .path = "set bridge-domain learn",
295 .short_help = "set bridge-domain learn <bridge-domain-id> [disable]",
296 .function = bd_learn,
301 Set bridge-domain forward enable/disable.
303 set bridge-domain forward <bd_index> [disable]
305 static clib_error_t *
306 bd_fwd (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
308 bd_main_t *bdm = &bd_main;
309 clib_error_t *error = 0;
314 if (!unformat (input, "%d", &bd_id))
316 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
317 format_unformat_error, input);
321 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
324 return clib_error_return (0, "No such bridge domain %d", bd_id);
329 if (unformat (input, "disable"))
334 /* set the bridge domain flag */
335 if (bd_set_flags (vm, bd_index, L2_FWD, enable))
338 clib_error_return (0, "bridge-domain id %d out of range", bd_index);
348 * Layer 2 unicast forwarding can be enabled and disabled on each
349 * interface and on each bridge-domain. Use this command to
350 * manage bridge-domains. It is enabled by default.
353 * Example of how to enable forwarding (where 200 is the bridge-domain-id):
354 * @cliexcmd{set bridge-domain forward 200}
355 * Example of how to disable forwarding (where 200 is the bridge-domain-id):
356 * @cliexcmd{set bridge-domain forward 200 disable}
359 VLIB_CLI_COMMAND (bd_fwd_cli, static) = {
360 .path = "set bridge-domain forward",
361 .short_help = "set bridge-domain forward <bridge-domain-id> [disable]",
367 Set bridge-domain flood enable/disable.
369 set bridge-domain flood <bd_index> [disable]
371 static clib_error_t *
372 bd_flood (vlib_main_t * vm,
373 unformat_input_t * input, vlib_cli_command_t * cmd)
375 bd_main_t *bdm = &bd_main;
376 clib_error_t *error = 0;
381 if (!unformat (input, "%d", &bd_id))
383 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
384 format_unformat_error, input);
388 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
391 return clib_error_return (0, "No such bridge domain %d", bd_id);
396 if (unformat (input, "disable"))
401 /* set the bridge domain flag */
402 if (bd_set_flags (vm, bd_index, L2_FLOOD, enable))
405 clib_error_return (0, "bridge-domain id %d out of range", bd_index);
414 * Layer 2 flooding can be enabled and disabled on each
415 * interface and on each bridge-domain. Use this command to
416 * manage bridge-domains. It is enabled by default.
419 * Example of how to enable flooding (where 200 is the bridge-domain-id):
420 * @cliexcmd{set bridge-domain flood 200}
421 * Example of how to disable flooding (where 200 is the bridge-domain-id):
422 * @cliexcmd{set bridge-domain flood 200 disable}
425 VLIB_CLI_COMMAND (bd_flood_cli, static) = {
426 .path = "set bridge-domain flood",
427 .short_help = "set bridge-domain flood <bridge-domain-id> [disable]",
428 .function = bd_flood,
433 Set bridge-domain unkown-unicast flood enable/disable.
435 set bridge-domain uu-flood <bd_index> [disable]
437 static clib_error_t *
438 bd_uu_flood (vlib_main_t * vm,
439 unformat_input_t * input, vlib_cli_command_t * cmd)
441 bd_main_t *bdm = &bd_main;
442 clib_error_t *error = 0;
447 if (!unformat (input, "%d", &bd_id))
449 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
450 format_unformat_error, input);
454 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
457 return clib_error_return (0, "No such bridge domain %d", bd_id);
462 if (unformat (input, "disable"))
467 /* set the bridge domain flag */
468 if (bd_set_flags (vm, bd_index, L2_UU_FLOOD, enable))
471 clib_error_return (0, "bridge-domain id %d out of range", bd_index);
480 * Layer 2 unknown-unicast flooding can be enabled and disabled on each
481 * bridge-domain. It is enabled by default.
484 * Example of how to enable unknown-unicast flooding (where 200 is the
486 * @cliexcmd{set bridge-domain uu-flood 200}
487 * Example of how to disable unknown-unicast flooding (where 200 is the bridge-domain-id):
488 * @cliexcmd{set bridge-domain uu-flood 200 disable}
491 VLIB_CLI_COMMAND (bd_uu_flood_cli, static) = {
492 .path = "set bridge-domain uu-flood",
493 .short_help = "set bridge-domain uu-flood <bridge-domain-id> [disable]",
494 .function = bd_uu_flood,
499 Set bridge-domain arp term enable/disable.
501 set bridge-domain arp term <bridge-domain-id> [disable]
503 static clib_error_t *
504 bd_arp_term (vlib_main_t * vm,
505 unformat_input_t * input, vlib_cli_command_t * cmd)
507 bd_main_t *bdm = &bd_main;
508 clib_error_t *error = 0;
513 if (!unformat (input, "%d", &bd_id))
515 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
516 format_unformat_error, input);
520 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
524 return clib_error_return (0, "No such bridge domain %d", bd_id);
527 if (unformat (input, "disable"))
530 /* set the bridge domain flag */
531 if (bd_set_flags (vm, bd_index, L2_ARP_TERM, enable))
534 clib_error_return (0, "bridge-domain id %d out of range", bd_index);
543 * Modify whether or not an existing bridge-domain should terminate and respond
544 * to ARP Requests. ARP Termination is disabled by default.
547 * Example of how to enable ARP termination (where 200 is the bridge-domain-id):
548 * @cliexcmd{set bridge-domain arp term 200}
549 * Example of how to disable ARP termination (where 200 is the bridge-domain-id):
550 * @cliexcmd{set bridge-domain arp term 200 disable}
553 VLIB_CLI_COMMAND (bd_arp_term_cli, static) = {
554 .path = "set bridge-domain arp term",
555 .short_help = "set bridge-domain arp term <bridge-domain-id> [disable]",
556 .function = bd_arp_term,
562 * Add/delete IP address to MAC address mapping.
564 * The clib hash implementation stores uword entries in the hash table.
565 * The hash table mac_by_ip4 is keyed via IP4 address and store the
566 * 6-byte MAC address directly in the hash table entry uword.
568 * @warning This only works for 64-bit processor with 8-byte uword;
569 * which means this code *WILL NOT WORK* for a 32-bit prcessor with
573 bd_add_del_ip_mac (u32 bd_index,
574 u8 * ip_addr, u8 * mac_addr, u8 is_ip6, u8 is_add)
576 l2input_main_t *l2im = &l2input_main;
577 l2_bridge_domain_t *bd_cfg = l2input_bd_config_from_index (l2im, bd_index);
578 u64 new_mac = *(u64 *) mac_addr;
580 u16 *mac16 = (u16 *) & new_mac;
582 ASSERT (sizeof (uword) == sizeof (u64)); /* make sure uword is 8 bytes */
584 mac16[3] = 0; /* Clear last 2 unsed bytes of the 8-byte MAC address */
587 ip6_address_t *ip6_addr_key;
589 old_mac = (u64 *) hash_get_mem (bd_cfg->mac_by_ip6, ip_addr);
593 { /* new entry - allocate and craete ip6 address key */
594 ip6_addr_key = clib_mem_alloc (sizeof (ip6_address_t));
595 clib_memcpy (ip6_addr_key, ip_addr, sizeof (ip6_address_t));
597 else if (*old_mac == new_mac)
598 { /* same mac entry already exist for ip6 address */
602 { /* updat mac for ip6 address */
603 hp = hash_get_pair (bd_cfg->mac_by_ip6, ip_addr);
604 ip6_addr_key = (ip6_address_t *) hp->key;
606 hash_set_mem (bd_cfg->mac_by_ip6, ip6_addr_key, new_mac);
610 if (old_mac && (*old_mac == new_mac))
612 hp = hash_get_pair (bd_cfg->mac_by_ip6, ip_addr);
613 ip6_addr_key = (ip6_address_t *) hp->key;
614 hash_unset_mem (bd_cfg->mac_by_ip6, ip_addr);
615 clib_mem_free (ip6_addr_key);
623 ip4_address_t ip4_addr = *(ip4_address_t *) ip_addr;
624 old_mac = (u64 *) hash_get (bd_cfg->mac_by_ip4, ip4_addr.as_u32);
627 if (old_mac && (*old_mac == new_mac))
628 return 0; /* mac entry already exist */
629 hash_set (bd_cfg->mac_by_ip4, ip4_addr.as_u32, new_mac);
633 if (old_mac && (*old_mac == new_mac))
634 hash_unset (bd_cfg->mac_by_ip4, ip4_addr.as_u32);
643 Set bridge-domain arp entry add/delete.
645 set bridge-domain arp entry <bridge-domain-id> <ip-addr> <mac-addr> [del]
647 static clib_error_t *
648 bd_arp_entry (vlib_main_t * vm,
649 unformat_input_t * input, vlib_cli_command_t * cmd)
651 bd_main_t *bdm = &bd_main;
652 clib_error_t *error = 0;
660 if (!unformat (input, "%d", &bd_id))
662 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
663 format_unformat_error, input);
667 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
672 return clib_error_return (0, "No such bridge domain %d", bd_id);
674 if (unformat (input, "%U", unformat_ip4_address, ip_addr))
678 else if (unformat (input, "%U", unformat_ip6_address, ip_addr))
684 error = clib_error_return (0, "expecting IP address but got `%U'",
685 format_unformat_error, input);
689 if (!unformat (input, "%U", unformat_ethernet_address, mac_addr))
691 error = clib_error_return (0, "expecting MAC address but got `%U'",
692 format_unformat_error, input);
696 if (unformat (input, "del"))
701 /* set the bridge domain flagAdd IP-MAC entry into bridge domain */
702 if (bd_add_del_ip_mac (bd_index, ip_addr, mac_addr, is_ip6, is_add))
704 error = clib_error_return (0, "MAC %s for IP %U and MAC %U failed",
705 is_add ? "add" : "del",
707 format_ip4_address : format_ip6_address,
708 ip_addr, format_ethernet_address, mac_addr);
716 * Add an ARP entry to an existing bridge-domain.
719 * Example of how to add an ARP entry (where 200 is the bridge-domain-id):
720 * @cliexcmd{set bridge-domain arp entry 200 192.168.72.45 52:54:00:3b:83:1a}
721 * Example of how to delete an ARP entry (where 200 is the bridge-domain-id):
722 * @cliexcmd{set bridge-domain arp entry 200 192.168.72.45 52:54:00:3b:83:1a del}
725 VLIB_CLI_COMMAND (bd_arp_entry_cli, static) = {
726 .path = "set bridge-domain arp entry",
727 .short_help = "set bridge-domain arp entry <bridge-domain-id> <ip-addr> <mac-addr> [del]",
728 .function = bd_arp_entry,
733 format_vtr (u8 * s, va_list * args)
735 u32 vtr_op = va_arg (*args, u32);
736 u32 dot1q = va_arg (*args, u32);
737 u32 tag1 = va_arg (*args, u32);
738 u32 tag2 = va_arg (*args, u32);
741 case L2_VTR_DISABLED:
742 return format (s, "none");
744 return format (s, "push-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1);
746 return format (s, "push-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", tag1,
749 return format (s, "pop-1");
751 return format (s, "pop-2");
752 case L2_VTR_TRANSLATE_1_1:
753 return format (s, "trans-1-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1);
754 case L2_VTR_TRANSLATE_1_2:
755 return format (s, "trans-1-2 %s %d %d", dot1q ? "dot1q" : "dot1ad",
757 case L2_VTR_TRANSLATE_2_1:
758 return format (s, "trans-2-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1);
759 case L2_VTR_TRANSLATE_2_2:
760 return format (s, "trans-2-2 %s %d %d", dot1q ? "dot1q" : "dot1ad",
763 return format (s, "none");
768 Show bridge-domain state.
770 show bridge-domain [<bd_index>]
772 static clib_error_t *
773 bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
775 vnet_main_t *vnm = vnet_get_main ();
776 bd_main_t *bdm = &bd_main;
777 clib_error_t *error = 0;
779 l2_bridge_domain_t *bd_config;
789 end = vec_len (l2input_main.bd_configs);
791 if (unformat (input, "%d", &bd_id))
793 if (unformat (input, "detail"))
795 else if (unformat (input, "det"))
797 if (unformat (input, "int"))
799 if (unformat (input, "arp"))
802 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
806 return clib_error_return (0, "No such bridge domain %d", bd_id);
808 vec_validate (l2input_main.bd_configs, bd_index);
809 bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
810 if (bd_is_valid (bd_config))
817 vlib_cli_output (vm, "bridge-domain %d not in use", bd_id);
822 /* Show all bridge-domains that have been initialized */
824 for (bd_index = start; bd_index < end; bd_index++)
826 bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
827 if (bd_is_valid (bd_config))
833 "%=5s %=7s %=10s %=10s %=10s %=10s %=10s %=14s",
834 "ID", "Index", "Learning", "U-Forwrd",
835 "UU-Flood", "Flooding", "ARP-Term",
840 "%=5d %=7d %=10s %=10s %=10s %=10s %=10s %=14U",
841 bd_config->bd_id, bd_index,
842 bd_config->feature_bitmap & L2INPUT_FEAT_LEARN ?
844 bd_config->feature_bitmap & L2INPUT_FEAT_FWD ? "on"
846 bd_config->feature_bitmap & L2INPUT_FEAT_UU_FLOOD ?
848 bd_config->feature_bitmap & L2INPUT_FEAT_FLOOD ?
850 bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM ?
851 "on" : "off", format_vnet_sw_if_index_name_with_NA,
852 vnm, bd_config->bvi_sw_if_index);
856 /* Show all member interfaces */
858 l2_flood_member_t *member;
861 vec_foreach (member, bd_config->members)
863 u32 vtr_opr, dot1q, tag1, tag2;
867 vlib_cli_output (vm, "\n%=30s%=7s%=5s%=5s%=30s",
868 "Interface", "Index", "SHG", "BVI",
871 l2vtr_get (vm, vnm, member->sw_if_index, &vtr_opr, &dot1q,
873 vlib_cli_output (vm, "%=30U%=7d%=5d%=5s%=30U",
874 format_vnet_sw_if_index_name, vnm,
875 member->sw_if_index, member->sw_if_index,
877 member->flags & L2_FLOOD_MEMBER_BVI ? "*" :
878 "-", format_vtr, vtr_opr, dot1q, tag1, tag2);
882 if ((detail || arp) &&
883 (bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM))
886 ip6_address_t *ip6_addr;
889 "\n IP4/IP6 to MAC table for ARP Termination");
892 hash_foreach (ip4_addr, mac_addr, bd_config->mac_by_ip4,
894 vlib_cli_output (vm, "%=40U => %=20U",
895 format_ip4_address, &ip4_addr,
896 format_ethernet_address, &mac_addr);
899 hash_foreach_mem (ip6_addr, mac_addr, bd_config->mac_by_ip6,
901 vlib_cli_output (vm, "%=40U => %=20U",
902 format_ip6_address, ip6_addr,
903 format_ethernet_address, &mac_addr);
912 vlib_cli_output (vm, "no bridge-domains in use");
920 * Show a summary of all the bridge-domain instances or detailed view of a
921 * single bridge-domain. Bridge-domains are created by adding an interface
922 * to a bridge using the '<em>set interface l2 bridge</em>' command.
926 * Example of displaying all bridge-domains:
927 * @cliexstart{show bridge-domain}
928 * ID Index Learning U-Forwrd UU-Flood Flooding ARP-Term BVI-Intf
929 * 0 0 off off off off off local0
930 * 200 1 on on on on off N/A
933 * Example of displaying details of a single bridge-domains:
934 * @cliexstart{show bridge-domain 200 detail}
935 * ID Index Learning U-Forwrd UU-Flood Flooding ARP-Term BVI-Intf
936 * 200 1 on on on on off N/A
938 * Interface Index SHG BVI VLAN-Tag-Rewrite
939 * GigabitEthernet0/8/0.200 3 0 - none
940 * GigabitEthernet0/9/0.200 4 0 - none
945 VLIB_CLI_COMMAND (bd_show_cli, static) = {
946 .path = "show bridge-domain",
947 .short_help = "show bridge-domain [bridge-domain-id [detail|int|arp]]",
953 * fd.io coding-style-patch-verification: ON
956 * eval: (c-set-style "gnu")