l2: Add bridge_domain_add_del_v2 to l2 api

https://jira.fd.io/browse/VPP-2034

Type: fix
Signed-off-by: Laszlo Kiraly <laszlo.kiraly@est.tech>
Change-Id: Ieb6919f958f437fc603d5e1f48cab01de780951d
This commit is contained in:
Laszlo Kiraly 2022-09-16 13:20:07 +02:00 committed by Dave Wallace
parent 7498aadd23
commit 0f8f4351b0
17 changed files with 226 additions and 53 deletions

View File

@ -1,6 +1,7 @@
/* Hey Emacs use -*- mode: C -*- */
/*
* Copyright (c) 2016 Cisco and/or its affiliates.
* Copyright (c) 2022 Nordix Foundation.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@ -14,7 +15,7 @@
* limitations under the License.
*/
option version = "3.1.0";
option version = "3.2.0";
import "vnet/ip/ip_types.api";
import "vnet/ethernet/ethernet_types.api";
@ -304,7 +305,7 @@ autoreply define bridge_domain_set_learn_limit
u32 learn_limit;
};
/** \brief L2 bridge domain add or delete request
/** \brief L2 bridge domain add or delete request - will be deprecated
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param bd_id - the bridge domain to create
@ -319,6 +320,7 @@ autoreply define bridge_domain_set_learn_limit
*/
autoreply define bridge_domain_add_del
{
option deprecated;
u32 client_index;
u32 context;
u32 bd_id;
@ -333,6 +335,49 @@ autoreply define bridge_domain_add_del
bool is_add [default=true];
};
/** \brief L2 bridge domain add delete request version 2
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param bd_id - if the id == ~0 creates a bridge domain with an unused id
if the id != ~0 the id of the bridge domain to create/delete
@param flood - enable/disable bcast/mcast flooding in the bd
@param uu_flood - enable/disable unknown unicast flood in the bd
@param forward - enable/disable forwarding on all interfaces in the bd
@param learn - enable/disable learning on all interfaces in the bd
@param arp_term - enable/disable arp termination in the bd
@param arp_ufwd - enable/disable arp unicast forwarding in the bd
@param mac_age - mac aging time in min, 0 for disabled
@param is_add - add or delete flag
*/
define bridge_domain_add_del_v2
{
u32 client_index;
u32 context;
u32 bd_id;
bool flood;
bool uu_flood;
bool forward;
bool learn;
bool arp_term;
bool arp_ufwd;
u8 mac_age;
string bd_tag[64];
bool is_add [default=true];
};
/** \brief L2 bridge domain add delete version 2 response
@param context - sender context, to match reply w/ request
@param retval - return code for the set bridge flags request
@param resulting_id - the id for the new bridge domain
*/
define bridge_domain_add_del_v2_reply
{
u32 context;
i32 retval;
u32 bd_id;
};
/** \brief L2 bridge domain request operational state details
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request

View File

@ -3,6 +3,7 @@
* l2_api.c - layer 2 forwarding api
*
* Copyright (c) 2016 Cisco and/or its affiliates.
* Copyright (c) 2022 Nordix Foundation.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@ -510,6 +511,37 @@ vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp)
REPLY_MACRO (VL_API_BRIDGE_DOMAIN_ADD_DEL_REPLY);
}
static void
vl_api_bridge_domain_add_del_v2_t_handler (
vl_api_bridge_domain_add_del_v2_t *mp)
{
vl_api_bridge_domain_add_del_v2_reply_t *rmp;
u32 bd_id = ntohl (mp->bd_id);
int rv = 0;
if ((~0 == bd_id) && (mp->is_add))
bd_id = bd_get_unused_id ();
if ((~0 == bd_id) && (mp->is_add))
rv = VNET_API_ERROR_EAGAIN;
else
{
l2_bridge_domain_add_del_args_t a = { .is_add = mp->is_add,
.flood = mp->flood,
.uu_flood = mp->uu_flood,
.forward = mp->forward,
.learn = mp->learn,
.arp_term = mp->arp_term,
.arp_ufwd = mp->arp_ufwd,
.mac_age = mp->mac_age,
.bd_id = bd_id,
.bd_tag = mp->bd_tag };
rv = bd_add_del (&a);
}
REPLY_MACRO2 (VL_API_BRIDGE_DOMAIN_ADD_DEL_V2_REPLY,
({ rmp->bd_id = htonl (bd_id); }));
}
static void
send_bridge_domain_details (l2input_main_t * l2im,
vl_api_registration_t * reg,

View File

@ -1493,8 +1493,15 @@ bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input,
if (bd_id == ~0)
{
error = clib_error_return (0, "bridge-domain-id not specified");
goto done;
if (is_add)
{
bd_id = bd_get_unused_id ();
}
else
{
error = clib_error_return (0, "bridge-domain-id not specified");
goto done;
}
}
if (bd_id == 0)
@ -1597,7 +1604,40 @@ VLIB_CLI_COMMAND (bd_create_cli, static) = {
};
/* *INDENT-ON* */
/*
* Returns an unused bridge domain id, and ~0 if it can't find one.
*/
u32
bd_get_unused_id ()
{
bd_main_t *bdm = &bd_main;
int i, j;
int is_seed_low = 0;
static u32 seed = 0;
/* limit to 1M tries */
for (j = 0; j < 1 << 10; j++)
{
seed = random_u32 (&seed) & L2_BD_ID_MAX;
if (seed == 0)
continue;
if (seed < L2_BD_ID_MAX % 2)
is_seed_low = 1;
for (i = 0; i < L2_BD_ID_MAX % 2; i++)
{
/* look around randomly generated id */
if (is_seed_low)
seed += (2 * (i % 2) - 1) * i;
else
seed -= (2 * (i % 2) - 1) * i;
if (seed == ~0 || seed == 0)
continue;
if (bd_find_index (bdm, seed) == ~0)
return seed;
}
}
return ~0;
}
/*
* fd.io coding-style-patch-verification: ON

View File

@ -2,6 +2,7 @@
* l2_bd.h : layer 2 bridge domain
*
* Copyright (c) 2013 Cisco and/or its affiliates.
* Copyright (c) 2022 Nordix Foundation.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
@ -166,7 +167,7 @@ u32 bd_set_flags (vlib_main_t * vm, u32 bd_index, bd_flags_t flags,
void bd_set_mac_age (vlib_main_t * vm, u32 bd_index, u8 age);
void bd_set_learn_limit (vlib_main_t *vm, u32 bd_index, u32 learn_limit);
int bd_add_del (l2_bridge_domain_add_del_args_t * args);
u32 bd_get_unused_id (void);
/**
* \brief Get a bridge domain.
*

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright(c) 2021 Cisco Systems, Inc.
* Copyright(c) 2022 Nordix Foundation.
*/
#include <vat/vat.h>
@ -634,6 +635,18 @@ done:
return ret;
}
static int
api_bridge_domain_add_del_v2 (vat_main_t *vam)
{
return -1;
}
static void
vl_api_bridge_domain_add_del_v2_reply_t_handler (
vl_api_bridge_domain_add_del_v2_reply_t *mp)
{
}
#define foreach_pbb_vtr_op \
_ ("disable", L2_VTR_DISABLED) \
_ ("pop", L2_VTR_POP_2) \

