VOM: Additions to allow uses to UT applications that use VOM 52/9552/3
authorNeale Ranns <neale.ranns@cisco.com>
Thu, 23 Nov 2017 20:15:00 +0000 (12:15 -0800)
committerNeale Ranns <nranns@cisco.com>
Fri, 24 Nov 2017 14:04:48 +0000 (14:04 +0000)
- find object by key
- compare objects

Change-Id: I36ec8612be9482bcef7ceced2a59f7403f77b3e8
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
52 files changed:
src/vpp-api/vom/Makefile.am
src/vpp-api/vom/acl_binding.cpp
src/vpp-api/vom/acl_binding.hpp
src/vpp-api/vom/arp_proxy_binding.cpp
src/vpp-api/vom/arp_proxy_binding.hpp
src/vpp-api/vom/bridge_domain.cpp
src/vpp-api/vom/bridge_domain.hpp
src/vpp-api/vom/bridge_domain_arp_entry.cpp
src/vpp-api/vom/bridge_domain_arp_entry.hpp
src/vpp-api/vom/bridge_domain_entry.cpp
src/vpp-api/vom/bridge_domain_entry.hpp
src/vpp-api/vom/client_db.cpp
src/vpp-api/vom/cmd.hpp
src/vpp-api/vom/connection.cpp
src/vpp-api/vom/connection.hpp
src/vpp-api/vom/dhcp_config.cpp
src/vpp-api/vom/dhcp_config.hpp
src/vpp-api/vom/hw.hpp
src/vpp-api/vom/inspect.cpp
src/vpp-api/vom/interface.cpp
src/vpp-api/vom/interface.hpp
src/vpp-api/vom/interface_ip6_nd.hpp
src/vpp-api/vom/interface_span.cpp
src/vpp-api/vom/interface_span.hpp
src/vpp-api/vom/interface_types.cpp
src/vpp-api/vom/ip_unnumbered.hpp
src/vpp-api/vom/l2_binding.cpp
src/vpp-api/vom/l2_binding.hpp
src/vpp-api/vom/l3_binding.cpp
src/vpp-api/vom/l3_binding.hpp
src/vpp-api/vom/lldp_binding.cpp
src/vpp-api/vom/lldp_binding.hpp
src/vpp-api/vom/lldp_global.cpp
src/vpp-api/vom/lldp_global.hpp
src/vpp-api/vom/lldp_global_cmds.hpp
src/vpp-api/vom/nat_binding.hpp
src/vpp-api/vom/neighbour.cpp
src/vpp-api/vom/neighbour.hpp
src/vpp-api/vom/om.cpp
src/vpp-api/vom/om.hpp
src/vpp-api/vom/route.cpp
src/vpp-api/vom/route.hpp
src/vpp-api/vom/route_domain.cpp
src/vpp-api/vom/route_domain.hpp
src/vpp-api/vom/singular_db.hpp
src/vpp-api/vom/sub_interface.cpp
src/vpp-api/vom/sub_interface.hpp
src/vpp-api/vom/tap_interface.cpp
src/vpp-api/vom/types.cpp
src/vpp-api/vom/types.hpp
src/vpp-api/vom/vxlan_tunnel.cpp
test/ext/vom_test.cpp

index cdeacdf..8eab140 100644 (file)
@@ -15,7 +15,7 @@ AUTOMAKE_OPTIONS = foreign
 ACLOCAL_AMFLAGS = -I m4
 AM_LIBTOOLFLAGS = --quiet
 
-AM_CXXFLAGS = -Wall -std=gnu++11 -I${top_srcdir} -I${top_builddir}/vpp-api/vapi/ -I$(top_srcdir)/vpp-api/ -I${libdir}/../include
+AM_CXXFLAGS = -Wall -std=gnu++11 -I${top_srcdir} -I${top_builddir}/vpp-api/vapi/ -I$(top_srcdir)/vpp-api/ -I${libdir}/../include -O0
 AM_LDFLAGS = -shared -no-undefined
 
 bin_PROGRAMS =
index 832e232..267b02a 100644 (file)
@@ -144,7 +144,7 @@ l2_binding::replay(void)
 
 std::ostream&
 operator<<(std::ostream& os,
-           const std::pair<direction_t, interface::key_type>& key)
+           const std::pair<direction_t, interface::key_t>& key)
 {
   os << "[" << key.first.to_string() << " " << key.second << "]";
 
index 1e87a88..3687503 100644 (file)
@@ -40,7 +40,7 @@ public:
   /**
    * The key for a binding is the direction and the interface
    */
-  typedef std::pair<direction_t, interface::key_type> key_t;
+  typedef std::pair<direction_t, interface::key_t> key_t;
 
   /**
    * Construct a new object matching the desried state
@@ -224,9 +224,8 @@ template <typename LIST>
 typename ACL::binding<LIST>::event_handler binding<LIST>::m_evh;
 };
 
-std::ostream& operator<<(
-  std::ostream& os,
-  const std::pair<direction_t, interface::key_type>& key);
+std::ostream& operator<<(std::ostream& os,
+                         const std::pair<direction_t, interface::key_t>& key);
 };
 
 /*
index c44cda3..407436c 100644 (file)
@@ -21,7 +21,7 @@ namespace VOM {
 /**
  * A DB of all ARP proxy bindings configs
  */
-singular_db<interface::key_type, arp_proxy_binding> arp_proxy_binding::m_db;
+singular_db<interface::key_t, arp_proxy_binding> arp_proxy_binding::m_db;
 
 arp_proxy_binding::event_handler arp_proxy_binding::m_evh;
 
index 2ee814a..f57f697 100644 (file)
@@ -116,7 +116,7 @@ private:
   /**
    * It's the singular_db class that calls replay()
    */
-  friend class singular_db<interface::key_type, arp_proxy_binding>;
+  friend class singular_db<interface::key_t, arp_proxy_binding>;
 
   /**
    * Sweep/reap the object if still stale
@@ -149,7 +149,7 @@ private:
   /**
    * A map of all ArpProxy bindings keyed against the interface.
    */
-  static singular_db<interface::key_type, arp_proxy_binding> m_db;
+  static singular_db<interface::key_t, arp_proxy_binding> m_db;
 };
 };
 
index 81d8362..6826819 100644 (file)
@@ -52,12 +52,24 @@ bridge_domain::bridge_domain(const bridge_domain& o)
 {
 }
 
+const bridge_domain::key_t&
+bridge_domain::key() const
+{
+  return (m_id.data());
+}
+
 uint32_t
 bridge_domain::id() const
 {
   return (m_id.data());
 }
 
+bool
+bridge_domain::operator==(const bridge_domain& b) const
+{
+  return (id() == b.id());
+}
+
 void
 bridge_domain::sweep()
 {
@@ -93,41 +105,17 @@ bridge_domain::to_string() const
 }
 
 std::shared_ptr<bridge_domain>
-bridge_domain::find(uint32_t id)
+bridge_domain::find(const key_t& key)
 {
-  /*
- * Loop throught the entire map looking for matching interface.
- * not the most efficient algorithm, but it will do for now. The
- * number of L3 configs is low and this is only called during bootup
- */
-  std::shared_ptr<bridge_domain> bd;
-
-  auto it = m_db.cbegin();
-
-  while (it != m_db.cend()) {
-    /*
- * The key in the DB is a pair of the interface's name and prefix.
- * If the keys match, save the L3-config
- */
-    auto key = it->first;
-
-    if (id == key) {
-      bd = it->second.lock();
-      break;
-    }
-
-    ++it;
-  }
-
-  return (bd);
+  return (m_db.find(key));
 }
 
 void
 bridge_domain::update(const bridge_domain& 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_id.rc()) {
     HW::enqueue(new bridge_domain_cmds::create_cmd(m_id, m_learning_mode));
   }
