VOM: fixes for interface recreate on agent restart and L2 re-binding

Change-Id: I14c838ee99f9bc2db66bb2e775039d2cb2e7924f
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
diff --git a/src/vpp-api/vom/interface.cpp b/src/vpp-api/vom/interface.cpp
index 10728ce..9fa96af 100644
--- a/src/vpp-api/vom/interface.cpp
+++ b/src/vpp-api/vom/interface.cpp
@@ -250,6 +250,8 @@
     q.push(new interface_cmds::af_packet_create_cmd(m_hdl, m_name));
   } else if (type_t::TAP == m_type) {
     q.push(new interface_cmds::tap_create_cmd(m_hdl, m_name));
+  } else {
+    m_hdl.set(rc_t::OK);
   }
 
   return (q);
@@ -365,9 +367,11 @@
 void
 interface::enable_stats_i(interface::stat_listener& el)
 {
-  m_stats.reset(new interface_cmds::stats_enable_cmd(el, handle_i()));
-  HW::enqueue(m_stats);
-  HW::write();
+  if (!m_stats) {
+    m_stats.reset(new interface_cmds::stats_enable_cmd(el, handle_i()));
+    HW::enqueue(m_stats);
+    HW::write();
+  }
 }
 
 void
diff --git a/src/vpp-api/vom/l2_binding.cpp b/src/vpp-api/vom/l2_binding.cpp
index cc0e84a..749557c 100644
--- a/src/vpp-api/vom/l2_binding.cpp
+++ b/src/vpp-api/vom/l2_binding.cpp
@@ -152,17 +152,28 @@
 l2_binding::update(const l2_binding& desired)
 {
   /*
- * the desired state is always that the interface should be created
- */
+   * 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()));
+  } 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()));
+    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()));
   }
 
   /*
- * set the VTR operation is request
- */
+   * set the VTR operation if request
+   */
   if (m_vtr_op.update(desired.m_vtr_op)) {
     HW::enqueue(new l2_binding_cmds::set_vtr_op_cmd(m_vtr_op, m_itf->handle(),
                                                     m_vtr_op_tag));
diff --git a/src/vpp-api/vom/l2_binding.hpp b/src/vpp-api/vom/l2_binding.hpp
index ba97cab..d24f69e 100644
--- a/src/vpp-api/vom/l2_binding.hpp
+++ b/src/vpp-api/vom/l2_binding.hpp
@@ -185,12 +185,12 @@
    * interface is bound to. By holding the reference here, we can
    * guarantee that this object will outlive the BD.
    */
-  const std::shared_ptr<bridge_domain> m_bd;
+  std::shared_ptr<bridge_domain> m_bd;
 
   /**
    * HW configuration for the binding. The bool representing the
    * do/don't bind.
- */
+   */
   HW::item<bool> m_binding;
 
   /**
diff --git a/src/vpp-api/vom/l2_binding_cmds.cpp b/src/vpp-api/vom/l2_binding_cmds.cpp
index 6b67c70..0f91e4b 100644
--- a/src/vpp-api/vom/l2_binding_cmds.cpp
+++ b/src/vpp-api/vom/l2_binding_cmds.cpp
@@ -143,7 +143,6 @@
   VAPI_CALL(req.execute());
 
   wait();
-  m_hw_item.set(rc_t::NOOP);
 
   return (rc_t::OK);
 }