vom: Fix the l2 port type in bridge domain

Change-Id: I8aba11142daeacce892ec529c2229ec54ee427e2
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
This commit is contained in:
Mohsin Kazmi
2018-09-27 15:00:32 +02:00
committed by Neale Ranns
parent 539663c401
commit 762d83c198
7 changed files with 148 additions and 51 deletions

View File

@ -209,6 +209,14 @@ bridge_domain::event_handler::handle_populate(const client_db::key_t& key)
*/
OM::commit(key, bd);
std::shared_ptr<interface> uu_fwd_itf =
interface::find(payload.uu_fwd_sw_if_index);
if (uu_fwd_itf) {
l2_binding l2(*uu_fwd_itf, bd,
l2_binding::l2_port_type_t::L2_PORT_TYPE_UU_FWD);
OM::commit(key, l2);
}
/**
* For each interface in the BD construct an l2_binding
*/

View File

@ -55,12 +55,43 @@ l2_binding::l2_vtr_op_t::l2_vtr_op_t(int v, const std::string s)
{
}
const l2_binding::l2_port_type_t
l2_binding::l2_port_type_t::L2_PORT_TYPE_NORMAL(0, "normal");
const l2_binding::l2_port_type_t l2_binding::l2_port_type_t::L2_PORT_TYPE_BVI(
1,
"bvi");
const l2_binding::l2_port_type_t
l2_binding::l2_port_type_t::L2_PORT_TYPE_UU_FWD(2, "uu-fwd");
l2_binding::l2_port_type_t::l2_port_type_t(int v, const std::string s)
: enum_base<l2_binding::l2_port_type_t>(v, s)
{
}
/**
* Construct a new object matching the desried state
*/
l2_binding::l2_binding(const interface& itf, const bridge_domain& bd)
: m_itf(itf.singular())
, m_bd(bd.singular())
, m_port_type(l2_port_type_t::L2_PORT_TYPE_NORMAL)
, m_binding(0)
, m_vtr_op(l2_vtr_op_t::L2_VTR_DISABLED, rc_t::UNSET)
, m_vtr_op_tag(0)
{
if (interface::type_t::BVI == m_itf->type())
m_port_type = l2_port_type_t::L2_PORT_TYPE_BVI;
}
/**
* Construct a new object matching the desried state
*/
l2_binding::l2_binding(const interface& itf,
const bridge_domain& bd,
const l2_port_type_t& port_type)
: m_itf(itf.singular())
, m_bd(bd.singular())
, m_port_type(port_type)
, m_binding(0)
, m_vtr_op(l2_vtr_op_t::L2_VTR_DISABLED, rc_t::UNSET)
, m_vtr_op_tag(0)
@ -70,6 +101,7 @@ l2_binding::l2_binding(const interface& itf, const bridge_domain& bd)
l2_binding::l2_binding(const l2_binding& o)
: m_itf(o.m_itf)
, m_bd(o.m_bd)
, m_port_type(o.m_port_type)
, m_binding(0)
, m_vtr_op(o.m_vtr_op)
, m_vtr_op_tag(o.m_vtr_op_tag)
@ -85,7 +117,8 @@ l2_binding::key() const
bool
l2_binding::operator==(const l2_binding& l) const
{
return ((*m_itf == *l.m_itf) && (*m_bd == *l.m_bd));
return ((*m_itf == *l.m_itf) && (*m_bd == *l.m_bd) &&
(m_port_type == l.m_port_type));
}
std::shared_ptr<l2_binding>
@ -98,9 +131,8 @@ void
l2_binding::sweep()
{
if (m_binding && handle_t::INVALID != m_itf->handle()) {
HW::enqueue(
new l2_binding_cmds::unbind_cmd(m_binding, m_itf->handle(), m_bd->id(),
interface::type_t::BVI == m_itf->type()));
HW::enqueue(new l2_binding_cmds::unbind_cmd(m_binding, m_itf->handle(),
m_bd->id(), m_port_type));
}
// no need to undo the VTR operation.
@ -111,9 +143,8 @@ void
l2_binding::replay()
{
if (m_binding && handle_t::INVALID != m_itf->handle()) {
HW::enqueue(
new l2_binding_cmds::bind_cmd(m_binding, m_itf->handle(), m_bd->id(),
interface::type_t::BVI == m_itf->type()));
HW::enqueue(new l2_binding_cmds::bind_cmd(m_binding, m_itf->handle(),
m_bd->id(), m_port_type));
}
if (m_vtr_op && handle_t::INVALID != m_itf->handle()) {
@ -135,7 +166,7 @@ l2_binding::to_string() const
{
std::ostringstream s;
s << "L2-binding:[" << m_itf->to_string() << " " << m_bd->to_string() << " "
<< m_binding.to_string() << "]";
<< m_port_type.to_string() << " " << m_binding.to_string() << "]";
return (s.str());
}
@ -156,20 +187,17 @@ l2_binding::update(const l2_binding& desired)
* the desired state is always that the interface should be created
*/
if (rc_t::OK != m_binding.rc()) {
HW::enqueue(
new l2_binding_cmds::bind_cmd(m_binding, m_itf->handle(), m_bd->id(),
interface::type_t::BVI == m_itf->type()));
HW::enqueue(new l2_binding_cmds::bind_cmd(m_binding, m_itf->handle(),
m_bd->id(), m_port_type));
} else if (!(*m_bd == *desired.m_bd)) {
/*
* re-binding to a different BD. do unbind, bind.
*/
HW::enqueue(
new l2_binding_cmds::unbind_cmd(m_binding, m_itf->handle(), m_bd->id(),
interface::type_t::BVI == m_itf->type()));
HW::enqueue(new l2_binding_cmds::unbind_cmd(m_binding, m_itf->handle(),
m_bd->id(), m_port_type));
m_bd = desired.m_bd;
HW::enqueue(
new l2_binding_cmds::bind_cmd(m_binding, m_itf->handle(), m_bd->id(),
interface::type_t::BVI == m_itf->type()));
HW::enqueue(new l2_binding_cmds::bind_cmd(m_binding, m_itf->handle(),
m_bd->id(), m_port_type));
}
/*

View File

@ -56,10 +56,26 @@ public:
l2_vtr_op_t(int v, const std::string s);
};
struct l2_port_type_t : public enum_base<l2_port_type_t>
{
l2_port_type_t(const l2_port_type_t& l) = default;
~l2_port_type_t() = default;
const static l2_port_type_t L2_PORT_TYPE_NORMAL;
const static l2_port_type_t L2_PORT_TYPE_BVI;
const static l2_port_type_t L2_PORT_TYPE_UU_FWD;
private:
l2_port_type_t(int v, const std::string s);
};
/**
* Construct a new object matching the desried state
*/
l2_binding(const interface& itf, const bridge_domain& bd);
l2_binding(const interface& itf,
const bridge_domain& bd,
const l2_port_type_t& port_type);
/**
* Copy Constructor
@ -187,6 +203,11 @@ private:
*/
std::shared_ptr<bridge_domain> m_bd;
/**
* l2 port type i.e. normal, bvi or unknown unicast
*/
l2_port_type_t m_port_type;
/**
* HW configuration for the binding. The bool representing the
* do/don't bind.

View File

@ -20,11 +20,11 @@ namespace l2_binding_cmds {
bind_cmd::bind_cmd(HW::item<bool>& item,
const handle_t& itf,
uint32_t bd,
bool is_bvi)
const l2_binding::l2_port_type_t& port_type)
: rpc_cmd(item)
, m_itf(itf)
, m_bd(bd)
, m_is_bvi(is_bvi)
, m_port_type(port_type)
{
}
@ -32,7 +32,7 @@ bool
bind_cmd::operator==(const bind_cmd& other) const
{
return ((m_itf == other.m_itf) && (m_bd == other.m_bd) &&
(m_is_bvi == other.m_is_bvi));
(m_port_type == other.m_port_type));
}
rc_t
@ -44,8 +44,13 @@ bind_cmd::issue(connection& con)
payload.rx_sw_if_index = m_itf.value();
payload.bd_id = m_bd;
payload.shg = 0;
payload.port_type =
(m_is_bvi ? L2_API_PORT_TYPE_BVI : L2_API_PORT_TYPE_NORMAL);
if (m_port_type == l2_binding::l2_port_type_t::L2_PORT_TYPE_BVI)
payload.port_type = L2_API_PORT_TYPE_BVI;
else if (m_port_type == l2_binding::l2_port_type_t::L2_PORT_TYPE_UU_FWD)
payload.port_type = L2_API_PORT_TYPE_UU_FWD;
else
payload.port_type = L2_API_PORT_TYPE_NORMAL;
payload.enable = 1;
VAPI_CALL(req.execute());
@ -58,7 +63,7 @@ bind_cmd::to_string() const
{
std::ostringstream s;
s << "L2-bind: " << m_hw_item.to_string() << " itf:" << m_itf.to_string()
<< " bd:" << m_bd;
<< " bd:" << m_bd << " port-type:" << m_port_type.to_string();
return (s.str());
}
@ -66,11 +71,11 @@ bind_cmd::to_string() const
unbind_cmd::unbind_cmd(HW::item<bool>& item,
const handle_t& itf,
uint32_t bd,
bool is_bvi)
const l2_binding::l2_port_type_t& port_type)
: rpc_cmd(item)
, m_itf(itf)
, m_bd(bd)
, m_is_bvi(is_bvi)
, m_port_type(port_type)
{
}
@ -78,7 +83,7 @@ bool
unbind_cmd::operator==(const unbind_cmd& other) const
{
return ((m_itf == other.m_itf) && (m_bd == other.m_bd) &&
(m_is_bvi == other.m_is_bvi));
(m_port_type == other.m_port_type));
}
rc_t
@ -90,8 +95,13 @@ unbind_cmd::issue(connection& con)
payload.rx_sw_if_index = m_itf.value();
payload.bd_id = m_bd;
payload.shg = 0;
payload.port_type =
(m_is_bvi ? L2_API_PORT_TYPE_BVI : L2_API_PORT_TYPE_NORMAL);
if (m_port_type == l2_binding::l2_port_type_t::L2_PORT_TYPE_BVI)
payload.port_type = L2_API_PORT_TYPE_BVI;
else if (m_port_type == l2_binding::l2_port_type_t::L2_PORT_TYPE_UU_FWD)
payload.port_type = L2_API_PORT_TYPE_UU_FWD;
else
payload.port_type = L2_API_PORT_TYPE_NORMAL;
payload.enable = 0;
VAPI_CALL(req.execute());
@ -107,7 +117,7 @@ unbind_cmd::to_string() const
{
std::ostringstream s;
s << "L2-unbind: " << m_hw_item.to_string() << " itf:" << m_itf.to_string()
<< " bd:" << m_bd;
<< " bd:" << m_bd << " port-type:" << m_port_type;
return (s.str());
}

View File

@ -35,7 +35,10 @@ public:
/**
* Constructor
*/
bind_cmd(HW::item<bool>& item, const handle_t& itf, uint32_t bd, bool is_bvi);
bind_cmd(HW::item<bool>& item,
const handle_t& itf,
uint32_t bd,
const l2_binding::l2_port_type_t& port_type);
/**
* Issue the command to VPP/HW
@ -63,9 +66,9 @@ private:
uint32_t m_bd;
/**
* Is it a BVI interface that is being bound
* What is the port type i.e. normal, bvi, uu-fwd that is being bound
*/
bool m_is_bvi;
const l2_binding::l2_port_type_t& m_port_type;
};
/**
@ -81,7 +84,7 @@ public:
unbind_cmd(HW::item<bool>& item,
const handle_t& itf,
uint32_t bd,
bool is_bvi);
const l2_binding::l2_port_type_t& port_type);
/**
* Issue the command to VPP/HW
@ -109,9 +112,9 @@ private:
uint32_t m_bd;
/**
* Is it a BVI interface that is being bound
* What is the port type i.e. bvi, normal or uu-fwd that is being bound
*/
bool m_is_bvi;
const l2_binding::l2_port_type_t& m_port_type;
};
/**

View File

@ -1389,12 +1389,13 @@ static void vl_api_bridge_domain_details_t_handler
u32 n_sw_ifs = ntohl (mp->n_sw_ifs);
int i;
print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-3s",
" ID", "LRN", "FWD", "FLD", "BVI", "#IF");
print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-6s %-3s",
" ID", "LRN", "FWD", "FLD", "BVI", "UU-FWD", "#IF");
print (vam->ofp, "%3d %3d %3d %3d %3d %3d",
print (vam->ofp, "%3d %3d %3d %3d %3d %6d %3d",
ntohl (mp->bd_id), mp->learn, mp->forward,
mp->flood, ntohl (mp->bvi_sw_if_index), n_sw_ifs);
mp->flood, ntohl (mp->bvi_sw_if_index),
ntohl (mp->uu_fwd_sw_if_index), n_sw_ifs);
if (n_sw_ifs)
{

View File

@ -936,7 +936,10 @@ BOOST_AUTO_TEST_CASE(test_bridge) {
l2_binding *l2itf = new l2_binding(itf1, bd1);
HW::item<bool> hw_l2_bind(true, rc_t::OK);
ADD_EXPECT(l2_binding_cmds::bind_cmd(hw_l2_bind, hw_ifh.data(), hw_bd.data(), false));
ADD_EXPECT(l2_binding_cmds::bind_cmd(hw_l2_bind,
hw_ifh.data(),
hw_bd.data(),
l2_binding::l2_port_type_t::L2_PORT_TYPE_NORMAL));
TRY_CHECK_RC(OM::write(franz, *l2itf));
/*
@ -959,7 +962,10 @@ BOOST_AUTO_TEST_CASE(test_bridge) {
HW::item<l2_binding::l2_vtr_op_t> hw_set_vtr(l2_binding::l2_vtr_op_t::L2_VTR_POP_1, rc_t::OK);
l2itf2->set(l2_binding::l2_vtr_op_t::L2_VTR_POP_1, 68);
ADD_EXPECT(l2_binding_cmds::bind_cmd(hw_l2_bind, hw_ifh2.data(), hw_bd.data(), false));
ADD_EXPECT(l2_binding_cmds::bind_cmd(hw_l2_bind,
hw_ifh2.data(),
hw_bd.data(),
l2_binding::l2_port_type_t::L2_PORT_TYPE_NORMAL));
ADD_EXPECT(l2_binding_cmds::set_vtr_op_cmd(hw_set_vtr, hw_ifh2.data(), 68));
TRY_CHECK_RC(OM::write(dante, *l2itf2));
@ -983,7 +989,10 @@ BOOST_AUTO_TEST_CASE(test_bridge) {
delete l2itf;
HW::item<interface::admin_state_t> hw_as_down(interface::admin_state_t::DOWN,
rc_t::OK);
ADD_EXPECT(l2_binding_cmds::unbind_cmd(hw_l2_bind, hw_ifh.data(), hw_bd.data(), false));
ADD_EXPECT(l2_binding_cmds::unbind_cmd(hw_l2_bind,
hw_ifh.data(),
hw_bd.data(),
l2_binding::l2_port_type_t::L2_PORT_TYPE_NORMAL));
ADD_EXPECT(interface_cmds::state_change_cmd(hw_as_down, hw_ifh));
ADD_EXPECT(interface_cmds::af_packet_delete_cmd(hw_ifh, itf1_name));
TRY_CHECK(OM::remove(franz));
@ -996,7 +1005,10 @@ BOOST_AUTO_TEST_CASE(test_bridge) {
STRICT_ORDER_OFF();
ADD_EXPECT(bridge_domain_arp_entry_cmds::delete_cmd(hw_be1, bd1.id(), mac1, ip1));
ADD_EXPECT(bridge_domain_entry_cmds::delete_cmd(hw_be1, mac1, bd1.id(), false));
ADD_EXPECT(l2_binding_cmds::unbind_cmd(hw_l2_bind, hw_ifh2.data(), hw_bd.data(), false));
ADD_EXPECT(l2_binding_cmds::unbind_cmd(hw_l2_bind,
hw_ifh2.data(),
hw_bd.data(),
l2_binding::l2_port_type_t::L2_PORT_TYPE_NORMAL));
ADD_EXPECT(bridge_domain_cmds::delete_cmd(hw_bd));
ADD_EXPECT(interface_cmds::state_change_cmd(hw_as_down, hw_ifh2));
@ -1027,7 +1039,10 @@ BOOST_AUTO_TEST_CASE(test_bridge) {
TRY_CHECK_RC(OM::write(jkr, itf3));
l2_binding *l2itf3 = new l2_binding(itf3, bd2);
ADD_EXPECT(l2_binding_cmds::bind_cmd(hw_l2_bind, hw_ifh3.data(), hw_bd2.data(), true));
ADD_EXPECT(l2_binding_cmds::bind_cmd(hw_l2_bind,
hw_ifh3.data(),
hw_bd2.data(),
l2_binding::l2_port_type_t::L2_PORT_TYPE_BVI));
TRY_CHECK_RC(OM::write(jkr, *l2itf3));
HW::item<bool> hw_be2(true, rc_t::OK);
@ -1039,7 +1054,10 @@ BOOST_AUTO_TEST_CASE(test_bridge) {
delete l2itf3;
delete be2;
STRICT_ORDER_OFF();
ADD_EXPECT(l2_binding_cmds::unbind_cmd(hw_l2_bind, hw_ifh3.data(), hw_bd2.data(), true));
ADD_EXPECT(l2_binding_cmds::unbind_cmd(hw_l2_bind,
hw_ifh3.data(),
hw_bd2.data(),
l2_binding::l2_port_type_t::L2_PORT_TYPE_BVI));
ADD_EXPECT(bridge_domain_entry_cmds::delete_cmd(hw_be2, mac2, bd2.id(), true));
ADD_EXPECT(interface_cmds::state_change_cmd(hw_as_down, hw_ifh3));
ADD_EXPECT(interface_cmds::loopback_delete_cmd(hw_ifh3));
@ -1143,14 +1161,20 @@ BOOST_AUTO_TEST_CASE(test_vxlan) {
l2_binding *l2itf = new l2_binding(vxt, bd1);
HW::item<bool> hw_l2_bind(true, rc_t::OK);
ADD_EXPECT(l2_binding_cmds::bind_cmd(hw_l2_bind, hw_vxt.data(), hw_bd.data(), false));
ADD_EXPECT(l2_binding_cmds::bind_cmd(hw_l2_bind,
hw_vxt.data(),
hw_bd.data(),
l2_binding::l2_port_type_t::L2_PORT_TYPE_NORMAL));
TRY_CHECK_RC(OM::write(franz, *l2itf));
// flush Franz's state
delete l2itf;
HW::item<handle_t> hw_vxtdel(3, rc_t::NOOP);
STRICT_ORDER_OFF();
ADD_EXPECT(l2_binding_cmds::unbind_cmd(hw_l2_bind, hw_vxt.data(), hw_bd.data(), false));
ADD_EXPECT(l2_binding_cmds::unbind_cmd(hw_l2_bind,
hw_vxt.data(),
hw_bd.data(),
l2_binding::l2_port_type_t::L2_PORT_TYPE_NORMAL));
ADD_EXPECT(bridge_domain_cmds::delete_cmd(hw_bd));
ADD_EXPECT(vxlan_tunnel_cmds::delete_cmd(hw_vxtdel, ep));
TRY_CHECK(OM::remove(franz));
@ -1971,7 +1995,8 @@ BOOST_AUTO_TEST_CASE(test_pipes) {
ADD_EXPECT(l2_binding_cmds::bind_cmd(hw_l2_1_bind,
pipe1.east()->handle(),
hw_bd.data(), false));
hw_bd.data(),
l2_binding::l2_port_type_t::L2_PORT_TYPE_NORMAL));
TRY_CHECK_RC(OM::write(gk, *l2_1));
l2_binding *l2_2 = new l2_binding(*pipe1.west(), bd1);
@ -1979,7 +2004,8 @@ BOOST_AUTO_TEST_CASE(test_pipes) {
ADD_EXPECT(l2_binding_cmds::bind_cmd(hw_l2_2_bind,
pipe1.west()->handle(),
hw_bd.data(), false));
hw_bd.data(),
l2_binding::l2_port_type_t::L2_PORT_TYPE_NORMAL));
TRY_CHECK_RC(OM::write(gk, *l2_2));
STRICT_ORDER_OFF();
@ -1989,11 +2015,11 @@ BOOST_AUTO_TEST_CASE(test_pipes) {
ADD_EXPECT(l2_binding_cmds::unbind_cmd(hw_l2_1_bind,
pipe1.east()->handle(),
hw_bd.data(),
false));
l2_binding::l2_port_type_t::L2_PORT_TYPE_NORMAL));
ADD_EXPECT(l2_binding_cmds::unbind_cmd(hw_l2_1_bind,
pipe1.west()->handle(),
hw_bd.data(),
false));
l2_binding::l2_port_type_t::L2_PORT_TYPE_NORMAL));
ADD_EXPECT(interface_cmds::state_change_cmd(hw_as_down, hw_hdl));
ADD_EXPECT(pipe_cmds::delete_cmd(hw_hdl, hw_hdl_pair));
ADD_EXPECT(bridge_domain_cmds::delete_cmd(hw_bd));