index 2c134f0..c7f84e9 100644 (file)
@@ -31,6 +31,11 @@ namespace VOM {
 class bridge_domain : public object_base
 {
 public:
+  /**
+   * Key Type for Bridge Domains in the sigular DB
+   */
+  typedef uint32_t key_t;
+
   /**
    * Bridge Domain Learning mode
    */
@@ -67,6 +72,21 @@ public:
    */
   ~bridge_domain();
 
+  /**
+   * Comparison operator - for UT
+   */
+  bool operator==(const bridge_domain& b) const;
+
+  /**
+   * Return the bridge domain's VPP ID
+   */
+  uint32_t id() const;
+
+  /**
+   * Return the bridge domain's key
+   */
+  const key_t& key() const;
+
   /**
    * Return the matchin 'singular' instance of the bridge-domain
    */
@@ -77,15 +97,10 @@ public:
    */
   std::string to_string(void) const;
 
-  /**
-   * Return VPP's handle for this obejct
-   */
-  uint32_t id() const;
-
   /**
    * Static function to find the bridge_domain in the model
    */
-  static std::shared_ptr<bridge_domain> find(uint32_t id);
+  static std::shared_ptr<bridge_domain> find(const key_t& key);
 
   /**
    * Dump all bridge-doamin into the stream provided
@@ -146,7 +161,7 @@ private:
   /**
    * It's the singular_db class that calls replay()
    */
-  friend class singular_db<uint32_t, bridge_domain>;
+  friend class singular_db<key_t, bridge_domain>;
 
   /**
    * Sweep/reap the object if still stale
@@ -171,7 +186,7 @@ private:
   /**
    * A map of all interfaces key against the interface's name
    */
-  static singular_db<uint32_t, bridge_domain> m_db;
+  static singular_db<key_t, bridge_domain> m_db;
 };
 };
 
index ee34dbb..e8ae30f 100644 (file)
@@ -25,22 +25,22 @@ bridge_domain_arp_entry::event_handler bridge_domain_arp_entry::m_evh;
 
 bridge_domain_arp_entry::bridge_domain_arp_entry(
   const bridge_domain& bd,
-  const mac_address_t& mac,
-  const boost::asio::ip::address& ip_addr)
+  const boost::asio::ip::address& ip_addr,
+  const mac_address_t& mac)
   : m_hw(false)
   , m_bd(bd.singular())
-  , m_mac(mac)
   , m_ip_addr(ip_addr)
+  , m_mac(mac)
 {
 }
 
 bridge_domain_arp_entry::bridge_domain_arp_entry(
-  const mac_address_t& mac,
-  const boost::asio::ip::address& ip_addr)
+  const boost::asio::ip::address& ip_addr,
+  const mac_address_t& mac)
   : m_hw(false)
   , m_bd(nullptr)
-  , m_mac(mac)
   , m_ip_addr(ip_addr)
+  , m_mac(mac)
 {
   /*
  * the route goes in the default table
@@ -54,8 +54,8 @@ bridge_domain_arp_entry::bridge_domain_arp_entry(
   const bridge_domain_arp_entry& bde)
   : m_hw(bde.m_hw)
   , m_bd(bde.m_bd)
-  , m_mac(bde.m_mac)
   , m_ip_addr(bde.m_ip_addr)
+  , m_mac(bde.m_mac)
 {
 }
 
@@ -64,7 +64,19 @@ bridge_domain_arp_entry::~bridge_domain_arp_entry()
   sweep();
 
   // not in the DB anymore.
-  m_db.release(std::make_tuple(m_bd->id(), m_mac, m_ip_addr), this);
+  m_db.release(key(), this);
+}
+
+const bridge_domain_arp_entry::key_t
+bridge_domain_arp_entry::key() const
+{
+  return (std::make_pair(m_bd->key(), m_ip_addr));
+}
+
+bool
+bridge_domain_arp_entry::operator==(const bridge_domain_arp_entry& bdae) const
+{
+  return ((key() == bdae.key()) && (m_mac == bdae.m_mac));
 }
 
 void
@@ -111,8 +123,13 @@ bridge_domain_arp_entry::update(const bridge_domain_arp_entry& r)
 std::shared_ptr<bridge_domain_arp_entry>
 bridge_domain_arp_entry::find_or_add(const bridge_domain_arp_entry& temp)
 {
-  return (m_db.find_or_add(
-    std::make_tuple(temp.m_bd->id(), temp.m_mac, temp.m_ip_addr), temp));
+  return (m_db.find_or_add(temp.key(), temp));
+}
+
+std::shared_ptr<bridge_domain_arp_entry>
+bridge_domain_arp_entry::find(const key_t& k)
+{
+  return (m_db.find(k));
 }
 
 std::shared_ptr<bridge_domain_arp_entry>
@@ -127,15 +144,6 @@ bridge_domain_arp_entry::dump(std::ostream& os)
   m_db.dump(os);
 }
 
-std::ostream&
-operator<<(std::ostream& os, const bridge_domain_arp_entry::key_t& key)
-{
-  os << "[" << std::get<0>(key) << ", " << std::get<1>(key) << ", "
-     << std::get<2>(key) << "]";
-
-  return (os);
-}
-
 bridge_domain_arp_entry::event_handler::event_handler()
 {
   OM::register_listener(this);
index caad96b..b4af6a0 100644 (file)
@@ -32,20 +32,20 @@ public:
    * The key for a bridge_domain ARP entry;
    *  the BD, IP address and MAC address
    */
-  typedef std::tuple<uint32_t, mac_address_t, boost::asio::ip::address> key_t;
+  typedef std::pair<bridge_domain::key_t, boost::asio::ip::address> key_t;
 
   /**
-   * Construct a bridge_domain in the given bridge domain
+   * Construct a bridge domain ARP Entry in the given bridge domain
    */
   bridge_domain_arp_entry(const bridge_domain& bd,
-                          const mac_address_t& mac,
-                          const boost::asio::ip::address& ip_addr);
+                          const boost::asio::ip::address& ip_addr,
+                          const mac_address_t& mac);
 
   /**
-   * Construct a bridge_domain in the default table
+   * Construct a bridge domain ARP entry in the default table
    */
-  bridge_domain_arp_entry(const mac_address_t& mac,
-                          const boost::asio::ip::address& ip_addr);
+  bridge_domain_arp_entry(const boost::asio::ip::address& ip_addr,
+                          const mac_address_t& mac);
 
   /**
    * Copy Construct
@@ -57,6 +57,16 @@ public:
    */
   ~bridge_domain_arp_entry();
 
+  /**
+   * Return the object's key
+   */
+  const key_t key() const;
+
+  /**
+   * comparison operator
+   */
+  bool operator==(const bridge_domain_arp_entry& bdae) const;
+
   /**
    * Return the matching 'singular instance'
    */
@@ -65,8 +75,7 @@ public:
   /**
    * Find the instnace of the bridge_domain domain in the OM
    */
-  static std::shared_ptr<bridge_domain_arp_entry> find(
-    const bridge_domain_arp_entry& temp);
+  static std::shared_ptr<bridge_domain_arp_entry> find(const key_t& k);
 
   /**
    * Dump all bridge_domain-doamin into the stream provided
@@ -156,14 +165,14 @@ private:
   std::shared_ptr<bridge_domain> m_bd;
 
   /**
-   * The mac to match
+   * The IP address
    */
-  mac_address_t m_mac;
+  boost::asio::ip::address m_ip_addr;
 
   /**
-   * The IP address
+   * The mac to return
    */
-  boost::asio::ip::address m_ip_addr;
+  mac_address_t m_mac;
 
   /**
    * A map of all bridge_domains
@@ -173,7 +182,7 @@ private:
 
 std::ostream& operator<<(std::ostream& os,
                          const bridge_domain_arp_entry::key_t& key);
-};
+}; // namespace
 
 /*
  * fd.io coding-style-patch-verification: ON
index 343d82d..79f36f7 100644 (file)
@@ -55,12 +55,24 @@ bridge_domain_entry::bridge_domain_entry(const bridge_domain_entry& bde)
 {
 }
 
+const bridge_domain_entry::key_t
+bridge_domain_entry::key() const
+{
+  return (std::make_pair(m_bd->key(), m_mac));
+}
+
+bool
+bridge_domain_entry::operator==(const bridge_domain_entry& bde) const
+{
+  return ((key() == bde.key()) && (m_tx_itf == bde.m_tx_itf));
+}
+
 bridge_domain_entry::~bridge_domain_entry()
 {
   sweep();
 
   // not in the DB anymore.
-  m_db.release(std::make_pair(m_bd->id(), m_mac), this);
+  m_db.release(key(), this);
 }
 
 void
@@ -106,7 +118,13 @@ bridge_domain_entry::update(const bridge_domain_entry& r)
 std::shared_ptr<bridge_domain_entry>
 bridge_domain_entry::find_or_add(const bridge_domain_entry& temp)
 {
-  return (m_db.find_or_add(std::make_pair(temp.m_bd->id(), temp.m_mac), temp));
+  return (m_db.find_or_add(temp.key(), temp));
+}
+
+std::shared_ptr<bridge_domain_entry>
+bridge_domain_entry::find(const key_t& k)
+{
+  return (m_db.find(k));
 }
 
 std::shared_ptr<bridge_domain_entry>
index 35ea8b6..2aef697 100644 (file)
@@ -30,7 +30,7 @@ public:
   /**
    * The key for a bridge_domain
    */