View File

@ -105,7 +105,9 @@ class TestACLplugin(VppTestCase):
# Create BD with MAC learning and unknown unicast flooding disabled
# and put interfaces to this BD
cls.vapi.bridge_domain_add_del(bd_id=cls.bd_id, uu_flood=1, learn=1)
cls.vapi.bridge_domain_add_del_v2(
bd_id=cls.bd_id, uu_flood=1, learn=1, flood=1, forward=1, is_add=1
)
for pg_if in cls.pg_interfaces:
cls.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=pg_if.sw_if_index, bd_id=cls.bd_id

View File

@ -104,7 +104,9 @@ class TestClassifyAcl(TestClassifier):
# Create BD with MAC learning and unknown unicast flooding disabled
# and put interfaces to this BD
cls.vapi.bridge_domain_add_del(bd_id=cls.bd_id, uu_flood=1, learn=1)
cls.vapi.bridge_domain_add_del_v2(
bd_id=cls.bd_id, uu_flood=1, learn=1, flood=1, forward=1, is_add=1
)
for pg_if in cls.pg_interfaces:
cls.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=pg_if.sw_if_index, bd_id=cls.bd_id

View File

@ -165,7 +165,9 @@ class MethodHolder(VppTestCase):
# Create BD with MAC learning and unknown unicast flooding disabled
# and put interfaces to this BD
cls.vapi.bridge_domain_add_del(bd_id=1, uu_flood=1, learn=1)
cls.vapi.bridge_domain_add_del_v2(
bd_id=1, uu_flood=1, learn=1, flood=1, forward=1, is_add=1
)
cls.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=cls.pg1._sw_if_index, bd_id=1
)

