VOM: fixes for stats
[vpp.git] / extras / vom / vom / interface.cpp
index 6faf349..504511e 100644 (file)
@@ -23,6 +23,8 @@
 #include "vom/logger.hpp"
 #include "vom/prefix.hpp"
 #include "vom/singular_db_funcs.hpp"
+#include "vom/stat_reader.hpp"
+#include "vom/tap_interface_cmds.hpp"
 
 namespace VOM {
 /**
@@ -37,6 +39,11 @@ std::map<handle_t, std::weak_ptr<interface>> interface::m_hdl_db;
 
 interface::event_handler interface::m_evh;
 
+/**
+ * the event enable command.
+ */
+std::shared_ptr<interface_cmds::events_cmd> interface::m_events_cmd;
+
 /**
  * Construct a new object matching the desried state
  */
@@ -51,6 +58,8 @@ interface::interface(const std::string& name,
   , m_table_id(route::DEFAULT_TABLE)
   , m_l2_address(l2_address_t::ZERO, rc_t::UNSET)
   , m_stats_type(stats_type_t::NORMAL)
+  , m_stats({})
+  , m_listener(nullptr)
   , m_oper(oper_state_t::DOWN)
   , m_tag(tag)
 {
@@ -69,6 +78,8 @@ interface::interface(const std::string& name,
   , 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_stats({})
+  , m_listener(nullptr)
   , m_oper(oper_state_t::DOWN)
   , m_tag(tag)
 {
@@ -83,6 +94,8 @@ interface::interface(const interface& o)
   , m_table_id(o.m_table_id)
   , m_l2_address(o.m_l2_address)
   , m_stats_type(o.m_stats_type)
+  , m_stats(o.m_stats)
+  , m_listener(o.m_listener)
   , m_oper(o.m_oper)
   , m_tag(o.m_tag)
 {
@@ -169,13 +182,8 @@ 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 (m_listener) {
+    disable_stats_i();
   }
 
   // If the interface is up, bring it down
@@ -203,16 +211,8 @@ 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_listener) {
+    enable_stats(m_listener, m_stats_type.data());
   }
 
   if (m_table_id && (m_table_id.data() != route::DEFAULT_TABLE)) {
@@ -286,8 +286,7 @@ interface::mk_create_cmd(std::queue<cmd*>& q)
     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));
+  } else if (type_t::TAPV2 == m_type) {
     if (!m_tag.empty())
       q.push(new interface_cmds::set_tag(m_hdl, m_tag));
   } else if (type_t::VHOST == m_type) {
@@ -306,8 +305,6 @@ interface::mk_delete_cmd(std::queue<cmd*>& q)
     q.push(new interface_cmds::loopback_delete_cmd(m_hdl));
   } else if (type_t::AFPACKET == m_type) {
     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));
   }
@@ -421,26 +418,101 @@ interface::set(const std::string& tag)
 }
 
 void