-  typedef std::pair<uint32_t, mac_address_t> key_t;
+  typedef std::pair<bridge_domain::key_t, mac_address_t> key_t;
 
   /**
    * Construct a bridge_domain in the given bridge domain
@@ -54,6 +54,16 @@ public:
    */
   ~bridge_domain_entry();
 
+  /**
+   * Return the object's key
+   */
+  const key_t key() const;
+
+  /**
+   * comparison operator
+   */
+  bool operator==(const bridge_domain_entry& be) const;
+
   /**
    * Return the matching 'singular instance'
    */
@@ -62,8 +72,7 @@ public:
   /**
    * Find the instnace of the bridge_domain domain in the OM
    */
-  static std::shared_ptr<bridge_domain_entry> find(
-    const bridge_domain_entry& temp);
+  static std::shared_ptr<bridge_domain_entry> find(const key_t& k);
 
   /**
    * Dump all bridge_domain-doamin into the stream provided
index fad2c13..41463d1 100644 (file)
@@ -25,7 +25,10 @@ client_db::find(const client_db::key_t& k)
 void
 client_db::flush(const client_db::key_t& k)
 {
-  m_objs.erase(m_objs.find(k));
+  auto found = m_objs.find(k);
+
+  if (found != m_objs.end())
+    m_objs.erase(found);
 }
 
 void
index 8143553..9c87d31 100644 (file)
@@ -20,8 +20,6 @@
 
 #include "vom/types.hpp"
 
-#include <vapi/vapi.hpp>
-
 namespace VOM {
 /**
  * Forward declaration of the connection class
index 3d965ea..90c02f9 100644 (file)
  * limitations under the License.
  */
 
+#include <vapi/vapi.hpp>
+
 #include "vom/connection.hpp"
 
 namespace VOM {
 connection::connection()
-  : m_app_name("vpp-OM")
+  : m_vapi_conn(new vapi::Connection())
+  , m_app_name("VOM")
 {
 }
 
@@ -29,7 +32,7 @@ connection::~connection()
 void
 connection::disconnect()
 {
-  m_vapi_conn.disconnect();
+  m_vapi_conn->disconnect();
 }
 
 void
@@ -38,16 +41,16 @@ connection::connect()
   vapi_error_e rv;
 
   do {
-    rv = m_vapi_conn.connect(m_app_name.c_str(),
-                             NULL, // m_api_prefix.c_str(),
-                             128, 128);
+    rv = m_vapi_conn->connect(m_app_name.c_str(),
+                              NULL, // m_api_prefix.c_str(),
+                              128, 128);
   } while (VAPI_OK != rv);
 }
 
 vapi::Connection&
 connection::ctx()
 {
-  return (m_vapi_conn);
+  return (*m_vapi_conn);
 }
 }
 
index 0dc0184..c8acf78 100644 (file)
 #ifndef __VOM_CONNECTION_H__
 #define __VOM_CONNECTION_H__
 
+#include <memory>
 #include <string>
 
-#include <vapi/vapi.hpp>
+/**
+ * Forward declarations
+ */
+namespace vapi {
+class Connection;
+};
 
 namespace VOM {
 /**
@@ -56,7 +62,7 @@ private:
   /**
    * The VAPI connection context
    */
-  vapi::Connection m_vapi_conn;
+  std::unique_ptr<vapi::Connection> m_vapi_conn;
 
   /**
    * The name of this application
index a729926..0b6e2ef 100644 (file)
@@ -20,7 +20,7 @@ namespace VOM {
 /**
  * A DB of all DHCP configs
  */
-singular_db<interface::key_type, dhcp_config> dhcp_config::m_db;
+singular_db<interface::key_t, dhcp_config> dhcp_config::m_db;
 
 dhcp_config::event_handler dhcp_config::m_evh;
 
@@ -58,6 +58,19 @@ dhcp_config::~dhcp_config()
   m_db.release(m_itf->key(), this);
 }
 
+bool
+dhcp_config::operator==(const dhcp_config& l) const
+{
+  return ((key() == l.key()) && (m_hostname == l.m_hostname) &&
+          (m_client_id == l.m_client_id));
+}
+
+const dhcp_config::key_t&
+dhcp_config::key() const
+{
+  return (m_itf->key());
+}
+
 void
 dhcp_config::sweep()
 {
@@ -111,6 +124,12 @@ dhcp_config::find_or_add(const dhcp_config& temp)
   return (m_db.find_or_add(temp.m_itf->key(), temp));
 }
 
+std::shared_ptr<dhcp_config>
+dhcp_config::find(const key_t& k)
+{
+  return (m_db.find(k));
+}
+
 std::shared_ptr<dhcp_config>
 dhcp_config::singular() const
 {
index f64a3c8..db97af9 100644 (file)
@@ -33,6 +33,11 @@ class events_cmd;
 class dhcp_config : public object_base
 {
 public:
+  /**
+   * typedef for the DHCP config key type
+   */
+  typedef interface::key_t key_t;
+
   /**
    * Construct a new object matching the desried state
    */
@@ -55,6 +60,16 @@ public:
    */
   ~dhcp_config();
 
+  /**
+   * Comparison operator - for UT
+   */
+  bool operator==(const dhcp_config& d) const;
+
+  /**
+   * Return the object's key
+   */
+  const key_t& key() const;
+
   /**
    * Return the 'singular' of the DHCP config that matches this object
    */
@@ -71,8 +86,13 @@ public:
   static void dump(std::ostream& os);
 
   /**
-   * A class that listens to DHCP Events
+   * Find a DHCP config from its key
    */
+  static std::shared_ptr<dhcp_config> find(const key_t& k);
+
+  /**
+ * A class that listens to DHCP Events
+ */
   class event_listener
   {
   public:
@@ -153,7 +173,7 @@ private:
   /**
    * It's the singular_db class that calls replay()
    */
-  friend class singular_db<interface::key_type, dhcp_config>;
+  friend class singular_db<key_t, dhcp_config>;
 
   /**
    * Sweep/reap the object if still stale
@@ -191,7 +211,7 @@ private:
   /**
    * A map of all Dhcp configs keyed against the interface.
    */
-  static singular_db<interface::key_type, dhcp_config> m_db;
+  static singular_db<key_t, dhcp_config> m_db;
 };
 };
 
index 77ae5c3..7e30b67 100644 (file)
 
 #include <deque>
 #include <map>
+#include <queue>
 #include <sstream>
 #include <string>
 #include <thread>
 
+#include "vom/cmd.hpp"
 #include "vom/connection.hpp"
 #include "vom/types.hpp"
 
@@ -230,7 +232,7 @@ public:
     /**
      * Blocking Connect to VPP - call once at bootup
      */
-    void connect();
+    virtual void connect();
 
     /**
      * Disable the passing of commands to VPP. Whilst disabled all
index 55b533b..605a921 100644 (file)
@@ -60,8 +60,8 @@ inspect::handle_input(const std::string& message, std::ostream& output)
       OM::dump(results[1], output);
     } else if (message.find("all") != std::string::npos) {
       /*
- * get the unique set of handlers, then invoke each
- */
      * get the unique set of handlers, then invoke each
      */
       std::set<command_handler*> hdlrs;
       for (auto h : *m_cmd_handlers) {
         hdlrs.insert(h.second);
index 39ca074..aab2eab 100644 (file)
@@ -24,7 +24,7 @@ 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
@@ -91,6 +91,15 @@ interface::interface(const interface& o)
 {
 }
 
+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)
 {
@@ -217,8 +226,8 @@ 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();
@@ -236,7 +245,7 @@ interface::name() const
   return (m_name);
 }
 
-const interface::key_type&
+const interface::key_t&
 interface::key() const
 {
   return (name());
@@ -377,7 +386,7 @@ interface::enable_stats(interface::stat_listener& el)
 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>
@@ -387,9 +396,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>
@@ -399,9 +408,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;
@@ -424,9 +433,9 @@ 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
  */
+  interface_cmds::dump_cmd* cmd = new interface_cmds::dump_cmd();
 
   HW::enqueue(cmd);
   HW::write();
@@ -438,15 +447,15 @@ interface::event_handler::handle_populate(const client_db::key_t& key)
     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()));
