Fixes for 'make UNATTENDED=yes CC=clang CXX=clang verify'
[vpp.git] / src / vpp-api / vom / interface.cpp
index 1c9f20d..e9b7a1a 100644 (file)
  */
 
 #include "vom/interface.hpp"
+#include "vom/bond_group_binding.hpp"
+#include "vom/bond_group_binding_cmds.hpp"
+#include "vom/bond_interface_cmds.hpp"
 #include "vom/interface_cmds.hpp"
 #include "vom/interface_factory.hpp"
 #include "vom/l3_binding_cmds.hpp"
 #include "vom/logger.hpp"
 #include "vom/prefix.hpp"
+#include "vom/singular_db_funcs.hpp"
 
 namespace VOM {
 /**
  * A DB of all the interfaces, key on the name
  */
-singular_db<const std::string, interface> interface::m_db;
+singular_db<interface::key_t, interface> interface::m_db;
 
 /**
  * A DB of all the interfaces, key on VPP's handle
@@ -38,36 +42,25 @@ interface::event_handler interface::m_evh;
  */
 interface::interface(const std::string& name,
                      interface::type_t itf_type,
-                     interface::admin_state_t itf_state)
+                     interface::admin_state_t itf_state,
+                     const std::string& tag)
   : m_hdl(handle_t::INVALID)
   , m_name(name)
   , m_type(itf_type)
   , m_state(itf_state)
   , m_table_id(route::DEFAULT_TABLE)
   , m_l2_address(l2_address_t::ZERO, rc_t::UNSET)
+  , m_stats_type(stats_type_t::NORMAL)
   , m_oper(oper_state_t::DOWN)
-{
-}
-
-interface::interface(const handle_t& handle,
-                     const l2_address_t& l2_address,
-                     const std::string& name,
-                     interface::type_t type,
-                     interface::admin_state_t state)
-  : m_hdl(handle)
-  , m_name(name)
-  , m_type(type)
-  , m_state(state)
-  , m_table_id(route::DEFAULT_TABLE)
-  , m_l2_address(l2_address)
-  , m_oper(oper_state_t::DOWN)
+  , m_tag(tag)
 {
 }
 
 interface::interface(const std::string& name,
                      interface::type_t itf_type,
                      interface::admin_state_t itf_state,
-                     const route_domain& rd)
+                     const route_domain& rd,
+                     const std::string& tag)
   : m_hdl(handle_t::INVALID)
   , m_name(name)
   , m_type(itf_type)
@@ -75,7 +68,9 @@ interface::interface(const std::string& name,
   , m_state(itf_state)
   , m_table_id(m_rd->table_id())
   , m_l2_address(l2_address_t::ZERO, rc_t::UNSET)
+  , m_stats_type(stats_type_t::NORMAL)
   , m_oper(oper_state_t::DOWN)
+  , m_tag(tag)
 {
 }
 
@@ -87,10 +82,21 @@ interface::interface(const interface& o)
   , m_state(o.m_state)
   , m_table_id(o.m_table_id)
   , m_l2_address(o.m_l2_address)
+  , m_stats_type(o.m_stats_type)
   , m_oper(o.m_oper)
+  , m_tag(o.m_tag)
 {
 }
 
+bool
+interface::operator==(const interface& i) const
+{
+  return ((key() == i.key()) &&
+          (m_l2_address.data() == i.m_l2_address.data()) &&
+          (m_state == i.m_state) && (m_rd == i.m_rd) && (m_type == i.m_type) &&
+          (m_oper == i.m_oper));
+}
+
 interface::event_listener::event_listener()
   : m_status(rc_t::NOOP)
 {
@@ -124,6 +130,12 @@ interface::type() const
 
 const handle_t&
 interface::handle() const
+{
+  return (singular()->handle_i());
+}
+
+const handle_t&
+interface::handle_i() const
 {
   return (m_hdl.data());
 }
@@ -137,13 +149,13 @@ interface::l2_address() const
 interface::const_iterator_t
 interface::cbegin()
 {
-  return m_db.cbegin();
+  return m_db.begin();
 }
 
 interface::const_iterator_t
 interface::cend()
 {
-  return m_db.cend();
+  return m_db.end();
 }
 
 void
@@ -157,11 +169,21 @@ interface::sweep()
       new interface_cmds::set_table_cmd(m_table_id, l3_proto_t::IPV6, m_hdl));
   }
 
