vom: Fix the l2 port type in bridge domain 19/15019/2
authorMohsin Kazmi <sykazmi@cisco.com>
Thu, 27 Sep 2018 13:00:32 +0000 (15:00 +0200)
committerNeale Ranns <nranns@cisco.com>
Sat, 29 Sep 2018 17:06:30 +0000 (17:06 +0000)
Change-Id: I8aba11142daeacce892ec529c2229ec54ee427e2
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
extras/vom/vom/bridge_domain.cpp
extras/vom/vom/l2_binding.cpp
extras/vom/vom/l2_binding.hpp
extras/vom/vom/l2_binding_cmds.cpp
extras/vom/vom/l2_binding_cmds.hpp
src/vat/api_format.c
test/ext/vom_test.cpp

index b8c89e1..a2cf656 100644 (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
      */
index 4118f74..9e2c722 100644 (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));
   }
 
   /*
index d24f69e..0a30a0c 100644 (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.
index 6976e34..8769444 100644 (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());
 }
index 3d138b1..e864f9d 100644 (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;
 };
 
 /**
index 83b875e..99ede1e 100644 (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)
     {
index dad6835..3374259 100644 (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));