@@ -491,7 +500,9 @@ interface::event_handler::show(std::ostream& os)
 {
   m_db.dump(os);
 }
-}
+
+} // namespace VOM
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
index 76ecf8a..8cba2fa 100644 (file)
@@ -44,7 +44,7 @@ public:
   /**
    * The key for interface's key
    */
-  typedef std::string key_type;
+  typedef std::string key_t;
 
   /**
    * The iterator type
@@ -207,7 +207,7 @@ public:
   /**
    * Return the interface type
    */
-  const key_type& key() const;
+  const key_t& key() const;
 
   /**
    * Return the L2 Address
@@ -224,6 +224,11 @@ public:
    */
   void set(const oper_state_t& state);
 
+  /**
+   * Comparison operator - only used for UT
+   */
+  virtual bool operator==(const interface& i) const;
+
   /**
    * A base class for interface Create commands
    */
@@ -400,21 +405,14 @@ public:
   };
 
   /**
-   * The the singular instance of the interface in the object_base-Model
-   */
-  static std::shared_ptr<interface> find(const interface& temp);
-
-  /**
-   * The the singular instance of the interface in the object_base-Model
-   * by handle
+   * The the singular instance of the interface in the DB by handle
    */
   static std::shared_ptr<interface> find(const handle_t& h);
 
   /**
-   * The the singular instance of the interface in the object_base-Model
-   * by name
+   * The the singular instance of the interface in the DB by key
    */
-  static std::shared_ptr<interface> find(const std::string& s);
+  static std::shared_ptr<interface> find(const key_t& k);
 
   /**
    * Dump all interfaces into the stream provided
@@ -472,12 +470,12 @@ protected:
   /**
    * A map of all interfaces key against the interface's name
    */
-  static singular_db<const std::string, interface> m_db;
+  static singular_db<key_t, interface> m_db;
 
   /**
    * Add an interface to the DB keyed on handle
    */
-  static void add(const std::string& name, const HW::item<handle_t>& item);
+  static void add(const key_t& name, const HW::item<handle_t>& item);
 
   /**
    * remove an interface from the DB keyed on handle
@@ -540,7 +538,7 @@ private:
   /**
    * It's the singular_db class that calls replay()
    */
-  friend class singular_db<const std::string, interface>;
+  friend class singular_db<key_t, interface>;
 
   /**
    * The interfaces name
index 4c7f391..22f545a 100644 (file)
@@ -26,7 +26,6 @@
 #include "vom/ra_prefix.hpp"
 #include "vom/rpc_cmd.hpp"
 #include "vom/singular_db.hpp"
-#include "vom/sub_interface.hpp"
 
 namespace VOM {
 /**
@@ -96,7 +95,7 @@ public:
   /**
    * The key type for interface ip6 nd
    */
-  typedef interface::key_type key_t;
+  typedef interface::key_t key_t;
 
   /**
    * Find an singular instance in the DB for the interface passed
index 04c3192..5bdbda9 100644 (file)
@@ -20,7 +20,7 @@ namespace VOM {
 /**
  * A DB of all interface_span config
  */
-singular_db<interface_span::key_type_t, interface_span> interface_span::m_db;
+singular_db<interface_span::key_t, interface_span> interface_span::m_db;
 
 interface_span::event_handler interface_span::m_evh;
 
@@ -96,7 +96,7 @@ interface_span::update(const interface_span& desired)
 }
 
 std::ostream&
-operator<<(std::ostream& os, const interface_span::key_type_t& key)
+operator<<(std::ostream& os, const interface_span::key_t& key)
 {
   os << "[" << key.first << ", " << key.second << "]";
 
index 8d3d7cb..baa2054 100644 (file)
@@ -103,7 +103,7 @@ public:
   /**
    * The key type for interface_spans
    */
-  typedef std::pair<interface::key_type, interface::key_type> key_type_t;
+  typedef std::pair<interface::key_t, interface::key_t> key_t;
 
   /**
    * Find a singular instance in the DB for the interface passed
@@ -165,7 +165,7 @@ private:
   /**
      e* It's the singular_db class that calls replay()
   */
-  friend class singular_db<key_type_t, interface_span>;
+  friend class singular_db<key_t, interface_span>;
 
   /**
    * Sweep/reap the object if still stale
@@ -202,14 +202,13 @@ private:
    * A map of all interface span keyed against the interface to be
    * mirrored.
  */
-  static singular_db<key_type_t, interface_span> m_db;
+  static singular_db<key_t, interface_span> m_db;
 };
 
 /**
  * Ostream output for the key
  */
-std::ostream& operator<<(std::ostream& os,
-                         const interface_span::key_type_t& key);
+std::ostream& operator<<(std::ostream& os, const interface_span::key_t& key);
 };
 
 /*
index 6afec80..a089f58 100644 (file)
@@ -21,7 +21,7 @@ namespace VOM {
  */
 const interface::type_t interface::type_t::UNKNOWN(0, "unknown");
 const interface::type_t interface::type_t::BVI(1, "BVI");
-const interface::type_t interface::type_t::ETHERNET(2, "Ehternet");
+const interface::type_t interface::type_t::ETHERNET(2, "Ethernet");
 const interface::type_t interface::type_t::VXLAN(3, "VXLAN");
 const interface::type_t interface::type_t::AFPACKET(4, "AFPACKET");
 const interface::type_t interface::type_t::LOOPBACK(5, "LOOPBACK");
index 676c778..b736919 100644 (file)
@@ -68,7 +68,7 @@ public:
   /**
    * The key type for ip_unnumbereds
    */
-  typedef interface::key_type key_t;
+  typedef interface::key_t key_t;
 
   /**
    * Find an singular instance in the DB for the interface passed
index e380760..dd49e57 100644 (file)
@@ -20,7 +20,7 @@ namespace VOM {
 /**
  * A DB of all the L2 Configs
  */
-singular_db<const handle_t, l2_binding> l2_binding::m_db;
+singular_db<l2_binding::key_t, l2_binding> l2_binding::m_db;
 
 l2_binding::event_handler l2_binding::m_evh;
 
@@ -75,6 +75,24 @@ l2_binding::l2_binding(const l2_binding& o)
 {
 }
 