+  if (m_stats) {
+    if (stats_type_t::DETAILED == m_stats_type) {
+      HW::enqueue(new interface_cmds::collect_detail_stats_change_cmd(
+        m_stats_type, handle_i(), false));
+    }
+    HW::enqueue(new interface_cmds::stats_disable_cmd(m_hdl.data()));
+    m_stats.reset();
+  }
+
   // If the interface is up, bring it down
   if (m_state && interface::admin_state_t::UP == m_state.data()) {
     m_state.data() = interface::admin_state_t::DOWN;
     HW::enqueue(new interface_cmds::state_change_cmd(m_state, m_hdl));
   }
+
   if (m_hdl) {
     std::queue<cmd*> cmds;
     HW::enqueue(mk_delete_cmd(cmds));
@@ -181,6 +203,18 @@ interface::replay()
     HW::enqueue(new interface_cmds::state_change_cmd(m_state, m_hdl));
   }
 
+  if (m_stats) {
+    if (stats_type_t::DETAILED == m_stats_type) {
+      m_stats_type.set(rc_t::NOOP);
+      HW::enqueue(new interface_cmds::collect_detail_stats_change_cmd(
+        m_stats_type, handle_i(), true));
+    }
+    stat_listener& listener = m_stats->listener();
+    listener.status().set(rc_t::NOOP);
+    m_stats.reset(new interface_cmds::stats_enable_cmd(listener, handle_i()));
+    HW::enqueue(m_stats);
+  }
+
   if (m_table_id && (m_table_id.data() != route::DEFAULT_TABLE)) {
     HW::enqueue(
       new interface_cmds::set_table_cmd(m_table_id, l3_proto_t::IPV4, m_hdl));
@@ -207,15 +241,21 @@ interface::to_string() const
 {
   std::ostringstream s;
   s << "interface:[" << m_name << " type:" << m_type.to_string()
-    << " hdl:" << m_hdl.to_string()
-    << " l2-address:" << m_l2_address.to_string();
+    << " hdl:" << m_hdl.to_string() << " l2-address:["
+    << m_l2_address.to_string() << "]";
 
   if (m_rd) {
     s << " rd:" << m_rd->to_string();
   }
 
   s << " admin-state:" << m_state.to_string()
-    << " oper-state:" << m_oper.to_string() << "]";
+    << " oper-state:" << m_oper.to_string();
+
+  if (!m_tag.empty()) {
+    s << " tag:[" << m_tag << "]";
+  }
+
+  s << "]";
 
   return (s.str());
 }
@@ -226,7 +266,7 @@ interface::name() const
   return (m_name);
 }
 
-const interface::key_type&
+const interface::key_t&
 interface::key() const
 {
   return (name());
@@ -240,10 +280,22 @@ interface::mk_create_cmd(std::queue<cmd*>& q)
   } else if (type_t::BVI == m_type) {
     q.push(new interface_cmds::loopback_create_cmd(m_hdl, m_name));
     q.push(new interface_cmds::set_tag(m_hdl, m_name));
+    /*
+     * set the m_tag for pretty-print
+     */
+    m_tag = m_name;
   } else if (type_t::AFPACKET == m_type) {
     q.push(new interface_cmds::af_packet_create_cmd(m_hdl, m_name));
+    if (!m_tag.empty())
+      q.push(new interface_cmds::set_tag(m_hdl, m_tag));
   } else if (type_t::TAP == m_type) {
     q.push(new interface_cmds::tap_create_cmd(m_hdl, m_name));
+    if (!m_tag.empty())
+      q.push(new interface_cmds::set_tag(m_hdl, m_tag));
+  } else if (type_t::VHOST == m_type) {
+    q.push(new interface_cmds::vhost_create_cmd(m_hdl, m_name, m_tag));
+  } else {
+    m_hdl.set(rc_t::OK);
   }
 
   return (q);
