blob: e54d437f0ea2a15612ed7b0a6200048979a7bd08 [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 *
Neale Rannsb4743802018-09-05 09:13:57 -0700998format_uu_cfg (u8 * s, va_list * args)
999{
1000 l2_bridge_domain_t *bd_config = va_arg (*args, l2_bridge_domain_t *);
1001
1002 if (bd_config->feature_bitmap & L2INPUT_FEAT_UU_FWD)
1003 return (format (s, "%U", format_vnet_sw_if_index_name_with_NA,
1004 vnet_get_main (), bd_config->uu_fwd_sw_if_index));
1005 else if (bd_config->feature_bitmap & L2INPUT_FEAT_UU_FLOOD)
1006 return (format (s, "flood"));
1007 else
1008 return (format (s, "drop"));
1009}
1010
Dave Barach97d8dc22016-08-15 15:31:15 -04001011/**
Chris Luke16bcf7d2016-09-01 14:31:46 -04001012 Show bridge-domain state.
Dave Barach97d8dc22016-08-15 15:31:15 -04001013 The CLI format is:
1014 show bridge-domain [<bd_index>]
1015*/
Ed Warnickecb9cada2015-12-08 15:45:58 -07001016static clib_error_t *
Dave Barach97d8dc22016-08-15 15:31:15 -04001017bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001018{
Dave Barach97d8dc22016-08-15 15:31:15 -04001019 vnet_main_t *vnm = vnet_get_main ();
1020 bd_main_t *bdm = &bd_main;
1021 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001022 u32 bd_index = ~0;
Dave Barach97d8dc22016-08-15 15:31:15 -04001023 l2_bridge_domain_t *bd_config;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001024 u32 start, end;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001025 u32 detail = 0;
1026 u32 intf = 0;
1027 u32 arp = 0;
Jerome Tollet48304142017-09-05 12:13:22 +01001028 u32 bd_tag = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001029 u32 bd_id = ~0;
Dave Barach97d8dc22016-08-15 15:31:15 -04001030 uword *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001031
Jon Loeliger1c7d4852017-05-02 11:06:23 -05001032 start = 1;
Dave Barach97d8dc22016-08-15 15:31:15 -04001033 end = vec_len (l2input_main.bd_configs);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001034
Dave Barach97d8dc22016-08-15 15:31:15 -04001035 if (unformat (input, "%d", &bd_id))
1036 {
1037 if (unformat (input, "detail"))
1038 detail = 1;
1039 else if (unformat (input, "det"))
1040 detail = 1;
1041 if (unformat (input, "int"))
1042 intf = 1;
1043 if (unformat (input, "arp"))
1044 arp = 1;
Jerome Tollet48304142017-09-05 12:13:22 +01001045 if (unformat (input, "bd-tag"))
1046 bd_tag = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001047
Jon Loeliger1c7d4852017-05-02 11:06:23 -05001048 if (bd_id == 0)
1049 return clib_error_return (0,
1050 "No operations on the default bridge domain are supported");
1051
Dave Barach97d8dc22016-08-15 15:31:15 -04001052 p = hash_get (bdm->bd_index_by_bd_id, bd_id);
1053 if (p)
1054 bd_index = *p;
1055 else
1056 return clib_error_return (0, "No such bridge domain %d", bd_id);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001057
Dave Barach97d8dc22016-08-15 15:31:15 -04001058 vec_validate (l2input_main.bd_configs, bd_index);
1059 bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
1060 if (bd_is_valid (bd_config))
1061 {
1062 start = bd_index;
1063 end = start + 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001064 }
Dave Barach97d8dc22016-08-15 15:31:15 -04001065 else
1066 {
1067 vlib_cli_output (vm, "bridge-domain %d not in use", bd_id);
1068 goto done;
1069 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001070 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001071
Dave Barach97d8dc22016-08-15 15:31:15 -04001072 /* Show all bridge-domains that have been initialized */
John Loda1f2c72017-03-24 20:11:15 -04001073 u32 printed = 0;
1074 u8 *as = 0;
Dave Barach97d8dc22016-08-15 15:31:15 -04001075 for (bd_index = start; bd_index < end; bd_index++)
1076 {
1077 bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index);
1078 if (bd_is_valid (bd_config))
1079 {
1080 if (!printed)
1081 {
1082 printed = 1;
1083 vlib_cli_output (vm,
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001084 "%=8s %=7s %=4s %=9s %=9s %=9s %=11s %=9s %=9s %=9s %=11s",
John Lo97934772017-05-18 22:26:47 -04001085 "BD-ID", "Index", "BSN", "Age(min)",
Neale Rannsb4743802018-09-05 09:13:57 -07001086 "Learning", "U-Forwrd", "UU-Flood",
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001087 "Flooding", "ARP-Term", "arp-ufwd",
1088 "BVI-Intf");
Dave Barach97d8dc22016-08-15 15:31:15 -04001089 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001090
John Loda1f2c72017-03-24 20:11:15 -04001091 if (bd_config->mac_age)
1092 as = format (as, "%d", bd_config->mac_age);
1093 else
1094 as = format (as, "off");
Dave Barach97d8dc22016-08-15 15:31:15 -04001095 vlib_cli_output (vm,
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001096 "%=8d %=7d %=4d %=9v %=9s %=9s %=11U %=9s %=9s %=9s %=11U",
John Loda1f2c72017-03-24 20:11:15 -04001097 bd_config->bd_id, bd_index, bd_config->seq_num, as,
Dave Barach97d8dc22016-08-15 15:31:15 -04001098 bd_config->feature_bitmap & L2INPUT_FEAT_LEARN ?
1099 "on" : "off",
John Loda1f2c72017-03-24 20:11:15 -04001100 bd_config->feature_bitmap & L2INPUT_FEAT_FWD ?
1101 "on" : "off",
Neale Rannsb4743802018-09-05 09:13:57 -07001102 format_uu_cfg, bd_config,
Dave Barach97d8dc22016-08-15 15:31:15 -04001103 bd_config->feature_bitmap & L2INPUT_FEAT_FLOOD ?
1104 "on" : "off",
1105 bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM ?
John Loda1f2c72017-03-24 20:11:15 -04001106 "on" : "off",
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001107 bd_config->feature_bitmap & L2INPUT_FEAT_ARP_UFWD ?
1108 "on" : "off",
John Loda1f2c72017-03-24 20:11:15 -04001109 format_vnet_sw_if_index_name_with_NA,
Dave Barach97d8dc22016-08-15 15:31:15 -04001110 vnm, bd_config->bvi_sw_if_index);
John Loda1f2c72017-03-24 20:11:15 -04001111 vec_reset_length (as);
Dave Barach97d8dc22016-08-15 15:31:15 -04001112
1113 if (detail || intf)
1114 {
1115 /* Show all member interfaces */
Eyal Baric5b13602016-11-24 19:42:43 +02001116 int i;
1117 vec_foreach_index (i, bd_config->members)
Dave Barach97d8dc22016-08-15 15:31:15 -04001118 {
Eyal Baric5b13602016-11-24 19:42:43 +02001119 l2_flood_member_t *member =
1120 vec_elt_at_index (bd_config->members, i);
Eyal Bari0f360dc2017-06-14 13:11:20 +03001121 u8 swif_seq_num = *l2fib_swif_seq_num (member->sw_if_index);
Dave Barach97d8dc22016-08-15 15:31:15 -04001122 u32 vtr_opr, dot1q, tag1, tag2;
Eyal Baric5b13602016-11-24 19:42:43 +02001123 if (i == 0)
Dave Barach97d8dc22016-08-15 15:31:15 -04001124 {
John Loda1f2c72017-03-24 20:11:15 -04001125 vlib_cli_output (vm, "\n%=30s%=7s%=5s%=5s%=5s%=9s%=30s",
1126 "Interface", "If-idx", "ISN", "SHG",
1127 "BVI", "TxFlood", "VLAN-Tag-Rewrite");
Dave Barach97d8dc22016-08-15 15:31:15 -04001128 }
1129 l2vtr_get (vm, vnm, member->sw_if_index, &vtr_opr, &dot1q,
1130 &tag1, &tag2);
John Loda1f2c72017-03-24 20:11:15 -04001131 vlib_cli_output (vm, "%=30U%=7d%=5d%=5d%=5s%=9s%=30U",
Dave Barach97d8dc22016-08-15 15:31:15 -04001132 format_vnet_sw_if_index_name, vnm,
1133 member->sw_if_index, member->sw_if_index,
Eyal Bari0f360dc2017-06-14 13:11:20 +03001134 swif_seq_num, member->shg,
Dave Barach97d8dc22016-08-15 15:31:15 -04001135 member->flags & L2_FLOOD_MEMBER_BVI ? "*" :
Eyal Baric5b13602016-11-24 19:42:43 +02001136 "-", i < bd_config->flood_count ? "*" : "-",
1137 format_vtr, vtr_opr, dot1q, tag1, tag2);
Dave Barach97d8dc22016-08-15 15:31:15 -04001138 }
Neale Rannsb4743802018-09-05 09:13:57 -07001139 if (~0 != bd_config->uu_fwd_sw_if_index)
1140 vlib_cli_output (vm, "%=30U%=7d%=5d%=5d%=5s%=9s%=30s",
1141 format_vnet_sw_if_index_name, vnm,
1142 bd_config->uu_fwd_sw_if_index,
1143 bd_config->uu_fwd_sw_if_index,
1144 0, 0, "uu", "-", "None");
1145
Dave Barach97d8dc22016-08-15 15:31:15 -04001146 }
1147
1148 if ((detail || arp) &&
1149 (bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM))
1150 {
1151 u32 ip4_addr;
John Lo1edfba92016-08-27 01:11:57 -04001152 ip6_address_t *ip6_addr;
Dave Barach97d8dc22016-08-15 15:31:15 -04001153 u64 mac_addr;
1154 vlib_cli_output (vm,
John Lo1edfba92016-08-27 01:11:57 -04001155 "\n IP4/IP6 to MAC table for ARP Termination");
Dave Barach97d8dc22016-08-15 15:31:15 -04001156
1157 /* *INDENT-OFF* */
1158 hash_foreach (ip4_addr, mac_addr, bd_config->mac_by_ip4,
1159 ({
John Lo1edfba92016-08-27 01:11:57 -04001160 vlib_cli_output (vm, "%=40U => %=20U",
Dave Barach97d8dc22016-08-15 15:31:15 -04001161 format_ip4_address, &ip4_addr,
1162 format_ethernet_address, &mac_addr);
1163 }));
John Lo1edfba92016-08-27 01:11:57 -04001164
1165 hash_foreach_mem (ip6_addr, mac_addr, bd_config->mac_by_ip6,
1166 ({
1167 vlib_cli_output (vm, "%=40U => %=20U",
1168 format_ip6_address, ip6_addr,
1169 format_ethernet_address, &mac_addr);
1170 }));
Dave Barach97d8dc22016-08-15 15:31:15 -04001171 /* *INDENT-ON* */
1172 }
Jerome Tollet48304142017-09-05 12:13:22 +01001173
1174 if ((detail || bd_tag) && (bd_config->bd_tag))
1175 {
1176 vlib_cli_output (vm, "\n BD-Tag: %s", bd_config->bd_tag);
1177
1178 }
Dave Barach97d8dc22016-08-15 15:31:15 -04001179 }
1180 }
John Loda1f2c72017-03-24 20:11:15 -04001181 vec_free (as);
Dave Barach97d8dc22016-08-15 15:31:15 -04001182
1183 if (!printed)
1184 {
1185 vlib_cli_output (vm, "no bridge-domains in use");
1186 }
1187
1188done:
Ed Warnickecb9cada2015-12-08 15:45:58 -07001189 return error;
1190}
1191
Billy McFall22aa3e92016-09-09 08:46:40 -04001192/*?
1193 * Show a summary of all the bridge-domain instances or detailed view of a
1194 * single bridge-domain. Bridge-domains are created by adding an interface
1195 * to a bridge using the '<em>set interface l2 bridge</em>' command.
1196 *
1197 * @cliexpar
1198 * @parblock
1199 * Example of displaying all bridge-domains:
1200 * @cliexstart{show bridge-domain}
1201 * ID Index Learning U-Forwrd UU-Flood Flooding ARP-Term BVI-Intf
1202 * 0 0 off off off off off local0
1203 * 200 1 on on on on off N/A
1204 * @cliexend
1205 *
1206 * Example of displaying details of a single bridge-domains:
1207 * @cliexstart{show bridge-domain 200 detail}
1208 * ID Index Learning U-Forwrd UU-Flood Flooding ARP-Term BVI-Intf
1209 * 200 1 on on on on off N/A
1210 *
1211 * Interface Index SHG BVI VLAN-Tag-Rewrite
1212 * GigabitEthernet0/8/0.200 3 0 - none
1213 * GigabitEthernet0/9/0.200 4 0 - none
1214 * @cliexend
1215 * @endparblock
1216?*/
Dave Barach97d8dc22016-08-15 15:31:15 -04001217/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001218VLIB_CLI_COMMAND (bd_show_cli, static) = {
1219 .path = "show bridge-domain",
Jerome Tollet48304142017-09-05 12:13:22 +01001220 .short_help = "show bridge-domain [bridge-domain-id [detail|int|arp|bd-tag]]",
Ed Warnickecb9cada2015-12-08 15:45:58 -07001221 .function = bd_show,
1222};
Dave Barach97d8dc22016-08-15 15:31:15 -04001223/* *INDENT-ON* */
1224
Choonho Son05480792017-03-29 20:07:45 +09001225int
1226bd_add_del (l2_bridge_domain_add_del_args_t * a)
1227{
1228 bd_main_t *bdm = &bd_main;
1229 vlib_main_t *vm = bdm->vlib_main;
Choonho Son05480792017-03-29 20:07:45 +09001230 int rv = 0;
1231
Eyal Barib1352ed2017-04-07 23:14:17 +03001232 u32 bd_index = bd_find_index (bdm, a->bd_id);
Choonho Son05480792017-03-29 20:07:45 +09001233 if (a->is_add)
1234 {
Eyal Barib1352ed2017-04-07 23:14:17 +03001235 if (bd_index != ~0)
1236 return VNET_API_ERROR_BD_ALREADY_EXISTS;
John Lo97934772017-05-18 22:26:47 -04001237 if (a->bd_id > L2_BD_ID_MAX)
1238 return VNET_API_ERROR_BD_ID_EXCEED_MAX;
Eyal Barib1352ed2017-04-07 23:14:17 +03001239 bd_index = bd_add_bd_index (bdm, a->bd_id);
Choonho Son05480792017-03-29 20:07:45 +09001240
Neale Rannsb4743802018-09-05 09:13:57 -07001241 bd_flags_t enable_flags = 0, disable_flags = 0;
Choonho Son05480792017-03-29 20:07:45 +09001242 if (a->flood)
1243 enable_flags |= L2_FLOOD;
1244 else
1245 disable_flags |= L2_FLOOD;
1246
1247 if (a->uu_flood)
1248 enable_flags |= L2_UU_FLOOD;
1249 else
1250 disable_flags |= L2_UU_FLOOD;
1251
1252 if (a->forward)
1253 enable_flags |= L2_FWD;
1254 else
1255 disable_flags |= L2_FWD;
1256
1257 if (a->learn)
1258 enable_flags |= L2_LEARN;
1259 else
1260 disable_flags |= L2_LEARN;
1261
1262 if (a->arp_term)
1263 enable_flags |= L2_ARP_TERM;
1264 else
1265 disable_flags |= L2_ARP_TERM;
1266
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001267 if (a->arp_ufwd)
1268 enable_flags |= L2_ARP_UFWD;
1269 else
1270 disable_flags |= L2_ARP_UFWD;
1271
Choonho Son05480792017-03-29 20:07:45 +09001272 if (enable_flags)
1273 bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */ );
1274
1275 if (disable_flags)
1276 bd_set_flags (vm, bd_index, disable_flags, 0 /* disable */ );
1277
1278 bd_set_mac_age (vm, bd_index, a->mac_age);
Jerome Tollet48304142017-09-05 12:13:22 +01001279
1280 if (a->bd_tag)
1281 bd_set_bd_tag (vm, bd_index, a->bd_tag);
1282
Choonho Son05480792017-03-29 20:07:45 +09001283 }
1284 else
Eyal Barib1352ed2017-04-07 23:14:17 +03001285 {
1286 if (bd_index == ~0)
1287 return VNET_API_ERROR_NO_SUCH_ENTRY;
Jon Loeliger1c7d4852017-05-02 11:06:23 -05001288 if (bd_index == 0)
1289 return VNET_API_ERROR_BD_NOT_MODIFIABLE;
Eyal Barib1352ed2017-04-07 23:14:17 +03001290 if (vec_len (l2input_main.bd_configs[bd_index].members))
1291 return VNET_API_ERROR_BD_IN_USE;
1292 rv = bd_delete (bdm, bd_index);
1293 }
Choonho Son05480792017-03-29 20:07:45 +09001294
1295 return rv;
1296}
1297
1298/**
1299 Create or delete bridge-domain.
Choonho Son5ee51f82017-04-05 19:09:52 +09001300 The CLI format:
Jerome Tollet50570ec2017-09-14 12:53:56 +01001301 create bridge-domain <bd_index> [learn <0|1>] [forward <0|1>] [uu-flood <0|1>] [flood <0|1>]
1302 [arp-term <0|1>] [mac-age <nn>] [bd-tag <tag>] [del]
Choonho Son05480792017-03-29 20:07:45 +09001303*/
1304
1305static clib_error_t *
1306bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input,
1307 vlib_cli_command_t * cmd)
1308{
1309 unformat_input_t _line_input, *line_input = &_line_input;
1310 clib_error_t *error = 0;
1311 u8 is_add = 1;
1312 u32 bd_id = ~0;
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001313 u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term =
1314 0, arp_ufwd = 0;
Choonho Son05480792017-03-29 20:07:45 +09001315 u32 mac_age = 0;
Jerome Tollet48304142017-09-05 12:13:22 +01001316 u8 *bd_tag = NULL;
Choonho Son05480792017-03-29 20:07:45 +09001317 l2_bridge_domain_add_del_args_t _a, *a = &_a;
1318 int rv;
1319
1320 /* Get a line of input. */
1321 if (!unformat_user (input, unformat_line_input, line_input))
1322 return 0;
1323
1324 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1325 {
1326 if (unformat (line_input, "%d", &bd_id))
1327 ;
1328 else if (unformat (line_input, "flood %d", &flood))
1329 ;
1330 else if (unformat (line_input, "uu-flood %d", &uu_flood))
1331 ;
1332 else if (unformat (line_input, "forward %d", &forward))
1333 ;
Choonho Son5ee51f82017-04-05 19:09:52 +09001334 else if (unformat (line_input, "learn %d", &learn))
1335 ;
Choonho Son05480792017-03-29 20:07:45 +09001336 else if (unformat (line_input, "arp-term %d", &arp_term))
1337 ;
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001338 else if (unformat (line_input, "arp-ufwd %d", &arp_ufwd))
1339 ;
Choonho Son05480792017-03-29 20:07:45 +09001340 else if (unformat (line_input, "mac-age %d", &mac_age))
1341 ;
Jerome Tollet48304142017-09-05 12:13:22 +01001342 else if (unformat (line_input, "bd-tag %s", &bd_tag))
1343 ;
Choonho Son05480792017-03-29 20:07:45 +09001344 else if (unformat (line_input, "del"))
1345 {
1346 is_add = 0;
1347 flood = uu_flood = forward = learn = 0;
1348 }
1349 else
1350 break;
1351 }
1352
1353 if (bd_id == ~0)
1354 {
1355 error = clib_error_return (0, "bridge-domain-id not specified");
1356 goto done;
1357 }
1358
Jon Loeliger1c7d4852017-05-02 11:06:23 -05001359 if (bd_id == 0)
1360 {
1361 error = clib_error_return (0, "bridge domain 0 can not be modified");
1362 goto done;
1363 }
1364
Choonho Son05480792017-03-29 20:07:45 +09001365 if (mac_age > 255)
1366 {
1367 error = clib_error_return (0, "mac age must be less than 256");
1368 goto done;
1369 }
Jerome Tollet48304142017-09-05 12:13:22 +01001370 if ((bd_tag) && (strlen ((char *) bd_tag) > 63))
1371 {
1372 error = clib_error_return (0, "bd-tag cannot be longer than 63");
1373 goto done;
1374 }
Choonho Son05480792017-03-29 20:07:45 +09001375
Dave Barachb7b92992018-10-17 10:38:51 -04001376 clib_memset (a, 0, sizeof (*a));
Choonho Son05480792017-03-29 20:07:45 +09001377 a->is_add = is_add;
1378 a->bd_id = bd_id;
1379 a->flood = (u8) flood;
1380 a->uu_flood = (u8) uu_flood;
1381 a->forward = (u8) forward;
1382 a->learn = (u8) learn;
1383 a->arp_term = (u8) arp_term;
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001384 a->arp_ufwd = (u8) arp_ufwd;
Choonho Son05480792017-03-29 20:07:45 +09001385 a->mac_age = (u8) mac_age;
Jerome Tollet48304142017-09-05 12:13:22 +01001386 a->bd_tag = bd_tag;
Choonho Son05480792017-03-29 20:07:45 +09001387
1388 rv = bd_add_del (a);
1389
1390 switch (rv)
1391 {
1392 case 0:
1393 if (is_add)
1394 vlib_cli_output (vm, "bridge-domain %d", bd_id);
1395 break;
Eyal Barib1352ed2017-04-07 23:14:17 +03001396 case VNET_API_ERROR_BD_IN_USE:
1397 error = clib_error_return (0, "bridge domain in use - remove members");
1398 goto done;
Choonho Son05480792017-03-29 20:07:45 +09001399 case VNET_API_ERROR_NO_SUCH_ENTRY:
John Lo97934772017-05-18 22:26:47 -04001400 error = clib_error_return (0, "bridge domain ID does not exist");
Choonho Son05480792017-03-29 20:07:45 +09001401 goto done;
Jon Loeliger1c7d4852017-05-02 11:06:23 -05001402 case VNET_API_ERROR_BD_NOT_MODIFIABLE:
1403 error = clib_error_return (0, "bridge domain 0 can not be modified");
1404 goto done;
John Lo97934772017-05-18 22:26:47 -04001405 case VNET_API_ERROR_BD_ID_EXCEED_MAX:
1406 error = clib_error_return (0, "bridge domain ID exceed 16M limit");
1407 goto done;
Choonho Son05480792017-03-29 20:07:45 +09001408 default:
1409 error = clib_error_return (0, "bd_add_del returned %d", rv);
1410 goto done;
1411 }
1412
1413done:
Jerome Tollet48304142017-09-05 12:13:22 +01001414 vec_free (bd_tag);
Choonho Son05480792017-03-29 20:07:45 +09001415 unformat_free (line_input);
1416
1417 return error;
1418}
1419
1420
1421/*?
1422 * Create/Delete bridge-domain instance
1423 *
1424 * @cliexpar
1425 * @parblock
1426 * Example of creating bridge-domain 1:
1427 * @cliexstart{create bridge-domain 1}
1428 * bridge-domain 1
1429 * @cliexend
1430 *
1431 * Example of creating bridge-domain 2 with enabling arp-term, mac-age 60:
1432 * @cliexstart{create bridge-domain 2 arp-term 1 mac-age 60}
1433 * bridge-domain 2
1434 *
1435 * vpp# show bridge-domain
1436 * ID Index BSN Age(min) Learning U-Forwrd UU-Flood Flooding ARP-Term BVI-Intf
1437 * 0 0 0 off off off off off off local0
1438 * 1 1 0 off on on off on off N/A
1439 * 2 2 0 60 on on off on on N/A
1440 *
1441 * @cliexend
1442 *
1443 * Example of delete bridge-domain 1:
1444 * @cliexstart{create bridge-domain 1 del}
1445 * @cliexend
1446 * @endparblock
1447?*/
1448
1449/* *INDENT-OFF* */
1450VLIB_CLI_COMMAND (bd_create_cli, static) = {
1451 .path = "create bridge-domain",
1452 .short_help = "create bridge-domain <bridge-domain-id>"
1453 " [learn <0|1>] [forward <0|1>] [uu-flood <0|1>] [flood <0|1>] [arp-term <0|1>]"
Mohsin Kazmi5e6f7342019-04-05 17:40:20 +02001454 " [arp-ufwd <0|1>] [mac-age <nn>] [bd-tag <tag>] [del]",
Choonho Son05480792017-03-29 20:07:45 +09001455 .function = bd_add_del_command_fn,
1456};
1457/* *INDENT-ON* */
1458
1459
1460
Dave Barach97d8dc22016-08-15 15:31:15 -04001461/*
1462 * fd.io coding-style-patch-verification: ON
1463 *
1464 * Local Variables:
1465 * eval: (c-set-style "gnu")
1466 * End:
1467 */