+const l2_binding::key_t&
+l2_binding::key() const
+{
+  return (m_itf->key());
+}
+
+bool
+l2_binding::operator==(const l2_binding& l) const
+{
+  return ((*m_itf == *l.m_itf) && (*m_bd == *l.m_bd));
+}
+
+std::shared_ptr<l2_binding>
+l2_binding::find(const key_t& key)
+{
+  return (m_db.find(key));
+}
+
 void
 l2_binding::sweep()
 {
@@ -108,14 +126,14 @@ l2_binding::~l2_binding()
   sweep();
 
   // not in the DB anymore.
-  m_db.release(m_itf->handle(), this);
+  m_db.release(m_itf->key(), this);
 }
 
 std::string
 l2_binding::to_string() const
 {
   std::ostringstream s;
-  s << "L2-config:[" << m_itf->to_string() << " " << m_bd->to_string() << " "
+  s << "L2-binding:[" << m_itf->to_string() << " " << m_bd->to_string() << " "
     << m_binding.to_string() << "]";
 
   return (s.str());
@@ -154,7 +172,7 @@ l2_binding::update(const l2_binding& desired)
 std::shared_ptr<l2_binding>
 l2_binding::find_or_add(const l2_binding& temp)
 {
-  return (m_db.find_or_add(temp.m_itf->handle(), temp));
+  return (m_db.find_or_add(temp.m_itf->key(), temp));
 }
 
 std::shared_ptr<l2_binding>
index 0e6f7fc..ba97cab 100644 (file)
@@ -32,6 +32,11 @@ namespace VOM {
 class l2_binding : public object_base
 {
 public:
+  /**
+   * Key type for an L2 binding in the singular DB
+   */
+  typedef interface::key_t key_t;
+
   struct l2_vtr_op_t : public enum_base<l2_vtr_op_t>
   {
     l2_vtr_op_t(const l2_vtr_op_t& l) = default;
@@ -66,6 +71,16 @@ public:
    */
   ~l2_binding();
 
+  /**
+   * Return the binding's key
+   */
+  const key_t& key() const;
+
+  /**
+   * Comparison operator - for UT
+   */
+  bool operator==(const l2_binding& l) const;
+
   /**
    * Return the 'singular instance' of the L2 config that matches this
    * object
@@ -87,6 +102,11 @@ public:
    */
   void set(const l2_vtr_op_t& op, uint16_t tag);
 
+  /**
+   * Static function to find the bridge_domain in the model
+   */
+  static std::shared_ptr<l2_binding> find(const key_t& key);
+
 private:
   /**
    * Class definition for listeners to OM events
@@ -141,7 +161,7 @@ private:
   /**
    * It's the singular_db class that calls replay()
    */
-  friend class singular_db<const handle_t, l2_binding>;
+  friend class singular_db<key_t, l2_binding>;
 
   /**
    * Sweep/reap the object if still stale
@@ -186,7 +206,7 @@ private:
   /**
    * A map of all L2 interfaces key against the interface's handle_t
    */
-  static singular_db<const handle_t, l2_binding> m_db;
+  static singular_db<key_t, l2_binding> m_db;
 };
 };
 
index 065504c..be7c9d1 100644 (file)
@@ -17,7 +17,7 @@
 #include "vom/l3_binding_cmds.hpp"
 
 namespace VOM {
-singular_db<l3_binding::key_type_t, l3_binding> l3_binding::m_db;
+singular_db<l3_binding::key_t, l3_binding> l3_binding::m_db;
 
 l3_binding::event_handler l3_binding::m_evh;
 
@@ -43,7 +43,19 @@ l3_binding::~l3_binding()
   sweep();
 
   // not in the DB anymore.
-  m_db.release(make_pair(m_itf->key(), m_pfx), this);
+  m_db.release(key(), this);
+}
+
+bool
+l3_binding::operator==(const l3_binding& l) const
+{
+  return ((m_pfx == l.m_pfx) && (*m_itf == *l.m_itf));
+}
+
+const l3_binding::key_t
+l3_binding::key() const
+{
+  return (make_pair(m_itf->key(), m_pfx));
 }
 
 void
@@ -93,7 +105,7 @@ std::string
 l3_binding::to_string() const
 {
   std::ostringstream s;
-  s << "L3-config:[" << m_itf->to_string() << " prefix:" << m_pfx.to_string()
+  s << "L3-binding:[" << m_itf->to_string() << " prefix:" << m_pfx.to_string()
     << " " << m_binding.to_string() << "]";
 
   return (s.str());
@@ -116,7 +128,13 @@ l3_binding::update(const l3_binding& desired)
 std::shared_ptr<l3_binding>
 l3_binding::find_or_add(const l3_binding& temp)
 {
-  return (m_db.find_or_add(make_pair(temp.m_itf->key(), temp.m_pfx), temp));
+  return (m_db.find_or_add(temp.key(), temp));
+}
+
+std::shared_ptr<l3_binding>
+l3_binding::find(const key_t& k)
+{
+  return (m_db.find(k));
 }
 
 std::shared_ptr<l3_binding>
@@ -132,7 +150,7 @@ l3_binding::dump(std::ostream& os)
 }
 
 std::ostream&
-operator<<(std::ostream& os, const l3_binding::key_type_t& key)
+operator<<(std::ostream& os, const l3_binding::key_t& key)
 {
   os << "[" << key.first << ", " << key.second << "]";
 
index a147058..0177e56 100644 (file)
@@ -30,6 +30,11 @@ namespace VOM {
 class l3_binding : public object_base
 {
 public:
+  /**
+   * The key type for l3_bindings
+   */
+  typedef std::pair<interface::key_t, route::prefix_t> key_t;
+
   /**
    * Construct a new object matching the desried state
    */
@@ -46,14 +51,19 @@ public:
   ~l3_binding();
 
   /**
-   * The key type for l3_bindings
+   * Comparison operator
    */
-  typedef std::pair<interface::key_type, route::prefix_t> key_type_t;
+  bool operator==(const l3_binding& l) const;
+
+  /**
+   * Get the object's key
+   */
+  const key_t key() const;
 
   /**
    * The iterator type
    */
-  typedef singular_db<key_type_t, l3_binding>::const_iterator const_iterator_t;
+  typedef singular_db<key_t, l3_binding>::const_iterator const_iterator_t;
 
   static const_iterator_t cbegin();
   static const_iterator_t cend();
@@ -85,10 +95,15 @@ public:
   static void dump(std::ostream& os);
 
   /**
-   * Find an singular instance in the DB for the interface passed
+   * Find all bindings in the DB for the interface passed
    */
   static std::deque<std::shared_ptr<l3_binding>> find(const interface& i);
 
+  /**
+   * Find a binding from its key
+   */
+  static std::shared_ptr<l3_binding> find(const key_t& k);
+
 private:
   /**
    * Class definition for listeners to OM events
@@ -143,7 +158,7 @@ private:
   /**
      e* It's the singular_db class that calls replay()
   */
-  friend class singular_db<key_type_t, l3_binding>;
+  friend class singular_db<key_t, l3_binding>;
 
   /**
    * Sweep/reap the object if still stale
@@ -179,13 +194,13 @@ private:
    * A map of all L3 configs keyed against a combination of the interface
    * and subnet's keys.
    */
-  static singular_db<key_type_t, l3_binding> m_db;
+  static singular_db<key_t, l3_binding> m_db;
 };
 
 /**
  * Ostream output for the key
  */
-std::ostream& operator<<(std::ostream& os, const l3_binding::key_type_t& key);
+std::ostream& operator<<(std::ostream& os, const l3_binding::key_t& key);
 };
 
 /*
index 05d51bb..a1d3d9f 100644 (file)
@@ -20,7 +20,7 @@ namespace VOM {
 /**
  * A DB of all LLDP configs
  */
-singular_db<interface::key_type, lldp_binding> lldp_binding::m_db;
+singular_db<interface::key_t, lldp_binding> lldp_binding::m_db;
 
 lldp_binding::event_handler lldp_binding::m_evh;
 
@@ -46,6 +46,18 @@ lldp_binding::~lldp_binding()
   m_db.release(m_itf->key(), this);
 }
 
+bool
+lldp_binding::operator==(const lldp_binding& l) const
+{
+  return ((key() == l.key()) && (m_port_desc == l.m_port_desc));
+}
+
+const lldp_binding::key_t&
+lldp_binding::key() const
+{
+  return (m_itf->key());
+}
+
 void
 lldp_binding::sweep()
 {
@@ -98,6 +110,12 @@ lldp_binding::find_or_add(const lldp_binding& temp)
   return (m_db.find_or_add(temp.m_itf->key(), temp));
 }
 
+std::shared_ptr<lldp_binding>
+lldp_binding::find(const key_t& k)
+{
+  return (m_db.find(k));
+}
+
 std::shared_ptr<lldp_binding>
 lldp_binding::singular() const
 {
index 896708f..0c56100 100644 (file)
@@ -30,6 +30,11 @@ namespace VOM {
 class lldp_binding : public object_base
 {
 public:
+  /**
+   * Typedef for the key of a LLDP binding
+   */
+  typedef interface::key_t key_t;
+
   /**
    * Construct a new object matching the desried state
    */
@@ -39,11 +44,22 @@ public:
    * Copy Constructor
    */
   lldp_binding(const lldp_binding& o);
+
   /**
    * Destructor
    */
   ~lldp_binding();
 
+  /**
+   * Comparison operator
+   */
+  bool operator==(const lldp_binding& b) const;
+
+  /**
+   * Return this object's key
+   */
+  const key_t& key() const;
+
   /**
    * Return the 'singular' of the LLDP binding that matches this object
    */
@@ -59,6 +75,11 @@ public:
    */
   static void dump(std::ostream& os);
 
+  /**
+   * Find or add LLDP binding based on its key
+   */
+  static std::shared_ptr<lldp_binding> find(const key_t& k);
+
 private:
   /**
    * Class definition for listeners to OM events
@@ -113,7 +134,7 @@ private:
   /**
    * It's the singular_db class that calls replay()
    */
-  friend class singular_db<interface::key_type, lldp_binding>;
+  friend class singular_db<key_t, lldp_binding>;
 
   /**
    * Sweep/reap the object if still stale
@@ -146,7 +167,7 @@ private:
   /**
    * A map of all Lldp bindings keyed against the interface.
    */
-  static singular_db<interface::key_type, lldp_binding> m_db;
+  static singular_db<key_t, lldp_binding> m_db;
 };
 };
 
index e7d425e..7e701dc 100644 (file)
@@ -48,6 +48,19 @@ lldp_global::~lldp_global()
   m_db.release(m_system_name, this);
 }
 
+const lldp_global::key_t&
+lldp_global::key() const
+{
+  return (m_system_name);
+}
+
+bool
+lldp_global::operator==(const lldp_global& l) const
+{
+  return ((key() == l.key()) && (m_tx_hold == l.m_tx_hold) &&
+          (m_tx_interval == l.m_tx_interval));
+}
+
 void
 lldp_global::sweep()
 {
@@ -92,7 +105,13 @@ lldp_global::update(const lldp_global& desired)
 std::shared_ptr<lldp_global>
 lldp_global::find_or_add(const lldp_global& temp)
 {
-  return (m_db.find_or_add(temp.m_system_name, temp));
+  return (m_db.find_or_add(temp.key(), temp));
+}
+
+std::shared_ptr<lldp_global>
+lldp_global::find(const key_t& k)
+{
+  return (m_db.find(k));
 }
 
 std::shared_ptr<lldp_global>
index 743f9f7..f545a28 100644 (file)
 
 #include "vom/hw.hpp"
 #include "vom/inspect.hpp"
-#include "vom/interface.hpp"
 #include "vom/object_base.hpp"
 #include "vom/om.hpp"
 #include "vom/singular_db.hpp"
-#include "vom/sub_interface.hpp"
-
-#include <vapi/lldp.api.vapi.hpp>
 
 namespace VOM {
 /**
@@ -33,6 +29,11 @@ namespace VOM {
 class lldp_global : public object_base
 {
 public:
+  /**
+   * The key for the global conifugration is the 'system' namse
+   */
+  typedef std::string key_t;
+
   /**
    * Construct a new object matching the desried state
    */
@@ -50,6 +51,16 @@ public:
    */
   ~lldp_global();
 
+  /**
+   * Get this objects key
+   */
+  const key_t& key() const;
+
+  /**
+   * Comparison operator
+   */
+  bool operator==(const lldp_global& l) const;
+
   /**
    * Return the 'singular' of the LLDP global that matches this object
    */
@@ -66,45 +77,9 @@ public:
   static void dump(std::ostream& os);
 
   /**
-   * A command class that binds the LLDP global to the interface
+   * Find LLDP global config from its key
    */
-  class config_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Lldp_config>
-  {
-  public:
-    /**
-     * Constructor
-     */
-    config_cmd(HW::item<bool>& item,
-               const std::string& system_name,
-               uint32_t tx_hold,
-               uint32_t tx_interval);
-
-    /**
-     * Issue the command to VPP/HW
-     */
-    rc_t issue(connection& con);
-    /**
-     * convert to string format for debug purposes
-     */
-    std::string to_string() const;
-
-    /**
-     * Comparison operator - only used for UT
-     */
-    bool operator==(const config_cmd& i) const;
-
-  private:
-    /**
-     * The system name
-     */
-    const std::string m_system_name;
-
-    /**
-     * TX timer configs
-     */
-    uint32_t m_tx_hold;
-    uint32_t m_tx_interval;
-  };
+  static std::shared_ptr<lldp_global> find(const key_t& k);
 
 private:
   /**
@@ -160,7 +135,7 @@ private:
   /**
    * It's the singular_db class that calls replay()
    */
-  friend class singular_db<interface::key_type, lldp_global>;
+  friend class singular_db<key_t, lldp_global>;
 
   /**
    * Sweep/reap the object if still stale
@@ -193,7 +168,7 @@ private:
    * A map of all Lldp globals keyed against the system name.
    *  there needs to be some sort of key, that will do.
    */
-  static singular_db<std::string, lldp_global> m_db;
+  static singular_db<key_t, lldp_global> m_db;
 };
 };
 
index e4f8f37..621e73f 100644 (file)
@@ -26,8 +26,8 @@ namespace VOM {
 namespace lldp_global_cmds {
 
 /**
-* A command class that binds the LLDP global to the interface
-*/
+ * A command class that binds the LLDP global to the interface
+ */
 class config_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Lldp_config>
 {
 public:
index 2f6d67f..7761250 100644 (file)
@@ -61,7 +61,7 @@ public:
    *  The zoe is not included, since the same interface is never inside
    * and outside.
    */
-  typedef std::tuple<interface::key_type, direction_t, l3_proto_t> key_t;
+  typedef std::tuple<interface::key_t, direction_t, l3_proto_t> key_t;
 
   /**
    * Construct a new object matching the desried state
index 12b13ca..35e9c46 100644 (file)
@@ -21,20 +21,20 @@ singular_db<neighbour::key_t, neighbour> neighbour::m_db;
 neighbour::event_handler neighbour::m_evh;
 
 neighbour::neighbour(const interface& itf,
-                     const mac_address_t& mac,
-                     const boost::asio::ip::address& ip_addr)
+                     const boost::asio::ip::address& ip_addr,
+                     const mac_address_t& mac)
   : m_hw(false)
   , m_itf(itf.singular())
-  , m_mac(mac)
   , m_ip_addr(ip_addr)
+  , m_mac(mac)
 {
 }
 
 neighbour::neighbour(const neighbour& bde)
   : m_hw(bde.m_hw)
   , m_itf(bde.m_itf)
-  , m_mac(bde.m_mac)
   , m_ip_addr(bde.m_ip_addr)
+  , m_mac(bde.m_mac)
 {
 }
 
@@ -43,7 +43,19 @@ neighbour::~neighbour()
   sweep();
 
   // not in the DB anymore.
-  m_db.release(std::make_tuple(m_itf->key(), m_mac, m_ip_addr), this);
+  m_db.release(key(), this);
+}
+
+bool
+neighbour::operator==(const neighbour& n) const
+{
+  return ((key() == n.key()) && (m_mac == n.m_mac));
+}
+
+const neighbour::key_t
+neighbour::key() const
+{
+  return (std::make_pair(m_itf->key(), m_ip_addr));
 }
 
 void
@@ -90,8 +102,13 @@ neighbour::update(const neighbour& r)
 std::shared_ptr<neighbour>
 neighbour::find_or_add(const neighbour& temp)
 {
-  return (m_db.find_or_add(
-    std::make_tuple(temp.m_itf->key(), temp.m_mac, temp.m_ip_addr), temp));
+  return (m_db.find_or_add(temp.key(), temp));
+}
+
+std::shared_ptr<neighbour>
+neighbour::find(const key_t& k)
+{
+  return (m_db.find(k));
 }
 
 std::shared_ptr<neighbour>
@@ -109,8 +126,7 @@ neighbour::dump(std::ostream& os)
 std::ostream&
 operator<<(std::ostream& os, const neighbour::key_t& key)
 {
-  os << "[" << std::get<0>(key) << ", " << std::get<1>(key) << ", "
-     << std::get<2>(key) << "]";
+  os << "[" << key.first << ", " << key.second << "]";
 
   return (os);
 }
@@ -133,8 +149,8 @@ neighbour::populate_i(const client_db::key_t& key,
                       const l3_proto_t& proto)
 {
   /*
- * dump VPP current states
- */
  * dump VPP current states
  */
   std::shared_ptr<neighbour_cmds::dump_cmd> cmd =
     std::make_shared<neighbour_cmds::dump_cmd>(
       neighbour_cmds::dump_cmd(itf->handle(), proto));
@@ -144,23 +160,23 @@ neighbour::populate_i(const client_db::key_t& key,
 
   for (auto& record : *cmd) {
     /*
- * construct a neighbour from each recieved record.
- */
    * construct a neighbour from each recieved record.
    */
     auto& payload = record.get_payload();
 
     mac_address_t mac(payload.mac_address);
     boost::asio::ip::address ip_addr =
       from_bytes(payload.is_ipv6, payload.ip_address);
-    neighbour n(*itf, mac, ip_addr);
+    neighbour n(*itf, ip_addr, mac);
 
     VOM_LOG(log_level_t::DEBUG) << "neighbour-dump: " << itf->to_string()
                                 << mac.to_string() << ip_addr.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, n);
   }
 }
index 85577f0..500f03d 100644 (file)
 
 namespace VOM {
 /**
- * A entry in the ARP termination table of a Bridge Domain
+ * A entry in the neighbour entry (ARP or IPv6 ND)
  */
 class neighbour : public object_base
 {
 public:
   /**
-   * The key for a bridge_domain ARP entry;
-   *  the BD, IP address and MAC address
+   * The key for a neighbour entry;
+   *  the interface and IP address
    */
-  typedef std::tuple<interface::key_type,
-                     mac_address_t,
-                     boost::asio::ip::address>
-    key_t;
+  typedef std::pair<interface::key_t, boost::asio::ip::address> key_t;
 
   /**
    * Construct an ARP entry
    */
   neighbour(const interface& itf,
-            const mac_address_t& mac,
-            const boost::asio::ip::address& ip_addr);
+            const boost::asio::ip::address& ip_addr,
+            const mac_address_t& mac);
 
   /**
    * Copy Construct
@@ -53,18 +50,28 @@ public:
    */
   ~neighbour();
 
+  /**
+   * Return the object's key
+   */
+  const key_t key() const;
+
+  /**
+   * Comparison operator
+   */
+  bool operator==(const neighbour& n) const;
+
   /**
    * Return the matching 'singular instance'
    */
   std::shared_ptr<neighbour> singular() const;
 
   /**
-   * Find the instnace of the bridge_domain domain in the OM
+   * Find the neighbour fromits key
    */
-  static std::shared_ptr<neighbour> find(const neighbour& temp);
+  static std::shared_ptr<neighbour> find(const key_t& k);
 
   /**
-   * Dump all bridge_domain-doamin into the stream provided
+   * Dump all neighbours into the stream provided
    */
   static void dump(std::ostream& os);
 
@@ -127,7 +134,7 @@ private:
                          const l3_proto_t& proto);
 
   /**
-   * Find or add the instnace of the bridge_domain domain in the OM
+   * Find or add the instnace of the neighbour in the OM
    */
   static std::shared_ptr<neighbour> find_or_add(const neighbour& temp);
 
@@ -157,14 +164,14 @@ private:
   std::shared_ptr<interface> m_itf;
 
   /**
-   * The mac to match
+   * The IP address
    */
-  mac_address_t m_mac;
+  boost::asio::ip::address m_ip_addr;
 
   /**
-   * The IP address
+   * The mac to match
    */
-  boost::asio::ip::address m_ip_addr;
+  mac_address_t m_mac;
 
   /**
    * A map of all bridge_domains
index f82fee3..5f5c26e 100644 (file)
@@ -49,9 +49,9 @@ void
 OM::sweep(const client_db::key_t& key)
 {
   /*
- * Find if the object already stored on behalf of this key.
- * and mark them stale
- */
  * Find if the object already stored on behalf of this key.
  * and mark them stale
  */
   object_ref_list& objs = m_db->find(key);
 
   for (auto it = objs.begin(); it != objs.end();) {
@@ -69,11 +69,11 @@ void
 OM::remove(const client_db::key_t& key)
 {
   /*
- * Simply reset the list for this key. This will desctruct the
- * object list and shared_ptrs therein. When the last shared_ptr
- * goes the objects desctructor is called and the object is
- * removed from OM
- */
  * Simply reset the list for this key. This will desctruct the
  * object list and shared_ptrs therein. When the last shared_ptr
  * goes the objects desctructor is called and the object is
  * removed from OM
  */
   m_db->flush(key);
 
   HW::write();
@@ -83,8 +83,8 @@ void
 OM::replay()
 {
   /*
- * the listeners are sorted in dependency order
- */
  * the listeners are sorted in dependency order
  */
   for (listener* l : *m_listeners) {
     l->handle_replay();
   }
@@ -108,15 +108,15 @@ void
 OM::populate(const client_db::key_t& key)
 {
   /*
- * the listeners are sorted in dependency order
- */
  * the listeners are sorted in dependency order
  */
   for (listener* l : *m_listeners) {
     l->handle_populate(key);
   }
 
   /*
- * once we have it all, mark it stale.
- */
  * once we have it all, mark it stale.
  */
   mark(key);
 }
 
index f470c5e..e68d5ea 100644 (file)
@@ -16,6 +16,7 @@
 #ifndef __VOM_OM_H__
 #define __VOM_OM_H__
 
+#include <algorithm>
 #include <memory>
 #include <set>
 
index e59bfba..0da2ebb 100644 (file)
@@ -102,16 +102,47 @@ path::operator<(const path& p) const
 {
   if (m_type < p.m_type)
     return true;
+  if (m_rd && !p.m_rd)
+    return false;
+  if (!m_rd && p.m_rd)
+    return true;
   if (m_rd->table_id() < p.m_rd->table_id())
     return true;
   if (m_nh < p.m_nh)
     return true;
+  if (m_interface && !p.m_interface)
+    return false;
+  if (!m_interface && p.m_interface)
+    return true;
   if (m_interface->handle() < p.m_interface->handle())
     return true;
 
   return (false);
 }
 
+path::~path()
+{
+}
+
+bool
+path::operator==(const path& p) const
+{
+  bool result = true;
+  if (m_rd && !p.m_rd)
+    return false;
+  if (!m_rd && p.m_rd)
+    return false;
+  if (m_rd && p.m_rd)
+    result &= (*m_rd == *p.m_rd);
+  if (m_interface && !p.m_interface)
+    return false;
+  if (!m_interface && p.m_interface)
+    return false;
+  if (m_interface && p.m_interface)
+    result &= (*m_interface == *p.m_interface);
+  return (result && (m_type == p.m_type) && (m_nh == p.m_nh));
+}
+
 std::string
 path::to_string() const
 {
@@ -174,6 +205,14 @@ path::preference() const
   return m_preference;
 }
 
+ip_route::ip_route(const prefix_t& prefix, const path& p)
+  : m_hw(false)
+  , m_rd(route_domain::get_default())
+  , m_prefix(prefix)
+  , m_paths({ p })
+{
+}
+
 ip_route::ip_route(const prefix_t& prefix)
   : m_hw(false)
   , m_rd(route_domain::get_default())
@@ -198,12 +237,35 @@ ip_route::ip_route(const route_domain& rd, const prefix_t& prefix)
 {
 }
 
+ip_route::ip_route(const route_domain& rd,
+                   const prefix_t& prefix,
+                   const path& p)
+  : m_hw(false)
+  , m_rd(rd.singular())
+  , m_prefix(prefix)
+  , m_paths({ p })
+{
+}
+
 ip_route::~ip_route()
 {
   sweep();
 
   // not in the DB anymore.
-  m_db.release(std::make_pair(m_rd->table_id(), m_prefix), this);
+  m_db.release(key(), this);
+  m_paths.clear();
+}
+
+const ip_route::key_t
+ip_route::key() const
+{
+  return (std::make_pair(m_rd->table_id(), m_prefix));
+}
+
+bool
+ip_route::operator==(const ip_route& i) const
+{
+  return ((key() == i.key()) && (m_paths == i.m_paths));
 }
 
 void
@@ -262,8 +324,13 @@ ip_route::update(const ip_route& r)
 std::shared_ptr<ip_route>
 ip_route::find_or_add(const ip_route& temp)
 {
-  return (m_db.find_or_add(std::make_pair(temp.m_rd->table_id(), temp.m_prefix),
-                           temp));
+  return (m_db.find_or_add(temp.key(), temp));
+}
+
+std::shared_ptr<ip_route>
+ip_route::find(const key_t& k)
+{
+  return (m_db.find(k));
 }
 
 std::shared_ptr<ip_route>
@@ -308,8 +375,8 @@ ip_route::event_handler::handle_populate(const client_db::key_t& key)
     prefix_t pfx(0, payload.address, payload.address_length);
 
     /**
-* populating the route domain here
-*/
+     * populating the route domain here
+     */
     route_domain rd_temp(payload.table_id);
     std::shared_ptr<route_domain> rd = route_domain::find(rd_temp);
     if (!rd) {
@@ -341,10 +408,10 @@ ip_route::event_handler::handle_populate(const client_db::key_t& key)
     VOM_LOG(log_level_t::DEBUG) << "ip-route-dump: " << ip_r.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, ip_r);
   }
 
@@ -383,10 +450,10 @@ ip_route::event_handler::handle_populate(const client_db::key_t& key)
     VOM_LOG(log_level_t::DEBUG) << "ip-route-dump: " << ip_r.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, ip_r);
   }
 }
index 4f27ff1..2fb855a 100644 (file)
@@ -106,9 +106,14 @@ public:
   path(const path& p);
 
   /**
-   * Convert the path into the VPP API representation
+   * Destructor
    */
-  void to_vpp(vapi_payload_ip_add_del_route& payload) const;
+  ~path();
+
+  /**
+   * comparison operator
+   */
+  bool operator==(const path& p) const;
 
   /**
    * Less than operator for set insertion
@@ -195,6 +200,11 @@ public:
    */
   ip_route(const prefix_t& prefix);
 
+  /**
+   * Construct a route with a path
+   */
+  ip_route(const prefix_t& prefix, const path& p);
+
   /**
    * Copy Construct
    */
@@ -205,11 +215,26 @@ public:
    */
   ip_route(const route_domain& rd, const prefix_t& prefix);
 
+  /**
+   * Construct a route in the given route domain with a path
+   */
+  ip_route(const route_domain& rd, const prefix_t& prefix, const path& p);
+
   /**
    * Destructor
    */
   ~ip_route();
 
+  /**
+   * Get the route's key
+   */
+  const key_t key() const;
+
+  /**
+   * Comparison operator
+   */
+  bool operator==(const ip_route& i) const;
+
   /**
    * Return the matching 'singular instance'
    */
@@ -245,6 +270,11 @@ public:
    */
   std::string to_string() const;
 
+  /**
+   * Return the matching 'singular instance'
+   */
+  static std::shared_ptr<ip_route> find(const key_t& k);
+
 private:
   /**
    * Class definition for listeners to OM events
index 08357fa..c723f9f 100644 (file)
@@ -43,6 +43,12 @@ route_domain::route_domain(const route_domain& o)
 {
 }
 
+bool
+route_domain::operator==(const route_domain& r) const
+{
+  return (m_table_id == r.m_table_id);
+}
+
 route::table_id_t
 route_domain::table_id() const
 {
index 516271f..7d83154 100644 (file)
@@ -53,6 +53,11 @@ public:
    */
   ~route_domain();
 
+  /**
+   * comparison operator - for UT
+   */
+  bool operator==(const route_domain& r) const;
+
   /**
    * Return the matching 'singular instance'
    */
index bc49c88..07ea2cb 100644 (file)
@@ -143,7 +143,7 @@ private:
   /**
    * the map of objects against their key
    */
-  std::map<KEY, std::weak_ptr<OBJ>> m_map;
+  std::map<const KEY, std::weak_ptr<OBJ>> m_map;
 };
 };
 
index ea7fa41..01f4a54 100644 (file)
@@ -56,6 +56,13 @@ sub_interface::sub_interface(const sub_interface& o)
 {
 }
 
+bool
+sub_interface::operator==(const sub_interface& s) const
+{
+  return (interface::operator==(s) && (m_parent->key() == s.m_parent->key()) &&
+          (m_vlan == s.m_vlan));
+}
+
 std::string
 sub_interface::mk_name(const interface& parent, vlan_id_t vlan)
 {
@@ -88,10 +95,17 @@ sub_interface::singular() const
 std::shared_ptr<interface>
 sub_interface::singular_i() const
 {
-  return m_db.find_or_add(name(), *this);
+  return m_db.find_or_add(key(), *this);
 }
+
+std::shared_ptr<sub_interface>
+sub_interface::find(const key_t& k)
+{
+  return std::dynamic_pointer_cast<sub_interface>(m_db.find(k));
 }
 
+}; // namespace VOM
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
index 5878f45..1c65782 100644 (file)
@@ -43,11 +43,21 @@ public:
    */
   sub_interface(const sub_interface& o);
 
+  /**
+   * comparison operator - for UT
+   */
+  bool operator==(const sub_interface& s) const;
+
   /**
    * Return the matching 'singular instance' of the sub-interface
    */
   std::shared_ptr<sub_interface> singular() const;
 
+  /**
+   * Find a subinterface from its key
+   */
+  static std::shared_ptr<sub_interface> find(const key_t& k);
+
 private:
   /**
    * Construct with handle
index 4b6c787..8314b40 100644 (file)
@@ -99,8 +99,8 @@ void
 tap_interface::event_handler::handle_populate(const client_db::key_t& key)
 {
   /*
- * dump VPP current states
- */
  * dump VPP current states
  */
   std::shared_ptr<tap_interface_cmds::dump_cmd> cmd(
     new tap_interface_cmds::dump_cmd());
 
@@ -118,10 +118,10 @@ tap_interface::event_handler::handle_populate(const client_db::key_t& key)
     VOM_LOG(log_level_t::DEBUG) << "tap-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);
   }
 }