-interface::enable_stats_i(interface::stat_listener& el, const stats_type_t& st)
+interface::set(counter_t count, const std::string& stat_type)
+{
+  if ("rx" == stat_type)
+    m_stats.m_rx = count;
+  else if ("tx" == stat_type)
+    m_stats.m_tx = count;
+  else if ("rx-unicast" == stat_type)
+    m_stats.m_rx_unicast = count;
+  else if ("tx-unicast" == stat_type)
+    m_stats.m_tx_unicast = count;
+  else if ("rx-multicast" == stat_type)
+    m_stats.m_rx_multicast = count;
+  else if ("tx-multicast" == stat_type)
+    m_stats.m_tx_multicast = count;
+  else if ("rx-broadcast" == stat_type)
+    m_stats.m_rx_broadcast = count;
+  else if ("tx-broadcast" == stat_type)
+    m_stats.m_rx_broadcast = count;
+}
+
+const interface::stats_t&
+interface::get_stats(void) const
+{
+  return m_stats;
+}
+
+void
+interface::publish_stats()
 {
-  if (!m_stats) {
+  m_listener->handle_interface_stat(*this);
+}
+
+std::ostream&
+operator<<(std::ostream& os, const interface::stats_t& stats)
+{
+  os << "["
+     << "rx [packets " << stats.m_rx.packets << ", bytes " << stats.m_rx.bytes
+     << "]"
+     << " rx-unicast [packets " << stats.m_rx_unicast.packets << ", bytes "
+     << stats.m_rx_unicast.bytes << "]"
+     << " rx-multicast [packets " << stats.m_rx_multicast.packets << ", bytes "
+     << stats.m_rx_multicast.bytes << "]"
+     << " rx-broadcast [packets " << stats.m_rx_broadcast.packets << ", bytes "
+     << stats.m_rx_broadcast.bytes << "]"
+     << " tx [packets " << stats.m_tx.packets << ", bytes " << stats.m_tx.bytes
+     << "]"
+     << " tx-unicast [packets " << stats.m_tx_unicast.packets << ", bytes "
+     << stats.m_tx_unicast.bytes << "]"
+     << " tx-multicast [packets " << stats.m_tx_multicast.packets << ", bytes "
+     << stats.m_tx_multicast.bytes << "]"
+     << " tx-broadcast [packets " << stats.m_tx_broadcast.packets << ", bytes "
+     << stats.m_tx_broadcast.bytes << "]]" << std::endl;
+
+  return (os);
+}
+
+void
+interface::enable_stats_i(interface::stat_listener* el, const stats_type_t& st)
+{
+  if (el != NULL) {
     if (stats_type_t::DETAILED == st) {
-      m_stats_type = st;
+      m_stats_type.set(rc_t::NOOP);
       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();
+    stat_reader::registers(*this);
+    m_listener = el;
   }
 }
 
 void
-interface::enable_stats(interface::stat_listener& el, const stats_type_t& st)
+interface::enable_stats(interface::stat_listener* el, const stats_type_t& st)
 {
   singular()->enable_stats_i(el, st);
 }
 
+void
+interface::disable_stats_i()
+{
+  if (m_listener != NULL) {
+    if (stats_type_t::DETAILED == m_stats_type) {
+      HW::enqueue(new interface_cmds::collect_detail_stats_change_cmd(
+        m_stats_type, handle_i(), false));
+    }
+    stat_reader::unregisters(*this);
+    m_listener = NULL;
+  }
+}
+
+void
+interface::disable_stats()
+{
+  singular()->disable_stats_i();
+}
+
 std::shared_ptr<interface>
 interface::singular_i() const
 {
@@ -487,11 +559,25 @@ interface::dump(std::ostream& os)
   db_dump(m_db, os);
 }
 
+void
+interface::enable_events(interface::event_listener& el)
+{
+  m_events_cmd = std::make_shared<interface_cmds::events_cmd>(el);
+  HW::enqueue(m_events_cmd);
+  HW::write();
+}
+
+void
+interface::disable_events()
+{
+  m_events_cmd.reset();
+}
+
 void
 interface::event_handler::handle_populate(const client_db::key_t& key)
 {
   /*
-   * dump VPP current states
+   * dump VPP vhost-user interfaces
    */
   std::shared_ptr<interface_cmds::vhost_dump_cmd> vcmd =
     std::make_shared<interface_cmds::vhost_dump_cmd>();
@@ -507,6 +593,48 @@ interface::event_handler::handle_populate(const client_db::key_t& key)
     OM::commit(key, *vitf);
   }
 
+  /*
+   * dump VPP af-packet interfaces
+   */
+  std::shared_ptr<interface_cmds::af_packet_dump_cmd> afcmd =
+    std::make_shared<interface_cmds::af_packet_dump_cmd>();
+
+  HW::enqueue(afcmd);
+  HW::write();
+
+  for (auto& af_packet_itf_record : *afcmd) {
+    std::shared_ptr<interface> afitf =
+      interface_factory::new_af_packet_interface(
+        af_packet_itf_record.get_payload());
+    VOM_LOG(log_level_t::DEBUG) << " af_packet-dump: " << afitf->to_string();
+    OM::commit(key, *afitf);
+  }
+
+  /*
+   * dump VPP tapv2 interfaces
+   */
+  std::shared_ptr<tap_interface_cmds::tapv2_dump_cmd> tapv2cmd =
+    std::make_shared<tap_interface_cmds::tapv2_dump_cmd>();
+
+  HW::enqueue(tapv2cmd);
+  HW::write();
+
+  for (auto& tapv2_record : *tapv2cmd) {
+    std::shared_ptr<tap_interface> tapv2itf =
+      interface_factory::new_tap_interface(tapv2_record.get_payload());
+    VOM_LOG(log_level_t::DEBUG) << "tapv2-dump: " << tapv2itf->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, *tapv2itf);
+  }
+
+  /*
+   * dump VPP interfaces
+   */
   std::shared_ptr<interface_cmds::dump_cmd> cmd =
     std::make_shared<interface_cmds::dump_cmd>();
 
@@ -553,6 +681,9 @@ interface::event_handler::handle_populate(const client_db::key_t& key)
     }
   }
 
+  /*
+   * dump VPP bond interfaces
+   */
   std::shared_ptr<bond_interface_cmds::dump_cmd> bcmd =
     std::make_shared<bond_interface_cmds::dump_cmd>();