@@ -258,6 +310,8 @@ interface::mk_delete_cmd(std::queue<cmd*>& q)
     q.push(new interface_cmds::af_packet_delete_cmd(m_hdl, m_name));
   } else if (type_t::TAP == m_type) {
     q.push(new interface_cmds::tap_delete_cmd(m_hdl));
+  } else if (type_t::VHOST == m_type) {
+    q.push(new interface_cmds::vhost_delete_cmd(m_hdl, m_name));
   }
 
   return (q);
@@ -272,8 +326,18 @@ interface::update(const interface& desired)
   if (rc_t::OK != m_hdl.rc()) {
     std::queue<cmd*> cmds;
     HW::enqueue(mk_create_cmd(cmds));
+    /*
+     * interface create now, so we can barf early if it fails
+     */
+    HW::write();
   }
 
+  /*
+   * If the interface is not created do other commands should be issued
+   */
+  if (rc_t::OK != m_hdl.rc())
+    return;
+
   /*
    * change the interface state to that which is deisred
    */
@@ -326,6 +390,12 @@ interface::update(const interface& desired)
   }
 }
 
+void
+interface::set(const admin_state_t& state)
+{
+  m_state = state;
+}
+
 void
 interface::set(const l2_address_t& addr)
 {
@@ -334,16 +404,49 @@ interface::set(const l2_address_t& addr)
   m_l2_address.update(addr);
 }
 
+void
+interface::set(const handle_t& hdl)
+{
+  m_hdl = hdl;
+}
+
 void
 interface::set(const oper_state_t& state)
 {
   m_oper = state;
 }
 
+void
+interface::set(const std::string& tag)
+{
+  m_tag = tag;
+}
+
+void
+interface::enable_stats_i(interface::stat_listener& el, const stats_type_t& st)
+{
+  if (!m_stats) {
+    if (stats_type_t::DETAILED == st) {
+      m_stats_type = st;
+      HW::enqueue(new interface_cmds::collect_detail_stats_change_cmd(
+        m_stats_type, handle_i(), true));
+    }
+    m_stats.reset(new interface_cmds::stats_enable_cmd(el, handle_i()));
+    HW::enqueue(m_stats);
+    HW::write();
+  }
+}
+
+void
+interface::enable_stats(interface::stat_listener& el, const stats_type_t& st)
+{
+  singular()->enable_stats_i(el, st);
+}
+
 std::shared_ptr<interface>
 interface::singular_i() const
 {
-  return (m_db.find_or_add(name(), *this));
+  return (m_db.find_or_add(key(), *this));
 }
 
 std::shared_ptr<interface>
@@ -353,9 +456,9 @@ interface::singular() const
 }
 
 std::shared_ptr<interface>
-interface::find(const std::string& name)
+interface::find(const key_t& k)
 {
-  return (m_db.find(name));
+  return (m_db.find(k));
 }
 
 std::shared_ptr<interface>
@@ -365,9 +468,9 @@ interface::find(const handle_t& handle)
 }
 
 void