@@ -147,10 +147,11 @@ tap_interface::event_handler::order() const
 void
 tap_interface::event_handler::show(std::ostream& os)
 {
-  m_db.dump(os);
-}
+  // dumped by the interface handler
 }
 
+}; // namespace VOM
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
index 128d757..c5325d2 100644 (file)
@@ -18,6 +18,8 @@
 #include <iostream>
 #include <sstream>
 
+#include <boost/algorithm/string.hpp>
+
 #include "vom/types.hpp"
 
 namespace VOM {
@@ -111,6 +113,19 @@ mac_address_t::mac_address_t(std::initializer_list<uint8_t> i)
   std::copy(i.begin(), i.end(), std::begin(bytes));
 }
 
+mac_address_t::mac_address_t(const std::string& str)
+{
+  std::vector<std::string> parts;
+
+  boost::split(parts, str, boost::is_any_of(":"));
+
+  size_t n_bytes = std::min(bytes.size(), parts.size());
+
+  for (uint32_t ii = 0; ii < n_bytes; ii++) {
+    bytes[ii] = std::stoul(parts[ii], nullptr, 16);
+  }
+}
+
 const mac_address_t mac_address_t::ONE({ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff });
 
 const mac_address_t mac_address_t::ZERO({ 0x0 });
@@ -131,7 +146,6 @@ mac_address_t::to_string() const
 
   s.fill('0');
   s << std::hex;
