From 762d83c198c6c24cce4eb94a6d027f520d0b8383 Mon Sep 17 00:00:00 2001 From: Mohsin Kazmi Date: Thu, 27 Sep 2018 15:00:32 +0200 Subject: [PATCH] vom: Fix the l2 port type in bridge domain Change-Id: I8aba11142daeacce892ec529c2229ec54ee427e2 Signed-off-by: Mohsin Kazmi --- extras/vom/vom/bridge_domain.cpp | 8 +++++ extras/vom/vom/l2_binding.cpp | 62 +++++++++++++++++++++++++++----------- extras/vom/vom/l2_binding.hpp | 21 +++++++++++++ extras/vom/vom/l2_binding_cmds.cpp | 34 +++++++++++++-------- extras/vom/vom/l2_binding_cmds.hpp | 15 +++++---- src/vat/api_format.c | 9 +++--- test/ext/vom_test.cpp | 50 ++++++++++++++++++++++-------- 7 files changed, 148 insertions(+), 51 deletions(-) diff --git a/extras/vom/vom/bridge_domain.cpp b/extras/vom/vom/bridge_domain.cpp index b8c89e10bd9..a2cf656a6ad 100644 --- a/extras/vom/vom/bridge_domain.cpp +++ b/extras/vom/vom/bridge_domain.cpp @@ -209,6 +209,14 @@ bridge_domain::event_handler::handle_populate(const client_db::key_t& key) */ OM::commit(key, bd); + std::shared_ptr 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 */ diff --git a/extras/vom/vom/l2_binding.cpp b/extras/vom/vom/l2_binding.cpp index 4118f74065a..9e2c7228dd0 100644 --- a/extras/vom/vom/l2_binding.cpp +++ b/extras/vom/vom/l2_binding.cpp @@ -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(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 @@ -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)); } /* diff --git a/extras/vom/vom/l2_binding.hpp b/extras/vom/vom/l2_binding.hpp index d24f69ee33d..0a30a0cc894 100644 --- a/extras/vom/vom/l2_binding.hpp +++ b/extras/vom/vom/l2_binding.hpp @@ -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(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 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. diff --git a/extras/vom/vom/l2_binding_cmds.cpp b/extras/vom/vom/l2_binding_cmds.cpp index 6976e345a04..8769444032c 100644 --- a/extras/vom/vom/l2_binding_cmds.cpp +++ b/extras/vom/vom/l2_binding_cmds.cpp @@ -20,11 +20,11 @@ namespace l2_binding_cmds { bind_cmd::bind_cmd(HW::item& 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& 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()); } diff --git a/extras/vom/vom/l2_binding_cmds.hpp b/extras/vom/vom/l2_binding_cmds.hpp index 3d138b1d1af..e864f9d0149 100644 --- a/extras/vom/vom/l2_binding_cmds.hpp +++ b/extras/vom/vom/l2_binding_cmds.hpp @@ -35,7 +35,10 @@ public: /** * Constructor */ - bind_cmd(HW::item& item, const handle_t& itf, uint32_t bd, bool is_bvi); + bind_cmd(HW::item& 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& 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; }; /** diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 83b875e3be4..99ede1ea7fd 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -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) { diff --git a/test/ext/vom_test.cpp b/test/ext/vom_test.cpp index dad68356e9e..3374259cd60 100644 --- a/test/ext/vom_test.cpp +++ b/test/ext/vom_test.cpp @@ -936,7 +936,10 @@ BOOST_AUTO_TEST_CASE(test_bridge) { l2_binding *l2itf = new l2_binding(itf1, bd1); HW::item 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 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 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 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 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 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)); -- 2.16.6