summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extras/vom/vom/bridge_domain.cpp8
-rw-r--r--extras/vom/vom/l2_binding.cpp62
-rw-r--r--extras/vom/vom/l2_binding.hpp21
-rw-r--r--extras/vom/vom/l2_binding_cmds.cpp34
-rw-r--r--extras/vom/vom/l2_binding_cmds.hpp15
-rw-r--r--src/vat/api_format.c9
-rw-r--r--test/ext/vom_test.cpp50
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<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
*/
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<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));
}
/*
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>
+ {
+ 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
@@ -188,6 +204,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.
*/
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<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());
}
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<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;
};
/**
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<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));