VOM: stats: Associate stat obj to interface

Change-Id: Id8b159dd72b92798538a32fe570fb0038d742ef2
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
diff --git a/src/vpp-api/vom/interface.cpp b/src/vpp-api/vom/interface.cpp
index 8f1023d..39ca074 100644
--- a/src/vpp-api/vom/interface.cpp
+++ b/src/vpp-api/vom/interface.cpp
@@ -163,11 +163,15 @@
       new interface_cmds::set_table_cmd(m_table_id, l3_proto_t::IPV6, m_hdl));
   }
 
+  if (m_stats)
+    HW::dequeue(m_stats);
+
   // 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));
@@ -356,6 +360,20 @@
   m_oper = state;
 }
 
+void
+interface::enable_stats_i(interface::stat_listener& el)
+{
+  m_stats.reset(new interface_cmds::stats_cmd(el, handle_i()));
+  HW::enqueue(m_stats);
+  HW::write();
+}
+
+void
+interface::enable_stats(interface::stat_listener& el)
+{
+  singular()->enable_stats_i(el);
+}
+
 std::shared_ptr<interface>
 interface::singular_i() const
 {
diff --git a/src/vpp-api/vom/interface.hpp b/src/vpp-api/vom/interface.hpp
index 181e76d..76ecf8a 100644
--- a/src/vpp-api/vom/interface.hpp
+++ b/src/vpp-api/vom/interface.hpp
@@ -421,6 +421,11 @@
    */
   static void dump(std::ostream& os);
 
+  /**
+   * Enable stats for this interface
+   */
+  void enable_stats(stat_listener& el);
+
 protected:
   /**
    * Construct an interface object with a handle and a HW address
@@ -513,6 +518,11 @@
   static event_handler m_evh;
 
   /**
+   * enable the interface stats in the singular instance
+   */
+  void enable_stats_i(stat_listener& el);
+
+  /**
    * Commit the acculmulated changes into VPP. i.e. to a 'HW" write.
    */
   void update(const interface& obj);
@@ -550,6 +560,11 @@
   std::shared_ptr<route_domain> m_rd;
 
   /**
+   * shared pointer to the stats object for this interface.
+   */
+  std::shared_ptr<interface_cmds::stats_cmd> m_stats;
+
+  /**
    * The state of the interface
    */
   HW::item<admin_state_t> m_state;
diff --git a/src/vpp-api/vom/interface_cmds.cpp b/src/vpp-api/vom/interface_cmds.cpp
index 4f6286f..750ad1f 100644
--- a/src/vpp-api/vom/interface_cmds.cpp
+++ b/src/vpp-api/vom/interface_cmds.cpp
@@ -401,11 +401,10 @@
 /**
  * Interface statistics
  */
-stats_cmd::stats_cmd(interface::stat_listener& el,
-                     const std::vector<handle_t>& interfaces)
+stats_cmd::stats_cmd(interface::stat_listener& el, const handle_t& handle)
   : event_cmd(el.status())
   , m_listener(el)
-  , m_swifindex(interfaces)
+  , m_swifindex(handle)
 {
 }
 
@@ -419,29 +418,21 @@
 stats_cmd::issue(connection& con)
 {
   /*
- * First set the clal back to handle the interface stats
- */
+   * First set the call back to handle the interface stats
+   */
   m_reg.reset(new reg_t(con.ctx(), std::ref(*(static_cast<event_cmd*>(this)))));
-  // m_reg->execute();
 
   /*
- * then send the request to enable them
- */
-  msg_t req(con.ctx(), m_swifindex.size(),
-            std::ref(*(static_cast<rpc_cmd*>(this))));
+   * then send the request to enable them
+   */
+  msg_t req(con.ctx(), 1, std::ref(*(static_cast<rpc_cmd*>(this))));
 
   auto& payload = req.get_request().get_payload();
   payload.enable_disable = 1;
   payload.pid = getpid();
-  payload.num = m_swifindex.size();
+  payload.num = 1;
 
-  auto it = m_swifindex.cbegin();
-  uint32_t ii = 0;
-  while (it != m_swifindex.cend()) {
-    payload.sw_ifs[ii] = it->value();
-    ++it;
-    ++ii;
-  }
+  payload.sw_ifs[0] = m_swifindex.value();
 
   VAPI_CALL(req.execute());
 
@@ -453,6 +444,20 @@
 void
 stats_cmd::retire(connection& con)
 {
+  /*
+   * disable interface stats.
+   */
+  msg_t req(con.ctx(), 1, std::ref(*(static_cast<rpc_cmd*>(this))));
+
+  auto& payload = req.get_request().get_payload();
+  payload.enable_disable = 0;
+  payload.pid = getpid();
+  payload.num = 1;
+  payload.sw_ifs[0] = m_swifindex.value();
+
+  VAPI_CALL(req.execute());
+
+  wait();
 }
 
 void
diff --git a/src/vpp-api/vom/interface_cmds.hpp b/src/vpp-api/vom/interface_cmds.hpp
index 4178be3..c86df92 100644
--- a/src/vpp-api/vom/interface_cmds.hpp
+++ b/src/vpp-api/vom/interface_cmds.hpp
@@ -364,7 +364,7 @@
   /**
    * The listeners to notify when data/events arrive
    */
-  interface::interface::event_listener& m_listener;
+  interface::event_listener& m_listener;
 };
 
 /**
@@ -377,8 +377,7 @@
   /**
    * Constructor taking the listner to notify
    */
-  stats_cmd(interface::stat_listener& el,
-            const std::vector<handle_t>& interfaces);
+  stats_cmd(interface::stat_listener& el, const handle_t& handle);
 
   /**
    * Issue the command to VPP/HW
@@ -409,9 +408,9 @@
   /**
    * The listeners to notify when data/stats arrive
    */
-  interface::interface::stat_listener& m_listener;
+  interface::stat_listener& m_listener;
 
-  std::vector<handle_t> m_swifindex;
+  handle_t m_swifindex;
 };
 
 /**
diff --git a/src/vpp-api/vom/rpc_cmd.hpp b/src/vpp-api/vom/rpc_cmd.hpp
index 60dbd47..ae3c675 100644
--- a/src/vpp-api/vom/rpc_cmd.hpp
+++ b/src/vpp-api/vom/rpc_cmd.hpp
@@ -71,7 +71,16 @@
   /**
    * Fulfill the commands promise. Called from the RX thread
    */
-  void fulfill(const DATA& d) { m_promise.set_value(d); }
+  void fulfill(const DATA& d)
+  {
+    m_promise.set_value(d);
+
+    /*
+     * we reset the promise after setting the value to reuse it
+     * when we run the retire command from the same cmd object
+     */
+    m_promise = std::promise<DATA>();
+  }
 
   /**
    * Wait on the commands promise. i.e. block on the completion