View File

@ -112,7 +112,9 @@ class TestL2fib(VppTestCase):
for bd_id in n_brs:
# Create BD with MAC learning and unknown unicast flooding
# disabled and put interfaces to this BD
cls.vapi.bridge_domain_add_del(bd_id=bd_id, uu_flood=0, learn=0)
cls.vapi.bridge_domain_add_del_v2(
bd_id=bd_id, is_add=1, uu_flood=0, learn=0, flood=1, forward=1
)
ifs = [cls.pg_interfaces[i] for i in cls.bd_ifs(bd_id)]
for pg_if in ifs:
cls.vapi.sw_interface_set_l2_bridge(

View File

@ -57,7 +57,9 @@ class TestL2Flood(VppTestCase):
#
# Create a single bridge Domain
#
self.vapi.bridge_domain_add_del(bd_id=1)
self.vapi.bridge_domain_add_del_v2(
bd_id=1, is_add=1, flood=1, uu_flood=1, forward=1, learn=1
)
#
# add each interface to the BD. 3 interfaces per split horizon group
@ -169,7 +171,7 @@ class TestL2Flood(VppTestCase):
enable=0,
)
self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
self.vapi.bridge_domain_add_del_v2(bd_id=1, is_add=0)
def test_flood_one(self):
"""L2 no-Flood Test"""
@ -177,7 +179,9 @@ class TestL2Flood(VppTestCase):
#
# Create a single bridge Domain
#
self.vapi.bridge_domain_add_del(bd_id=1)
self.vapi.bridge_domain_add_del_v2(
bd_id=1, is_add=1, flood=1, uu_flood=1, forward=1, learn=1
)
#
# add 2 interfaces to the BD. this means a flood goes to only
@ -207,7 +211,7 @@ class TestL2Flood(VppTestCase):
self.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=i.sw_if_index, bd_id=1, enable=0
)
self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
self.vapi.bridge_domain_add_del_v2(bd_id=1, is_add=0)
def test_uu_fwd(self):
"""UU Flood"""
@ -215,7 +219,9 @@ class TestL2Flood(VppTestCase):
#
# Create a single bridge Domain
#
self.vapi.bridge_domain_add_del(bd_id=1, uu_flood=1)
self.vapi.bridge_domain_add_del_v2(
bd_id=1, is_add=1, uu_flood=1, flood=1, forward=1, learn=1
)
#
# add each interface to the BD. 3 interfaces per split horizon group
@ -352,7 +358,7 @@ class TestL2Flood(VppTestCase):
rx_sw_if_index=i.sw_if_index, bd_id=1, enable=0
)
self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
self.vapi.bridge_domain_add_del_v2(bd_id=1, is_add=0)
if __name__ == "__main__":

View File

@ -132,14 +132,16 @@ class TestL2bdArpTerm(VppTestCase):
def bd_add_del(self, bd_id=1, is_add=1):
if is_add:
self.vapi.bridge_domain_add_del(bd_id=bd_id, is_add=is_add)
self.vapi.bridge_domain_add_del_v2(
bd_id=bd_id, is_add=is_add, flood=1, uu_flood=1, forward=1, learn=1
)
for swif in self.bd_swifs(bd_id):
swif_idx = swif.sw_if_index
self.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=swif_idx, bd_id=bd_id, enable=is_add
)
if not is_add:
self.vapi.bridge_domain_add_del(bd_id=bd_id, is_add=is_add)
self.vapi.bridge_domain_add_del_v2(bd_id=bd_id, is_add=is_add)
@classmethod
def arp_req(cls, src_host, host):

View File

