blob: 207ef4d66010e5dc7ac1d58471f273b8bc55039b [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
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>
Damjan Mariond171d482016-12-05 14:16:38 +010026#include <vnet/l2/l2_learn.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070027#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
Billy McFall22aa3e92016-09-09 08:46:40 -040036/**
37 * @file
38 * @brief Ethernet Bridge Domain.
39 *
40 * Code in this file manages Layer 2 bridge domains.
41 *
42 */
43
Ed Warnickecb9cada2015-12-08 15:45:58 -070044bd_main_t bd_main;
45
Dave Barach97d8dc22016-08-15 15:31:15 -040046/**
Chris Luke16bcf7d2016-09-01 14:31:46 -040047 Init bridge domain if not done already.
Dave Barach97d8dc22016-08-15 15:31:15 -040048 For feature bitmap, set all bits except ARP termination
49*/
Damjan Marion99d8c762015-12-14 15:01:56 +010050void
Dave Barach97d8dc22016-08-15 15:31:15 -040051bd_validate (l2_bridge_domain_t * bd_config)
Ed Warnickecb9cada2015-12-08 15:45:58 -070052{
Eyal Barib1352ed2017-04-07 23:14:17 +030053 if (bd_is_valid (bd_config))
54 return;
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +020055 bd_config->feature_bitmap =
56 ~(L2INPUT_FEAT_ARP_TERM | L2INPUT_FEAT_UU_FWD | L2INPUT_FEAT_ARP_UFWD);
Eyal Barib1352ed2017-04-07 23:14:17 +030057 bd_config->bvi_sw_if_index = ~0;
Neale Rannsb4743802018-09-05 09:13:57 -070058 bd_config->uu_fwd_sw_if_index = ~0;
Eyal Barib1352ed2017-04-07 23:14:17 +030059 bd_config->members = 0;
60 bd_config->flood_count = 0;
61 bd_config->tun_master_count = 0;
62 bd_config->tun_normal_count = 0;
Eyal Barib6b04f02018-07-11 14:01:36 +030063 bd_config->no_flood_count = 0;
Eyal Barib1352ed2017-04-07 23:14:17 +030064 bd_config->mac_by_ip4 = 0;
65 bd_config->mac_by_ip6 = hash_create_mem (0, sizeof (ip6_address_t),
66 sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -070067}
68
Dave Barach97d8dc22016-08-15 15:31:15 -040069u32
Eyal Barib1352ed2017-04-07 23:14:17 +030070bd_find_index (bd_main_t * bdm, u32 bd_id)
Ed Warnickecb9cada2015-12-08 15:45:58 -070071{
Eyal Barib1352ed2017-04-07 23:14:17 +030072 u32 *p = (u32 *) hash_get (bdm->bd_index_by_bd_id, bd_id);
73 if (!p)
74 return ~0;
75 return p[0];
76}
Ed Warnickecb9cada2015-12-08 15:45:58 -070077
Eyal Barib1352ed2017-04-07 23:14:17 +030078u32
79bd_add_bd_index (bd_main_t * bdm, u32 bd_id)
80{
81 ASSERT (!hash_get (bdm->bd_index_by_bd_id, bd_id));
82 u32 rv = clib_bitmap_first_clear (bdm->bd_index_bitmap);
Dave Barach97d8dc22016-08-15 15:31:15 -040083
Eyal Barib1352ed2017-04-07 23:14:17 +030084 /* mark this index taken */
Ed Warnickecb9cada2015-12-08 15:45:58 -070085 bdm->bd_index_bitmap = clib_bitmap_set (bdm->bd_index_bitmap, rv, 1);
86
87 hash_set (bdm->bd_index_by_bd_id, bd_id, rv);
88
89 vec_validate (l2input_main.bd_configs, rv);
90 l2input_main.bd_configs[rv].bd_id = bd_id;
91
92 return rv;
93}
94
John Loe26c81f2019-01-07 15:16:33 -050095static inline void
96bd_free_ip_mac_tables (l2_bridge_domain_t * bd)
97{
98 u64 mac_addr;
99 ip6_address_t *ip6_addr_key;
100
101 hash_free (bd->mac_by_ip4);
102 /* *INDENT-OFF* */
103 hash_foreach_mem (ip6_addr_key, mac_addr, bd->mac_by_ip6,
104 ({
105 clib_mem_free (ip6_addr_key); /* free memory used for ip6 addr key */
106 }));
107 /* *INDENT-ON* */
108 hash_free (bd->mac_by_ip6);
109}
110
Eyal Barib1352ed2017-04-07 23:14:17 +0300111static int
112bd_delete (bd_main_t * bdm, u32 bd_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700113{
John Lod77630a2017-04-28 00:33:36 -0400114 l2_bridge_domain_t *bd = &l2input_main.bd_configs[bd_index];
115 u32 bd_id = bd->bd_id;
Eyal Bariafc47aa2017-04-20 14:45:17 +0300116
John Lod48c8eb2017-05-05 12:35:25 -0400117 /* flush non-static MACs in BD and removed bd_id from hash table */
118 l2fib_flush_bd_mac (vlib_get_main (), bd_index);
Eyal Barib1352ed2017-04-07 23:14:17 +0300119 hash_unset (bdm->bd_index_by_bd_id, bd_id);
Dave Barach97d8dc22016-08-15 15:31:15 -0400120
121 /* mark this index clear */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700122 bdm->bd_index_bitmap = clib_bitmap_set (bdm->bd_index_bitmap, bd_index, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700123
John Lod77630a2017-04-28 00:33:36 -0400124 /* clear BD config for reuse: bd_id to -1 and clear feature_bitmap */
125 bd->bd_id = ~0;
126 bd->feature_bitmap = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700127
Jerome Tollet48304142017-09-05 12:13:22 +0100128 /* free BD tag */
129 vec_free (bd->bd_tag);
130
John Lod48c8eb2017-05-05 12:35:25 -0400131 /* free memory used by BD */
John Lod77630a2017-04-28 00:33:36 -0400132 vec_free (bd->members);
John Loe26c81f2019-01-07 15:16:33 -0500133 bd_free_ip_mac_tables (bd);
John Loda1f2c72017-03-24 20:11:15 -0400134
Ed Warnickecb9cada2015-12-08 15:45:58 -0700135 return 0;
136}
137
Eyal Baric5b13602016-11-24 19:42:43 +0200138static void
139update_flood_count (l2_bridge_domain_t * bd_config)
140{
Neale Ranns87dad112018-04-09 01:53:01 -0700141 bd_config->flood_count = (vec_len (bd_config->members) -
142 (bd_config->tun_master_count ?
143 bd_config->tun_normal_count : 0));
144 bd_config->flood_count -= bd_config->no_flood_count;
Eyal Baric5b13602016-11-24 19:42:43 +0200145}
146
Ed Warnickecb9cada2015-12-08 15:45:58 -0700147void
Dave Barach97d8dc22016-08-15 15:31:15 -0400148bd_add_member (l2_bridge_domain_t * bd_config, l2_flood_member_t * member)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700149{
Neale Ranns87dad112018-04-09 01:53:01 -0700150 u32 ix = 0;
Eyal Baric5b13602016-11-24 19:42:43 +0200151 vnet_sw_interface_t *sw_if = vnet_get_sw_interface
152 (vnet_get_main (), member->sw_if_index);
153
Dave Barach97d8dc22016-08-15 15:31:15 -0400154 /*
155 * Add one element to the vector
Neale Ranns87dad112018-04-09 01:53:01 -0700156 * vector is ordered [ bvi, normal/tun_masters..., tun_normals... no_flood]
Dave Barach97d8dc22016-08-15 15:31:15 -0400157 * When flooding, the bvi interface (if present) must be the last member
158 * processed due to how BVI processing can change the packet. To enable
159 * this order, we make the bvi interface the first in the vector and
Neale Ranns87dad112018-04-09 01:53:01 -0700160 * flooding walks the vector in reverse. The flood-count determines where
161 * in the member list to start the walk from.
Dave Barach97d8dc22016-08-15 15:31:15 -0400162 */
Eyal Baric5b13602016-11-24 19:42:43 +0200163 switch (sw_if->flood_class)
Dave Barach97d8dc22016-08-15 15:31:15 -0400164 {
Neale Ranns87dad112018-04-09 01:53:01 -0700165 case VNET_FLOOD_CLASS_NO_FLOOD:
166 bd_config->no_flood_count++;
167 ix = vec_len (bd_config->members);
168 break;
169 case VNET_FLOOD_CLASS_BVI:
170 ix = 0;
171 break;
Eyal Baric5b13602016-11-24 19:42:43 +0200172 case VNET_FLOOD_CLASS_TUNNEL_MASTER:
173 bd_config->tun_master_count++;
174 /* Fall through */
Eyal Baric5b13602016-11-24 19:42:43 +0200175 case VNET_FLOOD_CLASS_NORMAL:
Neale Ranns87dad112018-04-09 01:53:01 -0700176 ix = (vec_len (bd_config->members) -
177 bd_config->tun_normal_count - bd_config->no_flood_count);
Eyal Baric5b13602016-11-24 19:42:43 +0200178 break;
179 case VNET_FLOOD_CLASS_TUNNEL_NORMAL:
Neale Ranns87dad112018-04-09 01:53:01 -0700180 ix = (vec_len (bd_config->members) - bd_config->no_flood_count);
Eyal Baric5b13602016-11-24 19:42:43 +0200181 bd_config->tun_normal_count++;
182 break;
183 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700184
Eyal Baric5b13602016-11-24 19:42:43 +0200185 vec_insert_elts (bd_config->members, member, 1, ix);
186 update_flood_count (bd_config);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700187}
188
Ed Warnickecb9cada2015-12-08 15:45:58 -0700189#define BD_REMOVE_ERROR_OK 0
190#define BD_REMOVE_ERROR_NOT_FOUND 1
191
192u32
Dave Barach97d8dc22016-08-15 15:31:15 -0400193bd_remove_member (l2_bridge_domain_t * bd_config, u32 sw_if_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700194{
195 u32 ix;
Dave Barach97d8dc22016-08-15 15:31:15 -0400196
197 /* Find and delete the member */
198 vec_foreach_index (ix, bd_config->members)
199 {
Eyal Baric5b13602016-11-24 19:42:43 +0200200 l2_flood_member_t *m = vec_elt_at_index (bd_config->members, ix);
201 if (m->sw_if_index == sw_if_index)
Dave Barach97d8dc22016-08-15 15:31:15 -0400202 {
Eyal Baric5b13602016-11-24 19:42:43 +0200203 vnet_sw_interface_t *sw_if = vnet_get_sw_interface
204 (vnet_get_main (), sw_if_index);
205
206 if (sw_if->flood_class != VNET_FLOOD_CLASS_NORMAL)
207 {
208 if (sw_if->flood_class == VNET_FLOOD_CLASS_TUNNEL_MASTER)
209 bd_config->tun_master_count--;
210 else if (sw_if->flood_class == VNET_FLOOD_CLASS_TUNNEL_NORMAL)
211 bd_config->tun_normal_count--;
Eyal Barib6b04f02018-07-11 14:01:36 +0300212 else if (sw_if->flood_class == VNET_FLOOD_CLASS_NO_FLOOD)
213 bd_config->no_flood_count--;
Eyal Baric5b13602016-11-24 19:42:43 +0200214 }
Eyal Bari25b36672017-03-02 10:43:19 +0200215 vec_delete (bd_config->members, 1, ix);
Eyal Baric5b13602016-11-24 19:42:43 +0200216 update_flood_count (bd_config);
217
Dave Barach97d8dc22016-08-15 15:31:15 -0400218 return BD_REMOVE_ERROR_OK;
219 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700220 }
221
222 return BD_REMOVE_ERROR_NOT_FOUND;
223}
224
225
Dave Barach97d8dc22016-08-15 15:31:15 -0400226clib_error_t *
227l2bd_init (vlib_main_t * vm)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700228{
229 bd_main_t *bdm = &bd_main;
Dave Barach97d8dc22016-08-15 15:31:15 -0400230 bdm->bd_index_by_bd_id = hash_create (0, sizeof (uword));
231 /*
232 * create a dummy bd with bd_id of 0 and bd_index of 0 with feature set
233 * to packet drop only. Thus, packets received from any L2 interface with
234 * uninitialized bd_index of 0 can be dropped safely.
235 */
Eyal Barib1352ed2017-04-07 23:14:17 +0300236 u32 bd_index = bd_add_bd_index (bdm, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700237 ASSERT (bd_index == 0);
Dave Barach97d8dc22016-08-15 15:31:15 -0400238 l2input_main.bd_configs[0].feature_bitmap = L2INPUT_FEAT_DROP;
Choonho Son05480792017-03-29 20:07:45 +0900239
240 bdm->vlib_main = vm;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241 return 0;
242}
243
244VLIB_INIT_FUNCTION (l2bd_init);
245
246
Dave Barach97d8dc22016-08-15 15:31:15 -0400247/**
Chris Luke16bcf7d2016-09-01 14:31:46 -0400248 Set the learn/forward/flood flags for the bridge domain.
Dave Barach97d8dc22016-08-15 15:31:15 -0400249 Return 0 if ok, non-zero if for an error.
250*/
251u32
Neale Rannsb4743802018-09-05 09:13:57 -0700252bd_set_flags (vlib_main_t * vm, u32 bd_index, bd_flags_t flags, u32 enable)
Dave Barach97d8dc22016-08-15 15:31:15 -0400253{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700254
Eyal Bariafc47aa2017-04-20 14:45:17 +0300255 l2_bridge_domain_t *bd_config = l2input_bd_config (bd_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700256 bd_validate (bd_config);
Eyal Bariafc47aa2017-04-20 14:45:17 +0300257 u32 feature_bitmap = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700258
Dave Barach97d8dc22016-08-15 15:31:15 -0400259 if (flags & L2_LEARN)
260 {
261 feature_bitmap |= L2INPUT_FEAT_LEARN;
262 }
263 if (flags & L2_FWD)
264 {
265 feature_bitmap |= L2INPUT_FEAT_FWD;
266 }
267 if (flags & L2_FLOOD)
268 {
269 feature_bitmap |= L2INPUT_FEAT_FLOOD;
270 }
271 if (flags & L2_UU_FLOOD)
272 {
273 feature_bitmap |= L2INPUT_FEAT_UU_FLOOD;
274 }
275 if (flags & L2_ARP_TERM)
276 {
277 feature_bitmap |= L2INPUT_FEAT_ARP_TERM;
278 }
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +0200279 if (flags & L2_ARP_UFWD)
280 {
281 feature_bitmap |= L2INPUT_FEAT_ARP_UFWD;
282 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700283
Dave Barach97d8dc22016-08-15 15:31:15 -0400284 if (enable)
285 {
286 bd_config->feature_bitmap |= feature_bitmap;
287 }
288 else
289 {
290 bd_config->feature_bitmap &= ~feature_bitmap;
291 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700292
John Lo8d00fff2017-08-03 00:35:36 -0400293 return bd_config->feature_bitmap;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700294}
295
Dave Barach97d8dc22016-08-15 15:31:15 -0400296/**
Damjan Mariond171d482016-12-05 14:16:38 +0100297 Set the mac age for the bridge domain.
298*/
299void
300bd_set_mac_age (vlib_main_t * vm, u32 bd_index, u8 age)
301{
302 l2_bridge_domain_t *bd_config;
303 int enable = 0;
304
305 vec_validate (l2input_main.bd_configs, bd_index);
306 bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
307 bd_config->mac_age = age;
308
309 /* check if there is at least one bd with mac aging enabled */
310 vec_foreach (bd_config, l2input_main.bd_configs)
Eyal Barifead6702017-04-04 04:46:32 +0300311 enable |= bd_config->bd_id != ~0 && bd_config->mac_age != 0;
Damjan Mariond171d482016-12-05 14:16:38 +0100312
313 vlib_process_signal_event (vm, l2fib_mac_age_scanner_process_node.index,
314 enable ? L2_MAC_AGE_PROCESS_EVENT_START :
315 L2_MAC_AGE_PROCESS_EVENT_STOP, 0);
316}
317
Jerome Tollet50570ec2017-09-14 12:53:56 +0100318/**
319 Set the tag for the bridge domain.
320*/
Jerome Tollet48304142017-09-05 12:13:22 +0100321
Jerome Tollet50570ec2017-09-14 12:53:56 +0100322static void
Jerome Tollet48304142017-09-05 12:13:22 +0100323bd_set_bd_tag (vlib_main_t * vm, u32 bd_index, u8 * bd_tag)
324{
325 u8 *old;
326 l2_bridge_domain_t *bd_config;
327 vec_validate (l2input_main.bd_configs, bd_index);
328 bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
329
330 old = bd_config->bd_tag;
331
332 if (bd_tag[0])
333 {
334 bd_config->bd_tag = format (0, "%s%c", bd_tag, 0);
335 }
336 else
337 {
338 bd_config->bd_tag = NULL;
339 }
340
341 vec_free (old);
342}
343
Damjan Mariond171d482016-12-05 14:16:38 +0100344/**
Chris Luke16bcf7d2016-09-01 14:31:46 -0400345 Set bridge-domain learn enable/disable.
Dave Barach97d8dc22016-08-15 15:31:15 -0400346 The CLI format is:
347 set bridge-domain learn <bd_id> [disable]
348*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700349static clib_error_t *
350bd_learn (vlib_main_t * vm,
Dave Barach97d8dc22016-08-15 15:31:15 -0400351 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700352{
Dave Barach97d8dc22016-08-15 15:31:15 -0400353 bd_main_t *bdm = &bd_main;
354 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700355 u32 bd_index, bd_id;
356 u32 enable;
Dave Barach97d8dc22016-08-15 15:31:15 -0400357 uword *p;
358
359 if (!unformat (input, "%d", &bd_id))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700360 {
361 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
Dave Barach97d8dc22016-08-15 15:31:15 -0400362 format_unformat_error, input);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700363 goto done;
364 }
365
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500366 if (bd_id == 0)
367 return clib_error_return (0,
368 "No operations on the default bridge domain are supported");
369
Ed Warnickecb9cada2015-12-08 15:45:58 -0700370 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
371
372 if (p == 0)
373 return clib_error_return (0, "No such bridge domain %d", bd_id);
Dave Barach97d8dc22016-08-15 15:31:15 -0400374
Ed Warnickecb9cada2015-12-08 15:45:58 -0700375 bd_index = p[0];
376
377 enable = 1;
Dave Barach97d8dc22016-08-15 15:31:15 -0400378 if (unformat (input, "disable"))
379 {
380 enable = 0;
381 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700382
Dave Barach97d8dc22016-08-15 15:31:15 -0400383 /* set the bridge domain flag */
John Lo8d00fff2017-08-03 00:35:36 -0400384 bd_set_flags (vm, bd_index, L2_LEARN, enable);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700385
Dave Barach97d8dc22016-08-15 15:31:15 -0400386done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700387 return error;
388}
389
Billy McFall22aa3e92016-09-09 08:46:40 -0400390/*?
391 * Layer 2 learning can be enabled and disabled on each
392 * interface and on each bridge-domain. Use this command to
393 * manage bridge-domains. It is enabled by default.
394 *
395 * @cliexpar
396 * Example of how to enable learning (where 200 is the bridge-domain-id):
397 * @cliexcmd{set bridge-domain learn 200}
398 * Example of how to disable learning (where 200 is the bridge-domain-id):
399 * @cliexcmd{set bridge-domain learn 200 disable}
400?*/
Dave Barach97d8dc22016-08-15 15:31:15 -0400401/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700402VLIB_CLI_COMMAND (bd_learn_cli, static) = {
403 .path = "set bridge-domain learn",
404 .short_help = "set bridge-domain learn <bridge-domain-id> [disable]",
405 .function = bd_learn,
406};
Dave Barach97d8dc22016-08-15 15:31:15 -0400407/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700408
Dave Barach97d8dc22016-08-15 15:31:15 -0400409/**
Chris Luke16bcf7d2016-09-01 14:31:46 -0400410 Set bridge-domain forward enable/disable.
Dave Barach97d8dc22016-08-15 15:31:15 -0400411 The CLI format is:
412 set bridge-domain forward <bd_index> [disable]
413*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700414static clib_error_t *
Dave Barach97d8dc22016-08-15 15:31:15 -0400415bd_fwd (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700416{
Dave Barach97d8dc22016-08-15 15:31:15 -0400417 bd_main_t *bdm = &bd_main;
418 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700419 u32 bd_index, bd_id;
420 u32 enable;
Dave Barach97d8dc22016-08-15 15:31:15 -0400421 uword *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700422
Dave Barach97d8dc22016-08-15 15:31:15 -0400423 if (!unformat (input, "%d", &bd_id))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700424 {
425 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
Dave Barach97d8dc22016-08-15 15:31:15 -0400426 format_unformat_error, input);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700427 goto done;
428 }
429
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500430 if (bd_id == 0)
431 return clib_error_return (0,
432 "No operations on the default bridge domain are supported");
433
Ed Warnickecb9cada2015-12-08 15:45:58 -0700434 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
435
436 if (p == 0)
437 return clib_error_return (0, "No such bridge domain %d", bd_id);
Dave Barach97d8dc22016-08-15 15:31:15 -0400438
Ed Warnickecb9cada2015-12-08 15:45:58 -0700439 bd_index = p[0];
440
441 enable = 1;
Dave Barach97d8dc22016-08-15 15:31:15 -0400442 if (unformat (input, "disable"))
443 {
444 enable = 0;
445 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700446
Dave Barach97d8dc22016-08-15 15:31:15 -0400447 /* set the bridge domain flag */
John Lo8d00fff2017-08-03 00:35:36 -0400448 bd_set_flags (vm, bd_index, L2_FWD, enable);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700449
Dave Barach97d8dc22016-08-15 15:31:15 -0400450done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700451 return error;
452}
453
Billy McFall22aa3e92016-09-09 08:46:40 -0400454
455/*?
456 * Layer 2 unicast forwarding can be enabled and disabled on each
457 * interface and on each bridge-domain. Use this command to
458 * manage bridge-domains. It is enabled by default.
459 *
460 * @cliexpar
461 * Example of how to enable forwarding (where 200 is the bridge-domain-id):
462 * @cliexcmd{set bridge-domain forward 200}
463 * Example of how to disable forwarding (where 200 is the bridge-domain-id):
464 * @cliexcmd{set bridge-domain forward 200 disable}
465?*/
Dave Barach97d8dc22016-08-15 15:31:15 -0400466/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700467VLIB_CLI_COMMAND (bd_fwd_cli, static) = {
468 .path = "set bridge-domain forward",
469 .short_help = "set bridge-domain forward <bridge-domain-id> [disable]",
470 .function = bd_fwd,
471};
Dave Barach97d8dc22016-08-15 15:31:15 -0400472/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700473
Dave Barach97d8dc22016-08-15 15:31:15 -0400474/**
Chris Luke16bcf7d2016-09-01 14:31:46 -0400475 Set bridge-domain flood enable/disable.
Dave Barach97d8dc22016-08-15 15:31:15 -0400476 The CLI format is:
477 set bridge-domain flood <bd_index> [disable]
478*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700479static clib_error_t *
480bd_flood (vlib_main_t * vm,
Dave Barach97d8dc22016-08-15 15:31:15 -0400481 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700482{
Dave Barach97d8dc22016-08-15 15:31:15 -0400483 bd_main_t *bdm = &bd_main;
484 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700485 u32 bd_index, bd_id;
486 u32 enable;
Dave Barach97d8dc22016-08-15 15:31:15 -0400487 uword *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700488
Dave Barach97d8dc22016-08-15 15:31:15 -0400489 if (!unformat (input, "%d", &bd_id))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700490 {
491 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
Dave Barach97d8dc22016-08-15 15:31:15 -0400492 format_unformat_error, input);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700493 goto done;
494 }
495
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500496 if (bd_id == 0)
497 return clib_error_return (0,
498 "No operations on the default bridge domain are supported");
499
Ed Warnickecb9cada2015-12-08 15:45:58 -0700500 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
501
502 if (p == 0)
503 return clib_error_return (0, "No such bridge domain %d", bd_id);
Dave Barach97d8dc22016-08-15 15:31:15 -0400504
Ed Warnickecb9cada2015-12-08 15:45:58 -0700505 bd_index = p[0];
506
507 enable = 1;
Dave Barach97d8dc22016-08-15 15:31:15 -0400508 if (unformat (input, "disable"))
509 {
510 enable = 0;
511 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700512
Dave Barach97d8dc22016-08-15 15:31:15 -0400513 /* set the bridge domain flag */
John Lo8d00fff2017-08-03 00:35:36 -0400514 bd_set_flags (vm, bd_index, L2_FLOOD, enable);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700515
Dave Barach97d8dc22016-08-15 15:31:15 -0400516done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700517 return error;
518}
519
Billy McFall22aa3e92016-09-09 08:46:40 -0400520/*?
521 * Layer 2 flooding can be enabled and disabled on each
522 * interface and on each bridge-domain. Use this command to
523 * manage bridge-domains. It is enabled by default.
524 *
525 * @cliexpar
526 * Example of how to enable flooding (where 200 is the bridge-domain-id):
527 * @cliexcmd{set bridge-domain flood 200}
528 * Example of how to disable flooding (where 200 is the bridge-domain-id):
529 * @cliexcmd{set bridge-domain flood 200 disable}
530?*/
Dave Barach97d8dc22016-08-15 15:31:15 -0400531/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700532VLIB_CLI_COMMAND (bd_flood_cli, static) = {
533 .path = "set bridge-domain flood",
534 .short_help = "set bridge-domain flood <bridge-domain-id> [disable]",
535 .function = bd_flood,
536};
Dave Barach97d8dc22016-08-15 15:31:15 -0400537/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700538
Dave Barach97d8dc22016-08-15 15:31:15 -0400539/**
Andrey "Zed" Zaikin701625b2018-04-18 17:07:07 +0300540 Set bridge-domain unknown-unicast flood enable/disable.
Dave Barach97d8dc22016-08-15 15:31:15 -0400541 The CLI format is:
542 set bridge-domain uu-flood <bd_index> [disable]
543*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700544static clib_error_t *
545bd_uu_flood (vlib_main_t * vm,
Dave Barach97d8dc22016-08-15 15:31:15 -0400546 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700547{
Dave Barach97d8dc22016-08-15 15:31:15 -0400548 bd_main_t *bdm = &bd_main;
549 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700550 u32 bd_index, bd_id;
551 u32 enable;
Dave Barach97d8dc22016-08-15 15:31:15 -0400552 uword *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700553
Dave Barach97d8dc22016-08-15 15:31:15 -0400554 if (!unformat (input, "%d", &bd_id))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700555 {
556 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
Dave Barach97d8dc22016-08-15 15:31:15 -0400557 format_unformat_error, input);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700558 goto done;
559 }
560
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500561 if (bd_id == 0)
562 return clib_error_return (0,
563 "No operations on the default bridge domain are supported");
564
Ed Warnickecb9cada2015-12-08 15:45:58 -0700565 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
566
567 if (p == 0)
568 return clib_error_return (0, "No such bridge domain %d", bd_id);
Dave Barach97d8dc22016-08-15 15:31:15 -0400569
Ed Warnickecb9cada2015-12-08 15:45:58 -0700570 bd_index = p[0];
571
572 enable = 1;
Dave Barach97d8dc22016-08-15 15:31:15 -0400573 if (unformat (input, "disable"))
574 {
575 enable = 0;
576 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700577
Dave Barach97d8dc22016-08-15 15:31:15 -0400578 /* set the bridge domain flag */
John Lo8d00fff2017-08-03 00:35:36 -0400579 bd_set_flags (vm, bd_index, L2_UU_FLOOD, enable);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700580
Dave Barach97d8dc22016-08-15 15:31:15 -0400581done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700582 return error;
583}
584
Billy McFall22aa3e92016-09-09 08:46:40 -0400585/*?
586 * Layer 2 unknown-unicast flooding can be enabled and disabled on each
587 * bridge-domain. It is enabled by default.
588 *
589 * @cliexpar
590 * Example of how to enable unknown-unicast flooding (where 200 is the
591 * bridge-domain-id):
592 * @cliexcmd{set bridge-domain uu-flood 200}
593 * Example of how to disable unknown-unicast flooding (where 200 is the bridge-domain-id):
594 * @cliexcmd{set bridge-domain uu-flood 200 disable}
595?*/
Dave Barach97d8dc22016-08-15 15:31:15 -0400596/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700597VLIB_CLI_COMMAND (bd_uu_flood_cli, static) = {
598 .path = "set bridge-domain uu-flood",
599 .short_help = "set bridge-domain uu-flood <bridge-domain-id> [disable]",
600 .function = bd_uu_flood,
601};
Dave Barach97d8dc22016-08-15 15:31:15 -0400602/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700603
Dave Barach97d8dc22016-08-15 15:31:15 -0400604/**
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +0200605 Set bridge-domain arp-unicast forward enable/disable.
606 The CLI format is:
607 set bridge-domain arp-ufwd <bd_index> [disable]
608*/
609static clib_error_t *
610bd_arp_ufwd (vlib_main_t * vm,
611 unformat_input_t * input, vlib_cli_command_t * cmd)
612{
613 bd_main_t *bdm = &bd_main;
614 clib_error_t *error = 0;
615 u32 bd_index, bd_id;
616 u32 enable;
617 uword *p;
618
619 if (!unformat (input, "%d", &bd_id))
620 {
621 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
622 format_unformat_error, input);
623 goto done;
624 }
625
626 if (bd_id == 0)
627 return clib_error_return (0,
628 "No operations on the default bridge domain are supported");
629
630 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
631
632 if (p == 0)
633 return clib_error_return (0, "No such bridge domain %d", bd_id);
634
635 bd_index = p[0];
636
637 enable = 1;
638 if (unformat (input, "disable"))
639 {
640 enable = 0;
641 }
642
643 /* set the bridge domain flag */
644 bd_set_flags (vm, bd_index, L2_ARP_UFWD, enable);
645
646done:
647 return error;
648}
649
650/*?
651 * Layer 2 arp-unicast forwarding can be enabled and disabled on each
652 * bridge-domain. It is disabled by default.
653 *
654 * @cliexpar
655 * Example of how to enable arp-unicast forwarding (where 200 is the
656 * bridge-domain-id):
657 * @cliexcmd{set bridge-domain arp-ufwd 200}
658 * Example of how to disable arp-unicast forwarding (where 200 is the bridge-domain-id):
659 * @cliexcmd{set bridge-domain arp-ufwd 200 disable}
660?*/
661/* *INDENT-OFF* */
662VLIB_CLI_COMMAND (bd_arp_ufwd_cli, static) = {
663 .path = "set bridge-domain arp-ufwd",
664 .short_help = "set bridge-domain arp-ufwd <bridge-domain-id> [disable]",
665 .function = bd_arp_ufwd,
666};
667/* *INDENT-ON* */
668
669/**
Chris Luke16bcf7d2016-09-01 14:31:46 -0400670 Set bridge-domain arp term enable/disable.
Dave Barach97d8dc22016-08-15 15:31:15 -0400671 The CLI format is:
672 set bridge-domain arp term <bridge-domain-id> [disable]
673*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700674static clib_error_t *
675bd_arp_term (vlib_main_t * vm,
Dave Barach97d8dc22016-08-15 15:31:15 -0400676 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700677{
Dave Barach97d8dc22016-08-15 15:31:15 -0400678 bd_main_t *bdm = &bd_main;
679 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700680 u32 bd_index, bd_id;
681 u32 enable;
Dave Barach97d8dc22016-08-15 15:31:15 -0400682 uword *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700683
Dave Barach97d8dc22016-08-15 15:31:15 -0400684 if (!unformat (input, "%d", &bd_id))
685 {
686 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
687 format_unformat_error, input);
688 goto done;
689 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700690
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500691 if (bd_id == 0)
692 return clib_error_return (0,
693 "No operations on the default bridge domain are supported");
694
Ed Warnickecb9cada2015-12-08 15:45:58 -0700695 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
Dave Barach97d8dc22016-08-15 15:31:15 -0400696 if (p)
697 bd_index = *p;
698 else
699 return clib_error_return (0, "No such bridge domain %d", bd_id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700700
Dave Barach97d8dc22016-08-15 15:31:15 -0400701 enable = 1;
702 if (unformat (input, "disable"))
703 enable = 0;
704
705 /* set the bridge domain flag */
John Lo8d00fff2017-08-03 00:35:36 -0400706 bd_set_flags (vm, bd_index, L2_ARP_TERM, enable);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700707
708done:
709 return error;
710}
711
Damjan Mariond171d482016-12-05 14:16:38 +0100712static clib_error_t *
713bd_mac_age (vlib_main_t * vm,
714 unformat_input_t * input, vlib_cli_command_t * cmd)
715{
716 bd_main_t *bdm = &bd_main;
717 clib_error_t *error = 0;
718 u32 bd_index, bd_id;
719 u32 age;
720 uword *p;
721
722 if (!unformat (input, "%d", &bd_id))
723 {
724 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
725 format_unformat_error, input);
726 goto done;
727 }
728
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500729 if (bd_id == 0)
730 return clib_error_return (0,
731 "No operations on the default bridge domain are supported");
732
Damjan Mariond171d482016-12-05 14:16:38 +0100733 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
734
735 if (p == 0)
736 return clib_error_return (0, "No such bridge domain %d", bd_id);
737
738 bd_index = p[0];
739
740 if (!unformat (input, "%u", &age))
741 {
742 error =
743 clib_error_return (0, "expecting ageing time in minutes but got `%U'",
744 format_unformat_error, input);
745 goto done;
746 }
747
748 /* set the bridge domain flag */
749 if (age > 255)
750 {
751 error =
752 clib_error_return (0, "mac aging time cannot be bigger than 255");
753 goto done;
754 }
755 bd_set_mac_age (vm, bd_index, (u8) age);
756
757done:
758 return error;
759}
760
761/*?
762 * Layer 2 mac aging can be enabled and disabled on each
763 * bridge-domain. Use this command to set or disable mac aging
764 * on specific bridge-domains. It is disabled by default.
765 *
766 * @cliexpar
767 * Example of how to set mac aging (where 200 is the bridge-domain-id and
768 * 5 is aging time in minutes):
769 * @cliexcmd{set bridge-domain mac-age 200 5}
770 * Example of how to disable mac aging (where 200 is the bridge-domain-id):
771 * @cliexcmd{set bridge-domain flood 200 0}
772?*/
773/* *INDENT-OFF* */
774VLIB_CLI_COMMAND (bd_mac_age_cli, static) = {
775 .path = "set bridge-domain mac-age",
776 .short_help = "set bridge-domain mac-age <bridge-domain-id> <mins>",
777 .function = bd_mac_age,
778};
779/* *INDENT-ON* */
780
Billy McFall22aa3e92016-09-09 08:46:40 -0400781/*?
782 * Modify whether or not an existing bridge-domain should terminate and respond
783 * to ARP Requests. ARP Termination is disabled by default.
784 *
785 * @cliexpar
786 * Example of how to enable ARP termination (where 200 is the bridge-domain-id):
787 * @cliexcmd{set bridge-domain arp term 200}
788 * Example of how to disable ARP termination (where 200 is the bridge-domain-id):
789 * @cliexcmd{set bridge-domain arp term 200 disable}
790?*/
Dave Barach97d8dc22016-08-15 15:31:15 -0400791/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700792VLIB_CLI_COMMAND (bd_arp_term_cli, static) = {
793 .path = "set bridge-domain arp term",
794 .short_help = "set bridge-domain arp term <bridge-domain-id> [disable]",
795 .function = bd_arp_term,
796};
Dave Barach97d8dc22016-08-15 15:31:15 -0400797/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700798
799
Dave Barach97d8dc22016-08-15 15:31:15 -0400800/**
Chris Luke16bcf7d2016-09-01 14:31:46 -0400801 * Add/delete IP address to MAC address mapping.
802 *
Dave Barach97d8dc22016-08-15 15:31:15 -0400803 * The clib hash implementation stores uword entries in the hash table.
804 * The hash table mac_by_ip4 is keyed via IP4 address and store the
805 * 6-byte MAC address directly in the hash table entry uword.
Chris Luke16bcf7d2016-09-01 14:31:46 -0400806 *
807 * @warning This only works for 64-bit processor with 8-byte uword;
Paul Vinciguerrabdc0e6b2018-09-22 05:32:50 -0700808 * which means this code *WILL NOT WORK* for a 32-bit processor with
Chris Luke16bcf7d2016-09-01 14:31:46 -0400809 * 4-byte uword.
Dave Barach97d8dc22016-08-15 15:31:15 -0400810 */
811u32
812bd_add_del_ip_mac (u32 bd_index,
Neale Ranns4d5b9172018-10-24 02:57:49 -0700813 ip46_type_t type,
814 const ip46_address_t * ip,
815 const mac_address_t * mac, u8 is_add)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700816{
Eyal Bariafc47aa2017-04-20 14:45:17 +0300817 l2_bridge_domain_t *bd_cfg = l2input_bd_config (bd_index);
Neale Ranns4d5b9172018-10-24 02:57:49 -0700818 u64 new_mac = mac_address_as_u64 (mac);
Dave Barach97d8dc22016-08-15 15:31:15 -0400819 u64 *old_mac;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700820
Neale Ranns4d5b9172018-10-24 02:57:49 -0700821 /* make sure uword is 8 bytes */
822 ASSERT (sizeof (uword) == sizeof (u64));
Eyal Bariafc47aa2017-04-20 14:45:17 +0300823 ASSERT (bd_is_valid (bd_cfg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700824
Neale Ranns4d5b9172018-10-24 02:57:49 -0700825 if (IP46_TYPE_IP6 == type)
Dave Barach97d8dc22016-08-15 15:31:15 -0400826 {
John Lo1edfba92016-08-27 01:11:57 -0400827 ip6_address_t *ip6_addr_key;
828 hash_pair_t *hp;
Neale Ranns4d5b9172018-10-24 02:57:49 -0700829 old_mac = (u64 *) hash_get_mem (bd_cfg->mac_by_ip6, &ip->ip6);
John Lo1edfba92016-08-27 01:11:57 -0400830 if (is_add)
831 {
Neale Ranns4d5b9172018-10-24 02:57:49 -0700832 if (old_mac == NULL)
833 {
834 /* new entry - allocate and create ip6 address key */
John Lo1edfba92016-08-27 01:11:57 -0400835 ip6_addr_key = clib_mem_alloc (sizeof (ip6_address_t));
Neale Ranns4d5b9172018-10-24 02:57:49 -0700836 clib_memcpy (ip6_addr_key, &ip->ip6, sizeof (ip6_address_t));
John Lo1edfba92016-08-27 01:11:57 -0400837 }
838 else if (*old_mac == new_mac)
Neale Ranns4d5b9172018-10-24 02:57:49 -0700839 {
840 /* same mac entry already exist for ip6 address */
John Lo1edfba92016-08-27 01:11:57 -0400841 return 0;
842 }
843 else
Neale Ranns4d5b9172018-10-24 02:57:49 -0700844 {
845 /* update mac for ip6 address */
846 hp = hash_get_pair (bd_cfg->mac_by_ip6, &ip->ip6);
John Lo1edfba92016-08-27 01:11:57 -0400847 ip6_addr_key = (ip6_address_t *) hp->key;
848 }
849 hash_set_mem (bd_cfg->mac_by_ip6, ip6_addr_key, new_mac);
850 }
851 else
852 {
853 if (old_mac && (*old_mac == new_mac))
854 {
Neale Ranns4d5b9172018-10-24 02:57:49 -0700855 hp = hash_get_pair (bd_cfg->mac_by_ip6, &ip->ip6);
John Lo1edfba92016-08-27 01:11:57 -0400856 ip6_addr_key = (ip6_address_t *) hp->key;
Neale Ranns4d5b9172018-10-24 02:57:49 -0700857 hash_unset_mem (bd_cfg->mac_by_ip6, &ip->ip6);
John Lo1edfba92016-08-27 01:11:57 -0400858 clib_mem_free (ip6_addr_key);
859 }
860 else
861 return 1;
862 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700863 }
Dave Barach97d8dc22016-08-15 15:31:15 -0400864 else
865 {
Neale Ranns4d5b9172018-10-24 02:57:49 -0700866 old_mac = (u64 *) hash_get (bd_cfg->mac_by_ip4, ip->ip4.as_u32);
Dave Barach97d8dc22016-08-15 15:31:15 -0400867 if (is_add)
868 {
Dave Barach97d8dc22016-08-15 15:31:15 -0400869 if (old_mac && (*old_mac == new_mac))
Neale Ranns4d5b9172018-10-24 02:57:49 -0700870 /* mac entry already exist */
871 return 0;
872 hash_set (bd_cfg->mac_by_ip4, ip->ip4.as_u32, new_mac);
Dave Barach97d8dc22016-08-15 15:31:15 -0400873 }
874 else
875 {
Dave Barach97d8dc22016-08-15 15:31:15 -0400876 if (old_mac && (*old_mac == new_mac))
Neale Ranns4d5b9172018-10-24 02:57:49 -0700877 hash_unset (bd_cfg->mac_by_ip4, ip->ip4.as_u32);
Dave Barach97d8dc22016-08-15 15:31:15 -0400878 else
John Lo1edfba92016-08-27 01:11:57 -0400879 return 1;
Dave Barach97d8dc22016-08-15 15:31:15 -0400880 }
Dave Barach97d8dc22016-08-15 15:31:15 -0400881 }
John Lo1edfba92016-08-27 01:11:57 -0400882 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700883}
884
Dave Barach97d8dc22016-08-15 15:31:15 -0400885/**
John Loe26c81f2019-01-07 15:16:33 -0500886 * Flush IP address to MAC address mapping tables in a BD.
887 */
888void
889bd_flush_ip_mac (u32 bd_index)
890{
891 l2_bridge_domain_t *bd = l2input_bd_config (bd_index);
892 ASSERT (bd_is_valid (bd));
893 bd_free_ip_mac_tables (bd);
894 bd->mac_by_ip4 = 0;
895 bd->mac_by_ip6 =
896 hash_create_mem (0, sizeof (ip6_address_t), sizeof (uword));
897}
898
899/**
Chris Luke16bcf7d2016-09-01 14:31:46 -0400900 Set bridge-domain arp entry add/delete.
Dave Barach97d8dc22016-08-15 15:31:15 -0400901 The CLI format is:
Billy McFall22aa3e92016-09-09 08:46:40 -0400902 set bridge-domain arp entry <bridge-domain-id> <ip-addr> <mac-addr> [del]
Dave Barach97d8dc22016-08-15 15:31:15 -0400903*/
Ed Warnickecb9cada2015-12-08 15:45:58 -0700904static clib_error_t *
905bd_arp_entry (vlib_main_t * vm,
Dave Barach97d8dc22016-08-15 15:31:15 -0400906 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700907{
Neale Ranns4d5b9172018-10-24 02:57:49 -0700908 ip46_address_t ip_addr = ip46_address_initializer;
909 ip46_type_t type = IP46_TYPE_IP4;
Dave Barach97d8dc22016-08-15 15:31:15 -0400910 bd_main_t *bdm = &bd_main;
911 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700912 u32 bd_index, bd_id;
Neale Ranns4d5b9172018-10-24 02:57:49 -0700913 mac_address_t mac;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700914 u8 is_add = 1;
Dave Barach97d8dc22016-08-15 15:31:15 -0400915 uword *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700916
Dave Barach97d8dc22016-08-15 15:31:15 -0400917 if (!unformat (input, "%d", &bd_id))
918 {
919 error = clib_error_return (0, "expecting bridge-domain id but got `%U'",
920 format_unformat_error, input);
921 goto done;
922 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700923
Jon Loeliger1c7d4852017-05-02 11:06:23 -0500924 if (bd_id == 0)
925 return clib_error_return (0,
926 "No operations on the default bridge domain are supported");
927
Ed Warnickecb9cada2015-12-08 15:45:58 -0700928 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
929
Dave Barach97d8dc22016-08-15 15:31:15 -0400930 if (p)
931 bd_index = *p;
932 else
933 return clib_error_return (0, "No such bridge domain %d", bd_id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700934
Neale Ranns4d5b9172018-10-24 02:57:49 -0700935 if (unformat (input, "%U", unformat_ip4_address, &ip_addr.ip4))
Dave Barach97d8dc22016-08-15 15:31:15 -0400936 {
Neale Ranns4d5b9172018-10-24 02:57:49 -0700937 type = IP46_TYPE_IP4;
Dave Barach97d8dc22016-08-15 15:31:15 -0400938 }
Neale Ranns4d5b9172018-10-24 02:57:49 -0700939 else if (unformat (input, "%U", unformat_ip6_address, &ip_addr.ip6))
Dave Barach97d8dc22016-08-15 15:31:15 -0400940 {
Neale Ranns4d5b9172018-10-24 02:57:49 -0700941 type = IP46_TYPE_IP6;
Dave Barach97d8dc22016-08-15 15:31:15 -0400942 }
John Loe26c81f2019-01-07 15:16:33 -0500943 else if (unformat (input, "del-all"))
944 {
945 bd_flush_ip_mac (bd_index);
946 goto done;
947 }
Dave Barach97d8dc22016-08-15 15:31:15 -0400948 else
949 {
950 error = clib_error_return (0, "expecting IP address but got `%U'",
951 format_unformat_error, input);
952 goto done;
953 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700954
Neale Ranns4d5b9172018-10-24 02:57:49 -0700955 if (!unformat (input, "%U", unformat_mac_address_t, &mac))
Dave Barach97d8dc22016-08-15 15:31:15 -0400956 {
957 error = clib_error_return (0, "expecting MAC address but got `%U'",
958 format_unformat_error, input);
959 goto done;
960 }
961
962 if (unformat (input, "del"))
963 {
964 is_add = 0;
965 }
966
967 /* set the bridge domain flagAdd IP-MAC entry into bridge domain */
Neale Ranns4d5b9172018-10-24 02:57:49 -0700968 if (bd_add_del_ip_mac (bd_index, type, &ip_addr, &mac, is_add))
Dave Barach97d8dc22016-08-15 15:31:15 -0400969 {
970 error = clib_error_return (0, "MAC %s for IP %U and MAC %U failed",
971 is_add ? "add" : "del",
Neale Ranns4d5b9172018-10-24 02:57:49 -0700972 format_ip46_address, &ip_addr, IP46_TYPE_ANY,
973 format_mac_address_t, &mac);
Dave Barach97d8dc22016-08-15 15:31:15 -0400974 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700975
976done:
977 return error;
978}
979
Billy McFall22aa3e92016-09-09 08:46:40 -0400980/*?
981 * Add an ARP entry to an existing bridge-domain.
982 *
983 * @cliexpar
984 * Example of how to add an ARP entry (where 200 is the bridge-domain-id):
985 * @cliexcmd{set bridge-domain arp entry 200 192.168.72.45 52:54:00:3b:83:1a}
986 * Example of how to delete an ARP entry (where 200 is the bridge-domain-id):
987 * @cliexcmd{set bridge-domain arp entry 200 192.168.72.45 52:54:00:3b:83:1a del}
988?*/
Dave Barach97d8dc22016-08-15 15:31:15 -0400989/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700990VLIB_CLI_COMMAND (bd_arp_entry_cli, static) = {
991 .path = "set bridge-domain arp entry",
John Loe26c81f2019-01-07 15:16:33 -0500992 .short_help = "set bridge-domain arp entry <bridge-domain-id> [<ip-addr> <mac-addr> [del] | del-all]",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700993 .function = bd_arp_entry,
994};
Dave Barach97d8dc22016-08-15 15:31:15 -0400995/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700996
Neale Rannsb4743802018-09-05 09:13:57 -0700997static u8 *
Dave Barach97d8dc22016-08-15 15:31:15 -0400998format_vtr (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700999{
Dave Barach97d8dc22016-08-15 15:31:15 -04001000 u32 vtr_op = va_arg (*args, u32);
1001 u32 dot1q = va_arg (*args, u32);
1002 u32 tag1 = va_arg (*args, u32);
1003 u32 tag2 = va_arg (*args, u32);
1004 switch (vtr_op)
1005 {
Ed Warnickecb9cada2015-12-08 15:45:58 -07001006 case L2_VTR_DISABLED:
Dave Barach97d8dc22016-08-15 15:31:15 -04001007 return format (s, "none");
Ed Warnickecb9cada2015-12-08 15:45:58 -07001008 case L2_VTR_PUSH_1:
Dave Barach97d8dc22016-08-15 15:31:15 -04001009 return format (s, "push-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001010 case L2_VTR_PUSH_2:
Dave Barach97d8dc22016-08-15 15:31:15 -04001011 return format (s, "push-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", tag1,
1012 tag2);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001013 case L2_VTR_POP_1:
Dave Barach97d8dc22016-08-15 15:31:15 -04001014 return format (s, "pop-1");
Ed Warnickecb9cada2015-12-08 15:45:58 -07001015 case L2_VTR_POP_2:
Dave Barach97d8dc22016-08-15 15:31:15 -04001016 return format (s, "pop-2");
Ed Warnickecb9cada2015-12-08 15:45:58 -07001017 case L2_VTR_TRANSLATE_1_1:
Dave Barach97d8dc22016-08-15 15:31:15 -04001018 return format (s, "trans-1-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001019 case L2_VTR_TRANSLATE_1_2:
Dave Barach97d8dc22016-08-15 15:31:15 -04001020 return format (s, "trans-1-2 %s %d %d", dot1q ? "dot1q" : "dot1ad",
1021 tag1, tag2);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001022 case L2_VTR_TRANSLATE_2_1:
Dave Barach97d8dc22016-08-15 15:31:15 -04001023 return format (s, "trans-2-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001024 case L2_VTR_TRANSLATE_2_2:
Dave Barach97d8dc22016-08-15 15:31:15 -04001025 return format (s, "trans-2-2 %s %d %d", dot1q ? "dot1q" : "dot1ad",
1026 tag1, tag2);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001027 default:
Dave Barach97d8dc22016-08-15 15:31:15 -04001028 return format (s, "none");
Ed Warnickecb9cada2015-12-08 15:45:58 -07001029 }
1030}
1031
Neale Rannsb4743802018-09-05 09:13:57 -07001032static u8 *
1033format_uu_cfg (u8 * s, va_list * args)
1034{
1035 l2_bridge_domain_t *bd_config = va_arg (*args, l2_bridge_domain_t *);
1036
1037 if (bd_config->feature_bitmap & L2INPUT_FEAT_UU_FWD)
1038 return (format (s, "%U", format_vnet_sw_if_index_name_with_NA,
1039 vnet_get_main (), bd_config->uu_fwd_sw_if_index));
1040 else if (bd_config->feature_bitmap & L2INPUT_FEAT_UU_FLOOD)
1041 return (format (s, "flood"));
1042 else
1043 return (format (s, "drop"));
1044}
1045
Dave Barach97d8dc22016-08-15 15:31:15 -04001046/**
Chris Luke16bcf7d2016-09-01 14:31:46 -04001047 Show bridge-domain state.
Dave Barach97d8dc22016-08-15 15:31:15 -04001048 The CLI format is:
1049 show bridge-domain [<bd_index>]
1050*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07001051static clib_error_t *
Dave Barach97d8dc22016-08-15 15:31:15 -04001052bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001053{
Dave Barach97d8dc22016-08-15 15:31:15 -04001054 vnet_main_t *vnm = vnet_get_main ();
1055 bd_main_t *bdm = &bd_main;
1056 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001057 u32 bd_index = ~0;
Dave Barach97d8dc22016-08-15 15:31:15 -04001058 l2_bridge_domain_t *bd_config;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001059 u32 start, end;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001060 u32 detail = 0;
1061 u32 intf = 0;
1062 u32 arp = 0;
Jerome Tollet48304142017-09-05 12:13:22 +01001063 u32 bd_tag = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001064 u32 bd_id = ~0;
Dave Barach97d8dc22016-08-15 15:31:15 -04001065 uword *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001066
Jon Loeliger1c7d4852017-05-02 11:06:23 -05001067 start = 1;
Dave Barach97d8dc22016-08-15 15:31:15 -04001068 end = vec_len (l2input_main.bd_configs);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001069
Dave Barach97d8dc22016-08-15 15:31:15 -04001070 if (unformat (input, "%d", &bd_id))
1071 {
1072 if (unformat (input, "detail"))
1073 detail = 1;
1074 else if (unformat (input, "det"))
1075 detail = 1;
1076 if (unformat (input, "int"))
1077 intf = 1;
1078 if (unformat (input, "arp"))
1079 arp = 1;
Jerome Tollet48304142017-09-05 12:13:22 +01001080 if (unformat (input, "bd-tag"))
1081 bd_tag = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001082
Jon Loeliger1c7d4852017-05-02 11:06:23 -05001083 if (bd_id == 0)
1084 return clib_error_return (0,
1085 "No operations on the default bridge domain are supported");
1086
Dave Barach97d8dc22016-08-15 15:31:15 -04001087 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1088 if (p)
1089 bd_index = *p;
1090 else
1091 return clib_error_return (0, "No such bridge domain %d", bd_id);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001092
Dave Barach97d8dc22016-08-15 15:31:15 -04001093 vec_validate (l2input_main.bd_configs, bd_index);
1094 bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
1095 if (bd_is_valid (bd_config))
1096 {
1097 start = bd_index;
1098 end = start + 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001099 }
Dave Barach97d8dc22016-08-15 15:31:15 -04001100 else
1101 {
1102 vlib_cli_output (vm, "bridge-domain %d not in use", bd_id);
1103 goto done;
1104 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001105 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001106
Dave Barach97d8dc22016-08-15 15:31:15 -04001107 /* Show all bridge-domains that have been initialized */
John Loda1f2c72017-03-24 20:11:15 -04001108 u32 printed = 0;
1109 u8 *as = 0;
Dave Barach97d8dc22016-08-15 15:31:15 -04001110 for (bd_index = start; bd_index < end; bd_index++)
1111 {
1112 bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
1113 if (bd_is_valid (bd_config))
1114 {
1115 if (!printed)
1116 {
1117 printed = 1;
1118 vlib_cli_output (vm,
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001119 "%=8s %=7s %=4s %=9s %=9s %=9s %=11s %=9s %=9s %=9s %=11s",
John Lo97934772017-05-18 22:26:47 -04001120 "BD-ID", "Index", "BSN", "Age(min)",
Neale Rannsb4743802018-09-05 09:13:57 -07001121 "Learning", "U-Forwrd", "UU-Flood",
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001122 "Flooding", "ARP-Term", "arp-ufwd",
1123 "BVI-Intf");
Dave Barach97d8dc22016-08-15 15:31:15 -04001124 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001125
John Loda1f2c72017-03-24 20:11:15 -04001126 if (bd_config->mac_age)
1127 as = format (as, "%d", bd_config->mac_age);
1128 else
1129 as = format (as, "off");
Dave Barach97d8dc22016-08-15 15:31:15 -04001130 vlib_cli_output (vm,
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001131 "%=8d %=7d %=4d %=9v %=9s %=9s %=11U %=9s %=9s %=9s %=11U",
John Loda1f2c72017-03-24 20:11:15 -04001132 bd_config->bd_id, bd_index, bd_config->seq_num, as,
Dave Barach97d8dc22016-08-15 15:31:15 -04001133 bd_config->feature_bitmap & L2INPUT_FEAT_LEARN ?
1134 "on" : "off",
John Loda1f2c72017-03-24 20:11:15 -04001135 bd_config->feature_bitmap & L2INPUT_FEAT_FWD ?
1136 "on" : "off",
Neale Rannsb4743802018-09-05 09:13:57 -07001137 format_uu_cfg, bd_config,
Dave Barach97d8dc22016-08-15 15:31:15 -04001138 bd_config->feature_bitmap & L2INPUT_FEAT_FLOOD ?
1139 "on" : "off",
1140 bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM ?
John Loda1f2c72017-03-24 20:11:15 -04001141 "on" : "off",
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001142 bd_config->feature_bitmap & L2INPUT_FEAT_ARP_UFWD ?
1143 "on" : "off",
John Loda1f2c72017-03-24 20:11:15 -04001144 format_vnet_sw_if_index_name_with_NA,
Dave Barach97d8dc22016-08-15 15:31:15 -04001145 vnm, bd_config->bvi_sw_if_index);
John Loda1f2c72017-03-24 20:11:15 -04001146 vec_reset_length (as);
Dave Barach97d8dc22016-08-15 15:31:15 -04001147
1148 if (detail || intf)
1149 {
1150 /* Show all member interfaces */
Eyal Baric5b13602016-11-24 19:42:43 +02001151 int i;
1152 vec_foreach_index (i, bd_config->members)
Dave Barach97d8dc22016-08-15 15:31:15 -04001153 {
Eyal Baric5b13602016-11-24 19:42:43 +02001154 l2_flood_member_t *member =
1155 vec_elt_at_index (bd_config->members, i);
Eyal Bari0f360dc2017-06-14 13:11:20 +03001156 u8 swif_seq_num = *l2fib_swif_seq_num (member->sw_if_index);
Dave Barach97d8dc22016-08-15 15:31:15 -04001157 u32 vtr_opr, dot1q, tag1, tag2;
Eyal Baric5b13602016-11-24 19:42:43 +02001158 if (i == 0)
Dave Barach97d8dc22016-08-15 15:31:15 -04001159 {
John Loda1f2c72017-03-24 20:11:15 -04001160 vlib_cli_output (vm, "\n%=30s%=7s%=5s%=5s%=5s%=9s%=30s",
1161 "Interface", "If-idx", "ISN", "SHG",
1162 "BVI", "TxFlood", "VLAN-Tag-Rewrite");
Dave Barach97d8dc22016-08-15 15:31:15 -04001163 }
1164 l2vtr_get (vm, vnm, member->sw_if_index, &vtr_opr, &dot1q,
1165 &tag1, &tag2);
John Loda1f2c72017-03-24 20:11:15 -04001166 vlib_cli_output (vm, "%=30U%=7d%=5d%=5d%=5s%=9s%=30U",
Dave Barach97d8dc22016-08-15 15:31:15 -04001167 format_vnet_sw_if_index_name, vnm,
1168 member->sw_if_index, member->sw_if_index,
Eyal Bari0f360dc2017-06-14 13:11:20 +03001169 swif_seq_num, member->shg,
Dave Barach97d8dc22016-08-15 15:31:15 -04001170 member->flags & L2_FLOOD_MEMBER_BVI ? "*" :
Eyal Baric5b13602016-11-24 19:42:43 +02001171 "-", i < bd_config->flood_count ? "*" : "-",
1172 format_vtr, vtr_opr, dot1q, tag1, tag2);
Dave Barach97d8dc22016-08-15 15:31:15 -04001173 }
Neale Rannsb4743802018-09-05 09:13:57 -07001174 if (~0 != bd_config->uu_fwd_sw_if_index)
1175 vlib_cli_output (vm, "%=30U%=7d%=5d%=5d%=5s%=9s%=30s",
1176 format_vnet_sw_if_index_name, vnm,
1177 bd_config->uu_fwd_sw_if_index,
1178 bd_config->uu_fwd_sw_if_index,
1179 0, 0, "uu", "-", "None");
1180
Dave Barach97d8dc22016-08-15 15:31:15 -04001181 }
1182
1183 if ((detail || arp) &&
1184 (bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM))
1185 {
1186 u32 ip4_addr;
John Lo1edfba92016-08-27 01:11:57 -04001187 ip6_address_t *ip6_addr;
Dave Barach97d8dc22016-08-15 15:31:15 -04001188 u64 mac_addr;
1189 vlib_cli_output (vm,
John Lo1edfba92016-08-27 01:11:57 -04001190 "\n IP4/IP6 to MAC table for ARP Termination");
Dave Barach97d8dc22016-08-15 15:31:15 -04001191
1192 /* *INDENT-OFF* */
1193 hash_foreach (ip4_addr, mac_addr, bd_config->mac_by_ip4,
1194 ({
John Lo1edfba92016-08-27 01:11:57 -04001195 vlib_cli_output (vm, "%=40U => %=20U",
Dave Barach97d8dc22016-08-15 15:31:15 -04001196 format_ip4_address, &ip4_addr,
1197 format_ethernet_address, &mac_addr);
1198 }));
John Lo1edfba92016-08-27 01:11:57 -04001199
1200 hash_foreach_mem (ip6_addr, mac_addr, bd_config->mac_by_ip6,
1201 ({
1202 vlib_cli_output (vm, "%=40U => %=20U",
1203 format_ip6_address, ip6_addr,
1204 format_ethernet_address, &mac_addr);
1205 }));
Dave Barach97d8dc22016-08-15 15:31:15 -04001206 /* *INDENT-ON* */
1207 }
Jerome Tollet48304142017-09-05 12:13:22 +01001208
1209 if ((detail || bd_tag) && (bd_config->bd_tag))
1210 {
1211 vlib_cli_output (vm, "\n BD-Tag: %s", bd_config->bd_tag);
1212
1213 }
Dave Barach97d8dc22016-08-15 15:31:15 -04001214 }
1215 }
John Loda1f2c72017-03-24 20:11:15 -04001216 vec_free (as);
Dave Barach97d8dc22016-08-15 15:31:15 -04001217
1218 if (!printed)
1219 {
1220 vlib_cli_output (vm, "no bridge-domains in use");
1221 }
1222
1223done:
Ed Warnickecb9cada2015-12-08 15:45:58 -07001224 return error;
1225}
1226
Billy McFall22aa3e92016-09-09 08:46:40 -04001227/*?
1228 * Show a summary of all the bridge-domain instances or detailed view of a
1229 * single bridge-domain. Bridge-domains are created by adding an interface
1230 * to a bridge using the '<em>set interface l2 bridge</em>' command.
1231 *
1232 * @cliexpar
1233 * @parblock
1234 * Example of displaying all bridge-domains:
1235 * @cliexstart{show bridge-domain}
1236 * ID Index Learning U-Forwrd UU-Flood Flooding ARP-Term BVI-Intf
1237 * 0 0 off off off off off local0
1238 * 200 1 on on on on off N/A
1239 * @cliexend
1240 *
1241 * Example of displaying details of a single bridge-domains:
1242 * @cliexstart{show bridge-domain 200 detail}
1243 * ID Index Learning U-Forwrd UU-Flood Flooding ARP-Term BVI-Intf
1244 * 200 1 on on on on off N/A
1245 *
1246 * Interface Index SHG BVI VLAN-Tag-Rewrite
1247 * GigabitEthernet0/8/0.200 3 0 - none
1248 * GigabitEthernet0/9/0.200 4 0 - none
1249 * @cliexend
1250 * @endparblock
1251?*/
Dave Barach97d8dc22016-08-15 15:31:15 -04001252/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001253VLIB_CLI_COMMAND (bd_show_cli, static) = {
1254 .path = "show bridge-domain",
Jerome Tollet48304142017-09-05 12:13:22 +01001255 .short_help = "show bridge-domain [bridge-domain-id [detail|int|arp|bd-tag]]",
Ed Warnickecb9cada2015-12-08 15:45:58 -07001256 .function = bd_show,
1257};
Dave Barach97d8dc22016-08-15 15:31:15 -04001258/* *INDENT-ON* */
1259
Choonho Son05480792017-03-29 20:07:45 +09001260int
1261bd_add_del (l2_bridge_domain_add_del_args_t * a)
1262{
1263 bd_main_t *bdm = &bd_main;
1264 vlib_main_t *vm = bdm->vlib_main;
Choonho Son05480792017-03-29 20:07:45 +09001265 int rv = 0;
1266
Eyal Barib1352ed2017-04-07 23:14:17 +03001267 u32 bd_index = bd_find_index (bdm, a->bd_id);
Choonho Son05480792017-03-29 20:07:45 +09001268 if (a->is_add)
1269 {
Eyal Barib1352ed2017-04-07 23:14:17 +03001270 if (bd_index != ~0)
1271 return VNET_API_ERROR_BD_ALREADY_EXISTS;
John Lo97934772017-05-18 22:26:47 -04001272 if (a->bd_id > L2_BD_ID_MAX)
1273 return VNET_API_ERROR_BD_ID_EXCEED_MAX;
Eyal Barib1352ed2017-04-07 23:14:17 +03001274 bd_index = bd_add_bd_index (bdm, a->bd_id);
Choonho Son05480792017-03-29 20:07:45 +09001275
Neale Rannsb4743802018-09-05 09:13:57 -07001276 bd_flags_t enable_flags = 0, disable_flags = 0;
Choonho Son05480792017-03-29 20:07:45 +09001277 if (a->flood)
1278 enable_flags |= L2_FLOOD;
1279 else
1280 disable_flags |= L2_FLOOD;
1281
1282 if (a->uu_flood)
1283 enable_flags |= L2_UU_FLOOD;
1284 else
1285 disable_flags |= L2_UU_FLOOD;
1286
1287 if (a->forward)
1288 enable_flags |= L2_FWD;
1289 else
1290 disable_flags |= L2_FWD;
1291
1292 if (a->learn)
1293 enable_flags |= L2_LEARN;
1294 else
1295 disable_flags |= L2_LEARN;
1296
1297 if (a->arp_term)
1298 enable_flags |= L2_ARP_TERM;
1299 else
1300 disable_flags |= L2_ARP_TERM;
1301
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001302 if (a->arp_ufwd)
1303 enable_flags |= L2_ARP_UFWD;
1304 else
1305 disable_flags |= L2_ARP_UFWD;
1306
Choonho Son05480792017-03-29 20:07:45 +09001307 if (enable_flags)
1308 bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */ );
1309
1310 if (disable_flags)
1311 bd_set_flags (vm, bd_index, disable_flags, 0 /* disable */ );
1312
1313 bd_set_mac_age (vm, bd_index, a->mac_age);
Jerome Tollet48304142017-09-05 12:13:22 +01001314
1315 if (a->bd_tag)
1316 bd_set_bd_tag (vm, bd_index, a->bd_tag);
1317
Choonho Son05480792017-03-29 20:07:45 +09001318 }
1319 else
Eyal Barib1352ed2017-04-07 23:14:17 +03001320 {
1321 if (bd_index == ~0)
1322 return VNET_API_ERROR_NO_SUCH_ENTRY;
Jon Loeliger1c7d4852017-05-02 11:06:23 -05001323 if (bd_index == 0)
1324 return VNET_API_ERROR_BD_NOT_MODIFIABLE;
Eyal Barib1352ed2017-04-07 23:14:17 +03001325 if (vec_len (l2input_main.bd_configs[bd_index].members))
1326 return VNET_API_ERROR_BD_IN_USE;
1327 rv = bd_delete (bdm, bd_index);
1328 }
Choonho Son05480792017-03-29 20:07:45 +09001329
1330 return rv;
1331}
1332
1333/**
1334 Create or delete bridge-domain.
Choonho Son5ee51f82017-04-05 19:09:52 +09001335 The CLI format:
Jerome Tollet50570ec2017-09-14 12:53:56 +01001336 create bridge-domain <bd_index> [learn <0|1>] [forward <0|1>] [uu-flood <0|1>] [flood <0|1>]
1337 [arp-term <0|1>] [mac-age <nn>] [bd-tag <tag>] [del]
Choonho Son05480792017-03-29 20:07:45 +09001338*/
1339
1340static clib_error_t *
1341bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input,
1342 vlib_cli_command_t * cmd)
1343{
1344 unformat_input_t _line_input, *line_input = &_line_input;
1345 clib_error_t *error = 0;
1346 u8 is_add = 1;
1347 u32 bd_id = ~0;
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001348 u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term =
1349 0, arp_ufwd = 0;
Choonho Son05480792017-03-29 20:07:45 +09001350 u32 mac_age = 0;
Jerome Tollet48304142017-09-05 12:13:22 +01001351 u8 *bd_tag = NULL;
Choonho Son05480792017-03-29 20:07:45 +09001352 l2_bridge_domain_add_del_args_t _a, *a = &_a;
1353 int rv;
1354
1355 /* Get a line of input. */
1356 if (!unformat_user (input, unformat_line_input, line_input))
1357 return 0;
1358
1359 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1360 {
1361 if (unformat (line_input, "%d", &bd_id))
1362 ;
1363 else if (unformat (line_input, "flood %d", &flood))
1364 ;
1365 else if (unformat (line_input, "uu-flood %d", &uu_flood))
1366 ;
1367 else if (unformat (line_input, "forward %d", &forward))
1368 ;
Choonho Son5ee51f82017-04-05 19:09:52 +09001369 else if (unformat (line_input, "learn %d", &learn))
1370 ;
Choonho Son05480792017-03-29 20:07:45 +09001371 else if (unformat (line_input, "arp-term %d", &arp_term))
1372 ;
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001373 else if (unformat (line_input, "arp-ufwd %d", &arp_ufwd))
1374 ;
Choonho Son05480792017-03-29 20:07:45 +09001375 else if (unformat (line_input, "mac-age %d", &mac_age))
1376 ;
Jerome Tollet48304142017-09-05 12:13:22 +01001377 else if (unformat (line_input, "bd-tag %s", &bd_tag))
1378 ;
Choonho Son05480792017-03-29 20:07:45 +09001379 else if (unformat (line_input, "del"))
1380 {
1381 is_add = 0;
1382 flood = uu_flood = forward = learn = 0;
1383 }
1384 else
1385 break;
1386 }
1387
1388 if (bd_id == ~0)
1389 {
1390 error = clib_error_return (0, "bridge-domain-id not specified");
1391 goto done;
1392 }
1393
Jon Loeliger1c7d4852017-05-02 11:06:23 -05001394 if (bd_id == 0)
1395 {
1396 error = clib_error_return (0, "bridge domain 0 can not be modified");
1397 goto done;
1398 }
1399
Choonho Son05480792017-03-29 20:07:45 +09001400 if (mac_age > 255)
1401 {
1402 error = clib_error_return (0, "mac age must be less than 256");
1403 goto done;
1404 }
Jerome Tollet48304142017-09-05 12:13:22 +01001405 if ((bd_tag) && (strlen ((char *) bd_tag) > 63))
1406 {
1407 error = clib_error_return (0, "bd-tag cannot be longer than 63");
1408 goto done;
1409 }
Choonho Son05480792017-03-29 20:07:45 +09001410
Dave Barachb7b92992018-10-17 10:38:51 -04001411 clib_memset (a, 0, sizeof (*a));
Choonho Son05480792017-03-29 20:07:45 +09001412 a->is_add = is_add;
1413 a->bd_id = bd_id;
1414 a->flood = (u8) flood;
1415 a->uu_flood = (u8) uu_flood;
1416 a->forward = (u8) forward;
1417 a->learn = (u8) learn;
1418 a->arp_term = (u8) arp_term;
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001419 a->arp_ufwd = (u8) arp_ufwd;
Choonho Son05480792017-03-29 20:07:45 +09001420 a->mac_age = (u8) mac_age;
Jerome Tollet48304142017-09-05 12:13:22 +01001421 a->bd_tag = bd_tag;
Choonho Son05480792017-03-29 20:07:45 +09001422
1423 rv = bd_add_del (a);
1424
1425 switch (rv)
1426 {
1427 case 0:
1428 if (is_add)
1429 vlib_cli_output (vm, "bridge-domain %d", bd_id);
1430 break;
Eyal Barib1352ed2017-04-07 23:14:17 +03001431 case VNET_API_ERROR_BD_IN_USE:
1432 error = clib_error_return (0, "bridge domain in use - remove members");
1433 goto done;
Choonho Son05480792017-03-29 20:07:45 +09001434 case VNET_API_ERROR_NO_SUCH_ENTRY:
John Lo97934772017-05-18 22:26:47 -04001435 error = clib_error_return (0, "bridge domain ID does not exist");
Choonho Son05480792017-03-29 20:07:45 +09001436 goto done;
Jon Loeliger1c7d4852017-05-02 11:06:23 -05001437 case VNET_API_ERROR_BD_NOT_MODIFIABLE:
1438 error = clib_error_return (0, "bridge domain 0 can not be modified");
1439 goto done;
John Lo97934772017-05-18 22:26:47 -04001440 case VNET_API_ERROR_BD_ID_EXCEED_MAX:
1441 error = clib_error_return (0, "bridge domain ID exceed 16M limit");
1442 goto done;
Choonho Son05480792017-03-29 20:07:45 +09001443 default:
1444 error = clib_error_return (0, "bd_add_del returned %d", rv);
1445 goto done;
1446 }
1447
1448done:
Jerome Tollet48304142017-09-05 12:13:22 +01001449 vec_free (bd_tag);
Choonho Son05480792017-03-29 20:07:45 +09001450 unformat_free (line_input);
1451
1452 return error;
1453}
1454
1455
1456/*?
1457 * Create/Delete bridge-domain instance
1458 *
1459 * @cliexpar
1460 * @parblock
1461 * Example of creating bridge-domain 1:
1462 * @cliexstart{create bridge-domain 1}
1463 * bridge-domain 1
1464 * @cliexend
1465 *
1466 * Example of creating bridge-domain 2 with enabling arp-term, mac-age 60:
1467 * @cliexstart{create bridge-domain 2 arp-term 1 mac-age 60}
1468 * bridge-domain 2
1469 *
1470 * vpp# show bridge-domain
1471 * ID Index BSN Age(min) Learning U-Forwrd UU-Flood Flooding ARP-Term BVI-Intf
1472 * 0 0 0 off off off off off off local0
1473 * 1 1 0 off on on off on off N/A
1474 * 2 2 0 60 on on off on on N/A
1475 *
1476 * @cliexend
1477 *
1478 * Example of delete bridge-domain 1:
1479 * @cliexstart{create bridge-domain 1 del}
1480 * @cliexend
1481 * @endparblock
1482?*/
1483
1484/* *INDENT-OFF* */
1485VLIB_CLI_COMMAND (bd_create_cli, static) = {
1486 .path = "create bridge-domain",
1487 .short_help = "create bridge-domain <bridge-domain-id>"
1488 " [learn <0|1>] [forward <0|1>] [uu-flood <0|1>] [flood <0|1>] [arp-term <0|1>]"
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001489 " [arp-ufwd <0|1>] [mac-age <nn>] [bd-tag <tag>] [del]",
Choonho Son05480792017-03-29 20:07:45 +09001490 .function = bd_add_del_command_fn,
1491};
1492/* *INDENT-ON* */
1493
1494
1495
Dave Barach97d8dc22016-08-15 15:31:15 -04001496/*
1497 * fd.io coding-style-patch-verification: ON
1498 *
1499 * Local Variables:
1500 * eval: (c-set-style "gnu")
1501 * End:
1502 */