-  s << "mac:[";
   for (auto byte : bytes) {
     if (first)
       first = false;
@@ -139,7 +153,6 @@ mac_address_t::to_string() const
       s << ":";
     s << std::setw(2) << static_cast<unsigned int>(byte);
   }
-  s << "]";
 
   return (s.str());
 }
index ca488fe..b57867f 100644 (file)
@@ -222,6 +222,7 @@ std::ostream& operator<<(std::ostream& os, const handle_t& h);
 struct mac_address_t
 {
   mac_address_t(uint8_t bytes[6]);
+  mac_address_t(const std::string& str);
   mac_address_t(std::initializer_list<uint8_t> bytes);
   /**
    * Convert to byte array
index abb278b..cf87223 100644 (file)
@@ -217,8 +217,8 @@ void
 vxlan_tunnel::event_handler::handle_populate(const client_db::key_t& key)
 {
   /*
- * dump VPP current states
- */
  * dump VPP current states
  */
   std::shared_ptr<vxlan_tunnel_cmds::dump_cmd> cmd(
     new vxlan_tunnel_cmds::dump_cmd());
 
@@ -262,9 +262,11 @@ vxlan_tunnel::event_handler::order() const
 void
 vxlan_tunnel::event_handler::show(std::ostream& os)
 {
-  m_db.dump(os);
-}
+  // dumped by the interface handler
 }