@ -77,8 +77,12 @@ class TestL2LearnLimit(VppTestCase):
def setUp(self):
super(TestL2LearnLimit, self).setUp()
self.vapi.bridge_domain_add_del(bd_id=1)
self.vapi.bridge_domain_add_del(bd_id=2)
self.vapi.bridge_domain_add_del_v2(
bd_id=1, is_add=1, flood=1, forward=1, learn=1, uu_flood=1
)
self.vapi.bridge_domain_add_del_v2(
bd_id=2, is_add=1, flood=1, forward=1, learn=1, uu_flood=1
)
self.vapi.sw_interface_set_l2_bridge(self.pg_interfaces[0].sw_if_index, bd_id=1)
self.vapi.sw_interface_set_l2_bridge(self.pg_interfaces[1].sw_if_index, bd_id=2)
@ -91,8 +95,8 @@ class TestL2LearnLimit(VppTestCase):
self.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=self.pg_interfaces[1].sw_if_index, bd_id=2, enable=0
)
self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
self.vapi.bridge_domain_add_del(bd_id=2, is_add=0)
self.vapi.bridge_domain_add_del_v2(bd_id=1, is_add=0)
self.vapi.bridge_domain_add_del_v2(bd_id=2, is_add=0)
if __name__ == "__main__":

View File

@ -69,7 +69,9 @@ class TestL2LearnLimitBdEnable(VppTestCase):
"""L2BD test with bridge domain limit"""
self.vapi.want_l2_macs_events(enable_disable=1, learn_limit=1000)
self.vapi.bridge_domain_set_default_learn_limit(4)
self.vapi.bridge_domain_add_del(bd_id=3)
self.vapi.bridge_domain_add_del_v2(
bd_id=3, is_add=1, flood=1, uu_flood=1, forward=1, learn=1
)
self.vapi.sw_interface_set_l2_bridge(self.pg_interfaces[2].sw_if_index, bd_id=3)
self.vapi.bridge_domain_set_learn_limit(2, 5)
@ -95,13 +97,17 @@ class TestL2LearnLimitBdEnable(VppTestCase):
self.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=self.pg_interfaces[2].sw_if_index, bd_id=3, enable=0
)
self.vapi.bridge_domain_add_del(is_add=0, bd_id=3)
self.vapi.bridge_domain_add_del_v2(is_add=0, bd_id=3)
def setUp(self):
super(TestL2LearnLimitBdEnable, self).setUp()
self.vapi.bridge_domain_add_del(bd_id=1)
self.vapi.bridge_domain_add_del(bd_id=2)
self.vapi.bridge_domain_add_del_v2(
bd_id=1, is_add=1, flood=1, uu_flood=1, forward=1, learn=1
)
self.vapi.bridge_domain_add_del_v2(
bd_id=2, is_add=1, flood=1, uu_flood=1, forward=1, learn=1
)
self.vapi.sw_interface_set_l2_bridge(self.pg_interfaces[0].sw_if_index, bd_id=1)
self.vapi.sw_interface_set_l2_bridge(self.pg_interfaces[1].sw_if_index, bd_id=2)
@ -114,8 +120,8 @@ class TestL2LearnLimitBdEnable(VppTestCase):
self.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=self.pg_interfaces[1].sw_if_index, bd_id=2, enable=0
)
self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
self.vapi.bridge_domain_add_del(bd_id=2, is_add=0)
self.vapi.bridge_domain_add_del_v2(bd_id=1, is_add=0)
self.vapi.bridge_domain_add_del_v2(bd_id=2, is_add=0)
if __name__ == "__main__":

View File

@ -89,8 +89,12 @@ class TestL2LearnLimitEnable(VppTestCase):
def setUp(self):
super(TestL2LearnLimitEnable, self).setUp()
self.vapi.bridge_domain_add_del(bd_id=1)
self.vapi.bridge_domain_add_del(bd_id=2)
self.vapi.bridge_domain_add_del_v2(
bd_id=1, is_add=1, flood=1, forward=1, uu_flood=1, learn=1
)
self.vapi.bridge_domain_add_del_v2(
bd_id=2, is_add=1, flood=1, forward=1, uu_flood=1, learn=1
)
self.vapi.sw_interface_set_l2_bridge(self.pg_interfaces[0].sw_if_index, bd_id=1)
self.vapi.sw_interface_set_l2_bridge(self.pg_interfaces[1].sw_if_index, bd_id=2)
@ -103,8 +107,8 @@ class TestL2LearnLimitEnable(VppTestCase):
self.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=self.pg_interfaces[1].sw_if_index, bd_id=2, enable=0
)
self.vapi.bridge_domain_add_del(bd_id=1, is_add=0)
self.vapi.bridge_domain_add_del(bd_id=2, is_add=0)
self.vapi.bridge_domain_add_del_v2(bd_id=1, is_add=0)
self.vapi.bridge_domain_add_del_v2(bd_id=2, is_add=0)
if __name__ == "__main__":