-interface::add(const std::string& name, const HW::item<handle_t>& item)
+interface::add(const key_t& key, const HW::item<handle_t>& item)
 {
-  std::shared_ptr<interface> sp = find(name);
+  std::shared_ptr<interface> sp = find(key);
 
   if (sp && item) {
     m_hdl_db[item.data()] = sp;
@@ -383,36 +486,51 @@ interface::remove(const HW::item<handle_t>& item)
 void
 interface::dump(std::ostream& os)
 {
-  m_db.dump(os);
+  db_dump(m_db, os);
 }
 
 void
 interface::event_handler::handle_populate(const client_db::key_t& key)
 {
   /*
- * dump VPP current states
- */
-  std::shared_ptr<interface_cmds::dump_cmd> cmd(new interface_cmds::dump_cmd());
+   * dump VPP current states
+   */
+  std::shared_ptr<interface_cmds::vhost_dump_cmd> vcmd =
+    std::make_shared<interface_cmds::vhost_dump_cmd>();
+
+  HW::enqueue(vcmd);
+  HW::write();
+
+  for (auto& vhost_itf_record : *vcmd) {
+    std::shared_ptr<interface> vitf =
+      interface_factory::new_vhost_user_interface(
+        vhost_itf_record.get_payload());
+    VOM_LOG(log_level_t::DEBUG) << " vhost-dump: " << vitf->to_string();
+    OM::commit(key, *vitf);
+  }
+
+  std::shared_ptr<interface_cmds::dump_cmd> cmd =
+    std::make_shared<interface_cmds::dump_cmd>();
 
   HW::enqueue(cmd);
   HW::write();
 
   for (auto& itf_record : *cmd) {
-    std::unique_ptr<interface> itf =
+    std::shared_ptr<interface> itf =
       interface_factory::new_interface(itf_record.get_payload());
 
     if (itf && interface::type_t::LOCAL != itf->type()) {
       VOM_LOG(log_level_t::DEBUG) << "dump: " << itf->to_string();
       /*
- * Write each of the discovered interfaces into the OM,
- * but disable the HW Command q whilst we do, so that no
- * commands are sent to VPP
- */
      * Write each of the discovered interfaces into the OM,
      * but disable the HW Command q whilst we do, so that no
      * commands are sent to VPP
      */
       OM::commit(key, *itf);
 
       /**
- * Get the address configured on the interface
- */
      * Get the address configured on the interface
      */
       std::shared_ptr<l3_binding_cmds::dump_v4_cmd> dcmd =
         std::make_shared<l3_binding_cmds::dump_v4_cmd>(
           l3_binding_cmds::dump_v4_cmd(itf->handle()));
@@ -432,6 +550,60 @@ interface::event_handler::handle_populate(const client_db::key_t& key)
       }
     }
   }
+
+  std::shared_ptr<bond_interface_cmds::dump_cmd> bcmd =
+    std::make_shared<bond_interface_cmds::dump_cmd>();
+
+  HW::enqueue(bcmd);
+  HW::write();
+
+  for (auto& bond_itf_record : *bcmd) {
+    std::shared_ptr<bond_interface> bond_itf =
+      interface_factory::new_bond_interface(bond_itf_record.get_payload());
+
+    VOM_LOG(log_level_t::DEBUG) << " bond-dump:" << bond_itf->to_string();
+
+    /*
+     * Write each of the discovered interfaces into the OM,
+     * but disable the HW Command q whilst we do, so that no
+     * commands are sent to VPP
+     */
+    OM::commit(key, *bond_itf);
+
+    std::shared_ptr<bond_group_binding_cmds::dump_cmd> scmd =
+      std::make_shared<bond_group_binding_cmds::dump_cmd>(
+        bond_group_binding_cmds::dump_cmd(bond_itf->handle()));
+
+    HW::enqueue(scmd);
+    HW::write();
+
+    bond_group_binding::enslaved_itf_t enslaved_itfs;
+
+    for (auto& slave_itf_record : *scmd) {
+      bond_member slave_itf = interface_factory::new_bond_member_interface(
+        slave_itf_record.get_payload());
+
+      VOM_LOG(log_level_t::DEBUG) << " slave-dump:" << slave_itf.to_string();
+
+      /*
+       * Write each of the discovered interfaces into the OM,
+       * but disable the HW Command q whilst we do, so that no
+       * commands are sent to VPP
+       */
+      //      OM::commit(slave_itf->key(), *slave_itf);
+      enslaved_itfs.insert(slave_itf);
+    }
+
+    if (!enslaved_itfs.empty()) {
+      bond_group_binding bid(*bond_itf, enslaved_itfs);
+      /*
+       * Write each of the discovered interfaces into the OM,
+       * but disable the HW Command q whilst we do, so that no
+       * commands are sent to VPP
+       */
+      OM::commit(key, bid);
+    }
+  }
 }
 
 interface::event_handler::event_handler()
@@ -455,9 +627,11 @@ interface::event_handler::order() const
 void
 interface::event_handler::show(std::ostream& os)
 {
-  m_db.dump(os);
-}
+  db_dump(m_db, os);
 }
+
+} // namespace VOM
+
 /*
  * fd.io coding-style-patch-verification: ON
  *