+
+}; // namespace VOM
+
 /*
  * fd.io coding-style-patch-verification: ON
  *
index 612a2d3..c9ae255 100644 (file)
@@ -808,7 +808,7 @@ BOOST_AUTO_TEST_CASE(test_bridge) {
     HW::item<bool> hw_bea1(true, rc_t::OK);
     boost::asio::ip::address ip1 = boost::asio::ip::address::from_string("10.10.10.10");
 
-    bridge_domain_arp_entry *bea1 = new bridge_domain_arp_entry(bd1, mac1, ip1);
+    bridge_domain_arp_entry *bea1 = new bridge_domain_arp_entry(bd1, ip1, mac1);
     ADD_EXPECT(bridge_domain_arp_entry_cmds::create_cmd(hw_be1, bd1.id(), mac1, ip1));
     TRY_CHECK_RC(OM::write(dante, *bea1));
 
@@ -1315,7 +1315,7 @@ BOOST_AUTO_TEST_CASE(test_routing) {
      */
     HW::item<bool> hw_neighbour(true, rc_t::OK);
     mac_address_t mac_n({0,1,2,4,5,6});
-    neighbour *ne = new neighbour(itf1, mac_n, nh_10);
+    neighbour *ne = new neighbour(itf1, nh_10, mac_n);
     ADD_EXPECT(neighbour_cmds::create_cmd(hw_neighbour, hw_ifh.data(), mac_n, nh_10));
     TRY_CHECK_RC(OM::write(ian, *ne));