View File

@ -132,6 +132,9 @@ class TestL2bdMultiInst(VppTestCase):
# Create list of BDs
self.bd_list = []
# Create dict of BDs
self.bd_map = {}
# Create list of deleted BDs
self.bd_deleted_list = []
@ -186,19 +189,29 @@ class TestL2bdMultiInst(VppTestCase):
(Default value = 1)
"""
for b in range(start, start + count):
self.vapi.bridge_domain_add_del(bd_id=b)
self.logger.info("Bridge domain ID %d created" % b)
if self.bd_list.count(b) == 0:
self.bd_list.append(b)
if self.bd_deleted_list.count(b) == 1:
self.bd_deleted_list.remove(b)
if b == start:
self.vapi.bridge_domain_add_del_v2(
bd_id=b, flood=1, uu_flood=1, forward=1, learn=1, is_add=1
)
bd_id = b
else:
ret = self.vapi.bridge_domain_add_del_v2(
bd_id=0xFFFFFFFF, flood=1, uu_flood=1, forward=1, learn=1, is_add=1
)
bd_id = ret.bd_id
self.logger.info("Bridge domain ID %d created" % bd_id)
if self.bd_list.count(bd_id) == 0:
self.bd_map[b] = bd_id
self.bd_list.append(bd_id)
if self.bd_deleted_list.count(bd_id) == 1:
self.bd_deleted_list.remove(bd_id)
for j in self.bd_if_range(b):
pg_if = self.pg_interfaces[j]
self.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=pg_if.sw_if_index, bd_id=b
rx_sw_if_index=pg_if.sw_if_index, bd_id=bd_id
)
self.logger.info(
"pg-interface %s added to bridge domain ID %d" % (pg_if.name, b)
"pg-interface %s added to bridge domain ID %d" % (pg_if.name, bd_id)
)
self.pg_in_bd.append(pg_if)
hosts = self.hosts_by_pg_idx[pg_if.sw_if_index]
@ -220,16 +233,22 @@ class TestL2bdMultiInst(VppTestCase):
(Default value = 1)
"""
for b in range(start, start + count):
bd_id = self.bd_map[b]
for j in self.bd_if_range(b):
pg_if = self.pg_interfaces[j]
self.vapi.sw_interface_set_l2_bridge(
rx_sw_if_index=pg_if.sw_if_index, bd_id=b, enable=0
rx_sw_if_index=pg_if.sw_if_index, bd_id=bd_id, enable=0
)
self.pg_in_bd.remove(pg_if)
self.vapi.bridge_domain_add_del(bd_id=b, is_add=0)
self.bd_list.remove(b)
self.bd_deleted_list.append(b)
self.logger.info("Bridge domain ID %d deleted" % b)
self.logger.info(
"pg-interface %s removed from bridge domain ID %d"
% (pg_if.name, bd_id)
)
self.vapi.bridge_domain_add_del_v2(bd_id=bd_id, is_add=0)
self.bd_map.pop(b)
self.bd_list.remove(bd_id)
self.bd_deleted_list.append(bd_id)
self.logger.info("Bridge domain ID %d deleted" % bd_id)
def create_stream(self, src_if):
"""

View File

@ -84,7 +84,7 @@ class VppBridgeDomain(VppObject):
self.arp_ufwd = arp_ufwd
def add_vpp_config(self):
self._test.vapi.bridge_domain_add_del(
self._test.vapi.bridge_domain_add_del_v2(
bd_id=self.bd_id,
flood=self.flood,
uu_flood=self.uu_flood,
@ -98,7 +98,7 @@ class VppBridgeDomain(VppObject):
return self
def remove_vpp_config(self):
self._test.vapi.bridge_domain_add_del(bd_id=self.bd_id, is_add=0)
self._test.vapi.bridge_domain_add_del_v2(bd_id=self.bd_id, is_add=0)
def query_vpp_config(self):
return find_bridge_domain(self._test, self.bd_id)

View File

@ -50,13 +50,6 @@ defaultmapping = {
"bier_table_add_del": {
"is_add": 1,
},
"bridge_domain_add_del": {
"flood": 1,
"uu_flood": 1,
"forward": 1,
"learn": 1,
"is_add": 1,
},
"bvi_delete": {},
"geneve_add_del_tunnel": {
"mcast_sw_if_index": 4294967295,