VOM: De-template the ACL code. 85/17785/2
authorNeale Ranns <nranns@cisco.com>
Fri, 22 Feb 2019 08:44:40 +0000 (00:44 -0800)
committerNeale Ranns <nranns@cisco.com>
Fri, 22 Feb 2019 15:41:51 +0000 (15:41 +0000)
there's something going wrong with the dependency ordering.
i have added hacks in the past, but these are not reliable
across compiler versions.

Change-Id: I34b4aae4c7ed7beaa424cd692ff34cba21ba802a
Signed-off-by: Neale Ranns <nranns@cisco.com>
extras/vom/vom/CMakeLists.txt
extras/vom/vom/acl_binding.hpp
extras/vom/vom/acl_l2_list.cpp [new file with mode: 0644]
extras/vom/vom/acl_l2_list.hpp [moved from extras/vom/vom/acl_list.hpp with 53% similarity]
extras/vom/vom/acl_l3_list.cpp [moved from extras/vom/vom/acl_list.cpp with 60% similarity]
extras/vom/vom/acl_l3_list.hpp [new file with mode: 0644]
extras/vom/vom/acl_list_cmds.hpp
extras/vom/vom/gbp_contract.hpp
test/ext/vom_test.cpp

index a0a5f97..26dd3e4 100644 (file)
@@ -50,10 +50,11 @@ if(ACL_FILE)
     acl_binding.cpp
     acl_ethertype_cmds.cpp
     acl_ethertype.cpp
+    acl_l2_list.cpp
     acl_l2_rule.cpp
+    acl_l3_list.cpp
     acl_l3_rule.cpp
     acl_list_cmds.cpp
-    acl_list.cpp
     acl_types.cpp
   )
 endif()
@@ -189,7 +190,8 @@ if(ACL_FILE)
     acl_ethertype.hpp
     acl_l2_rule.hpp
     acl_l3_rule.hpp
-    acl_list.hpp
+    acl_l3_list.hpp
+    acl_l2_list.hpp
     acl_types.hpp
   )
 endif()
index 3a123a8..2c9923b 100644 (file)
@@ -18,7 +18,8 @@
 
 #include <ostream>
 
-#include "vom/acl_list.hpp"
+#include "vom/acl_l2_list.hpp"
+#include "vom/acl_l3_list.hpp"
 #include "vom/acl_types.hpp"
 #include "vom/hw.hpp"
 #include "vom/inspect.hpp"
diff --git a/extras/vom/vom/acl_l2_list.cpp b/extras/vom/vom/acl_l2_list.cpp
new file mode 100644 (file)
index 0000000..939fb34
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "vom/acl_l2_list.hpp"
+#include "vom/acl_list_cmds.hpp"
+#include "vom/logger.hpp"
+#include "vom/singular_db_funcs.hpp"
+
+namespace VOM {
+namespace ACL {
+
+/**
+ * Definition of the static singular_db for ACL Lists
+ */
+singular_db<l2_list::key_t, l2_list> l2_list::m_db;
+
+/**
+ * Definition of the static per-handle DB for ACL Lists
+ */
+std::map<handle_t, std::weak_ptr<l2_list>> l2_list::m_hdl_db;
+
+l2_list::event_handler l2_list::m_evh;
+
+l2_list::event_handler::event_handler()
+{
+  OM::register_listener(this);
+  inspect::register_handler({ "l2-acl-list" }, "L2 ACL lists", this);
+}
+
+l2_list::l2_list(const key_t& key)
+  : m_hdl(handle_t::INVALID)
+  , m_key(key)
+{
+}
+
+l2_list::l2_list(const handle_t& hdl, const key_t& key)
+  : m_hdl(hdl)
+  , m_key(key)
+{
+}
+
+l2_list::l2_list(const key_t& key, const rules_t& rules)
+  : m_hdl(handle_t::INVALID)
+  , m_key(key)
+  , m_rules(rules)
+{
+}
+
+l2_list::l2_list(const l2_list& o)
+  : m_hdl(o.m_hdl)
+  , m_key(o.m_key)
+  , m_rules(o.m_rules)
+{
+}
+
+l2_list::~l2_list()
+{
+  sweep();
+  m_db.release(m_key, this);
+}
+
+std::shared_ptr<l2_list>
+l2_list::singular() const
+{
+  return find_or_add(*this);
+}
+
+/**
+ * Dump all ACLs into the stream provided
+ */
+void
+l2_list::dump(std::ostream& os)
+{
+  db_dump(m_db, os);
+}
+
+/**
+ * convert to string format for debug purposes
+ */
+std::string
+l2_list::to_string() const
+{
+  std::ostringstream s;
+  s << "acl-list:[" << m_key << " " << m_hdl.to_string() << " rules:[";
+
+  for (auto rule : m_rules) {
+    s << rule.to_string() << " ";
+  }
+
+  s << "]]";
+
+  return (s.str());
+}
+
+void
+l2_list::insert(const l2_rule& rule)
+{
+  m_rules.insert(rule);
+}
+
+void
+l2_list::remove(const l2_rule& rule)
+{
+  m_rules.erase(rule);
+}
+
+const handle_t&
+l2_list::handle() const
+{
+  return (singular()->handle_i());
+}
+
+std::shared_ptr<l2_list>
+l2_list::find(const handle_t& handle)
+{
+  return (m_hdl_db[handle].lock());
+}
+
+std::shared_ptr<l2_list>
+l2_list::find(const key_t& key)
+{
+  return (m_db.find(key));
+}
+
+std::shared_ptr<l2_list>
+l2_list::find_or_add(const l2_list& temp)
+{
+  return (m_db.find_or_add(temp.key(), temp));
+}
+
+const handle_t&
+l2_list::handle_i() const
+{
+  return (m_hdl.data());
+}
+
+void
+l2_list::add(const key_t& key, const HW::item<handle_t>& item)
+{
+  std::shared_ptr<l2_list> sp = find(key);
+
+  if (sp && item) {
+    m_hdl_db[item.data()] = sp;
+  }
+}
+
+void
+l2_list::remove(const HW::item<handle_t>& item)
+{
+  m_hdl_db.erase(item.data());
+}
+
+const l2_list::key_t&
+l2_list::key() const
+{
+  return m_key;
+}
+
+const l2_list::rules_t&
+l2_list::rules() const
+{
+  return m_rules;
+}
+
+bool
+l2_list::operator==(const l2_list& l) const
+{
+  return (key() == l.key() && rules() == l.rules());
+}
+
+void
+l2_list::event_handler::handle_populate(const client_db::key_t& key)
+{
+  /*
+   * dump L2 ACLs
+   */
+  std::shared_ptr<list_cmds::l2_dump_cmd> cmd =
+    std::make_shared<list_cmds::l2_dump_cmd>();
+
+  HW::enqueue(cmd);
+  HW::write();
+
+  for (auto& record : *cmd) {
+    auto& payload = record.get_payload();
+
+    const handle_t hdl(payload.acl_index);
+    l2_list acl(hdl, std::string(reinterpret_cast<const char*>(payload.tag)));
+
+    for (unsigned int ii = 0; ii < payload.count; ii++) {
+      const route::prefix_t pfx(payload.r[ii].is_ipv6,
+                                payload.r[ii].src_ip_addr,
+                                payload.r[ii].src_ip_prefix_len);
+      l2_rule rule(ii, action_t::from_int(payload.r[ii].is_permit), pfx,
+                   { payload.r[ii].src_mac }, { payload.r[ii].src_mac_mask });
+
+      acl.insert(rule);
+    }
+    VOM_LOG(log_level_t::DEBUG) << "dump: " << acl.to_string();
+
+    /*
+     * Write each of the discovered ACLs into the OM,
+     * but disable the HW Command q whilst we do, so that no
+     * commands are sent to VPP
+     */
+    OM::commit(key, acl);
+  }
+}
+
+void
+l2_list::event_handler::show(std::ostream& os)
+{
+  db_dump(m_db, os);
+}
+
+dependency_t
+l2_list::event_handler::order() const
+{
+  return (dependency_t::ACL);
+}
+
+void
+l2_list::event_handler::handle_replay()
+{
+  m_db.replay();
+}
+
+void
+l2_list::update(const l2_list& obj)
+{
+  /*
+   * always update the instance with the latest rule set
+   */
+  if (rc_t::OK != m_hdl.rc() || obj.m_rules != m_rules) {
+    HW::enqueue(new list_cmds::l2_update_cmd(m_hdl, m_key, m_rules));
+  }
+  /*
+   * We don't, can't, read the priority from VPP,
+   * so the is equals check above does not include the priorty.
+   * but we save it now.
+   */
+  m_rules = obj.m_rules;
+}
+
+void
+l2_list::sweep(void)
+{
+  if (m_hdl) {
+    HW::enqueue(new list_cmds::l2_delete_cmd(m_hdl));
+  }
+  HW::write();
+}
+
+void
+l2_list::replay(void)
+{
+  if (m_hdl) {
+    m_hdl.data().reset();
+    HW::enqueue(new list_cmds::l2_update_cmd(m_hdl, m_key, m_rules));
+  }
+}
+
+}; // namespace ACL
+}; // namespace VOM
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
similarity index 53%
rename from extras/vom/vom/acl_list.hpp
rename to extras/vom/vom/acl_l2_list.hpp
index eff5e1c..82cfd07 100644 (file)
  * limitations under the License.
  */
 
-#ifndef __VOM_ACL_LIST_H__
-#define __VOM_ACL_LIST_H__
+#ifndef __VOM_ACL_L2_LIST_H__
+#define __VOM_ACL_L2_LIST_H__
 
 #include <set>
 
 #include "vom/acl_l2_rule.hpp"
-#include "vom/acl_l3_rule.hpp"
 #include "vom/acl_types.hpp"
 #include "vom/hw.hpp"
 #include "vom/inspect.hpp"
 namespace VOM {
 namespace ACL {
 /**
- * An ACL list comprises a set of match actions rules to be applied to
+ * An L2 ACL list comprises a set of match actions rules to be applied to
  * packets.
  * A list is bound to a given interface.
  */
-template <typename RULE>
-class list : public object_base
+class l2_list : public object_base
 {
 public:
   /**
@@ -47,126 +45,72 @@ public:
   /**
    * The rule container type
    */
-  typedef std::multiset<RULE> rules_t;
+  typedef std::multiset<l2_rule> rules_t;
 
   /**
    * Construct a new object matching the desried state
    */
-  list(const key_t& key)
-    : m_hdl(handle_t::INVALID)
-    , m_key(key)
-  {
-  }
+  l2_list(const key_t& key);
 
-  list(const handle_t& hdl, const key_t& key)
-    : m_hdl(hdl)
-    , m_key(key)
-  {
-  }
+  l2_list(const handle_t& hdl, const key_t& key);
 
-  list(const key_t& key, const rules_t& rules)
-    : m_hdl(handle_t::INVALID)
-    , m_key(key)
-    , m_rules(rules)
-  {
-  }
+  l2_list(const key_t& key, const rules_t& rules);
 
   /**
    * Copy Constructor
    */
-  list(const list& o)
-    : m_hdl(o.m_hdl)
-    , m_key(o.m_key)
-    , m_rules(o.m_rules)
-  {
-  }
+  l2_list(const l2_list& o);
 
   /**
    * Destructor
    */
-  ~list()
-  {
-    sweep();
-    m_db.release(m_key, this);
-  }
+  ~l2_list();
 
   /**
    * Return the 'sigular instance' of the ACL that matches this object
    */
-  std::shared_ptr<list> singular() const { return find_or_add(*this); }
+  std::shared_ptr<l2_list> singular() const;
 
   /**
    * Dump all ACLs into the stream provided
    */
-  static void dump(std::ostream& os) { m_db.dump(os); }
+  static void dump(std::ostream& os);
 
   /**
    * convert to string format for debug purposes
    */
-  std::string to_string() const
-  {
-    std::ostringstream s;
-    s << "acl-list:[" << m_key << " " << m_hdl.to_string() << " rules:[";
-
-    for (auto rule : m_rules) {
-      s << rule.to_string() << " ";
-    }
-
-    s << "]]";
-
-    return (s.str());
-  }
+  std::string to_string() const;
 
   /**
    * Insert priority sorted a rule into the list
    */
-  void insert(const RULE& rule) { m_rules.insert(rule); }
+  void insert(const l2_rule& rule);
 
   /**
    * Remove a rule from the list
    */
-  void remove(const RULE& rule) { m_rules.erase(rule); }
+  void remove(const l2_rule& rule);
 
   /**
    * Return the VPP assign handle
    */
-  const handle_t& handle() const { return (singular()->handle_i()); }
-
-  static std::shared_ptr<list> find(const handle_t& handle)
-  {
-    return (m_hdl_db[handle].lock());
-  }
-
-  static std::shared_ptr<list> find(const key_t& key)
-  {
-    return (m_db.find(key));
-  }
+  const handle_t& handle() const;
 
-  static void add(const key_t& key, const HW::item<handle_t>& item)
-  {
-    std::shared_ptr<list> sp = find(key);
+  static std::shared_ptr<l2_list> find(const handle_t& handle);
 
-    if (sp && item) {
-      m_hdl_db[item.data()] = sp;
-    }
-  }
+  static std::shared_ptr<l2_list> find(const key_t& key);
+  static void add(const key_t& key, const HW::item<handle_t>& item);
 
-  static void remove(const HW::item<handle_t>& item)
-  {
-    m_hdl_db.erase(item.data());
-  }
+  static void remove(const HW::item<handle_t>& item);
 
-  const key_t& key() const { return m_key; }
+  const key_t& key() const;
 
-  const rules_t& rules() const { return m_rules; }
+  const rules_t& rules() const;
 
   /**
    * Comparison operator - for UT
    */
-  bool operator==(const list& l) const
-  {
-    return (key() == l.key() && rules() == l.rules());
-  }
+  bool operator==(const l2_list& l) const;
 
 private:
   /**
@@ -187,7 +131,7 @@ private:
     /**
      * Handle a replay event
      */
-    void handle_replay() { m_db.replay(); }
+    void handle_replay();
 
     /**
      * Show the object in the Singular DB
@@ -197,7 +141,7 @@ private:
     /**
      * Get the sortable Id of the listener
      */
-    dependency_t order() const { return (dependency_t::ACL); }
+    dependency_t order() const;
   };
 
   /**
@@ -208,7 +152,7 @@ private:
   /**
    * Enqueue commands to the VPP command Q for the update
    */
-  void update(const list& obj);
+  void update(const l2_list& obj);
 
   /**
    * HW assigned handle
@@ -218,15 +162,12 @@ private:
   /**
    * Find or add the sigular instance in the DB
    */
-  static std::shared_ptr<list> find_or_add(const list& temp)
-  {
-    return (m_db.find_or_add(temp.key(), temp));
-  }
+  static std::shared_ptr<l2_list> find_or_add(const l2_list& temp);
 
   /**
    * return the acl-list's handle in the singular instance
    */
-  const handle_t& handle_i() const { return (m_hdl.data()); }
+  const handle_t& handle_i() const;
 
   /*
    * It's the VOM::OM class that updates call update
@@ -236,7 +177,7 @@ private:
   /**
    * It's the VOM::singular_db class that calls replay()
    */
-  friend class singular_db<key_t, list>;
+  friend class singular_db<key_t, l2_list>;
 
   /**
    * Sweep/reap the object if still stale
@@ -251,12 +192,12 @@ private:
   /**
    * A map of all ACL's against the client's key
    */
-  static singular_db<key_t, list> m_db;
+  static singular_db<key_t, l2_list> m_db;
 
   /**
    * A map of all ACLs keyed against VPP's handle
    */
-  static std::map<handle_t, std::weak_ptr<list>> m_hdl_db;
+  static std::map<handle_t, std::weak_ptr<l2_list>> m_hdl_db;
 
   /**
    * The Key is a user defined identifer for this ACL
@@ -269,32 +210,8 @@ private:
   rules_t m_rules;
 };
 
-/**
- * Typedef the L3 ACL type
- */
-typedef list<l3_rule> l3_list;
-
-/**
- * Typedef the L2 ACL type
- */
-typedef list<l2_rule> l2_list;
-
-/**
- * Definition of the static singular_db for ACL Lists
- */
-template <typename RULE>
-singular_db<typename ACL::list<RULE>::key_t, ACL::list<RULE>> list<RULE>::m_db;
-
-/**
- * Definition of the static per-handle DB for ACL Lists
- */
-template <typename RULE>
-std::map<handle_t, std::weak_ptr<ACL::list<RULE>>> list<RULE>::m_hdl_db;
-
-template <typename RULE>
-typename ACL::list<RULE>::event_handler list<RULE>::m_evh;
-};
-};
+}; // namesace ACL
+}; // namespace VOM
 
 /*
  * fd.io coding-style-patch-verification: ON
similarity index 60%
rename from extras/vom/vom/acl_list.cpp
rename to extras/vom/vom/acl_l3_list.cpp
index 651eb87..d3e4474 100644 (file)
@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-#include "vom/acl_list.hpp"
+#include "vom/acl_l3_list.hpp"
 #include "vom/acl_list_cmds.hpp"
 #include "vom/logger.hpp"
 #include "vom/singular_db_funcs.hpp"
 namespace VOM {
 namespace ACL {
 
-template <>
-l2_list::event_handler::event_handler()
+/**
+ * Definition of the static singular_db for ACL Lists
+ */
+singular_db<l3_list::key_t, l3_list> l3_list::m_db;
+
+/**
+ * Definition of the static per-handle DB for ACL Lists
+ */
+std::map<handle_t, std::weak_ptr<l3_list>> l3_list::m_hdl_db;
+
+l3_list::event_handler l3_list::m_evh;
+
+l3_list::event_handler::event_handler()
 {
   OM::register_listener(this);
-  inspect::register_handler({ "l2-acl-list" }, "L2 ACL lists", this);
+  inspect::register_handler({ "l3-acl-list" }, "L3 ACL lists", this);
+}
+
+l3_list::l3_list(const key_t& key)
+  : m_hdl(handle_t::INVALID)
+  , m_key(key)
+{
 }
 
-template <>
+l3_list::l3_list(const handle_t& hdl, const key_t& key)
+  : m_hdl(hdl)
+  , m_key(key)
+{
+}
+
+l3_list::l3_list(const key_t& key, const rules_t& rules)
+  : m_hdl(handle_t::INVALID)
+  , m_key(key)
+  , m_rules(rules)
+{
+}
+
+l3_list::l3_list(const l3_list& o)
+  : m_hdl(o.m_hdl)
+  , m_key(o.m_key)
+  , m_rules(o.m_rules)
+{
+}
+
+l3_list::~l3_list()
+{
+  sweep();
+  m_db.release(m_key, this);
+}
+
+std::shared_ptr<l3_list>
+l3_list::singular() const
+{
+  return find_or_add(*this);
+}
+
+/**
+ * Dump all ACLs into the stream provided
+ */
 void
-l2_list::event_handler::handle_populate(const client_db::key_t& key)
+l3_list::dump(std::ostream& os)
 {
-  /* hack to get this function instantiated */
-  m_evh.order();
+  db_dump(m_db, os);
+}
 
-  /*
-   * dump VPP Bridge domains
-   */
-  std::shared_ptr<list_cmds::l2_dump_cmd> cmd =
-    std::make_shared<list_cmds::l2_dump_cmd>();
+/**
+ * convert to string format for debug purposes
+ */
+std::string
+l3_list::to_string() const
+{
+  std::ostringstream s;
+  s << "acl-list:[" << m_key << " " << m_hdl.to_string() << " rules:[";
 
-  HW::enqueue(cmd);
-  HW::write();
+  for (auto rule : m_rules) {
+    s << rule.to_string() << " ";
+  }
 
-  for (auto& record : *cmd) {
-    auto& payload = record.get_payload();
+  s << "]]";
 
-    const handle_t hdl(payload.acl_index);
-    l2_list acl(hdl, std::string(reinterpret_cast<const char*>(payload.tag)));
+  return (s.str());
+}
 
-    for (unsigned int ii = 0; ii < payload.count; ii++) {
-      const route::prefix_t pfx(payload.r[ii].is_ipv6,
-                                payload.r[ii].src_ip_addr,
-                                payload.r[ii].src_ip_prefix_len);
-      l2_rule rule(ii, action_t::from_int(payload.r[ii].is_permit), pfx,
-                   { payload.r[ii].src_mac }, { payload.r[ii].src_mac_mask });
+void
+l3_list::insert(const l3_rule& rule)
+{
+  m_rules.insert(rule);
+}
 
-      acl.insert(rule);
-    }
-    VOM_LOG(log_level_t::DEBUG) << "dump: " << acl.to_string();
+void
+l3_list::remove(const l3_rule& rule)
+{
+  m_rules.erase(rule);
+}
 
-    /*
-     * Write each of the discovered ACLs into the OM,
-     * but disable the HW Command q whilst we do, so that no
-     * commands are sent to VPP
-     */
-    OM::commit(key, acl);
+const handle_t&
+l3_list::handle() const
+{
+  return (singular()->handle_i());
+}
+
+std::shared_ptr<l3_list>
+l3_list::find(const handle_t& handle)
+{
+  return (m_hdl_db[handle].lock());
+}
+
+std::shared_ptr<l3_list>
+l3_list::find(const key_t& key)
+{
+  return (m_db.find(key));
+}
+
+std::shared_ptr<l3_list>
+l3_list::find_or_add(const l3_list& temp)
+{
+  return (m_db.find_or_add(temp.key(), temp));
+}
+
+const handle_t&
+l3_list::handle_i() const
+{
+  return (m_hdl.data());
+}
+
+void
+l3_list::add(const key_t& key, const HW::item<handle_t>& item)
+{
+  std::shared_ptr<l3_list> sp = find(key);
+
+  if (sp && item) {
+    m_hdl_db[item.data()] = sp;
   }
 }
 
-template <>
 void
-l2_list::event_handler::show(std::ostream& os)
+l3_list::remove(const HW::item<handle_t>& item)
 {
-  db_dump(m_db, os);
+  m_hdl_db.erase(item.data());
 }
 
-template <>
-l3_list::event_handler::event_handler()
+const l3_list::key_t&
+l3_list::key() const
 {
-  OM::register_listener(this);
-  inspect::register_handler({ "l3-acl-list" }, "L3 ACL lists", this);
+  return m_key;
+}
+
+const l3_list::rules_t&
+l3_list::rules() const
+{
+  return m_rules;
+}
+
+bool
+l3_list::operator==(const l3_list& l) const
+{
+  return (key() == l.key() && rules() == l.rules());
 }
 
-template <>
 void
 l3_list::event_handler::handle_populate(const client_db::key_t& key)
 {
-  /* hack to get this function instantiated */
-  m_evh.order();
-
   /*
    * dump L3 ACLs Bridge domains
    */
@@ -136,39 +228,32 @@ l3_list::event_handler::handle_populate(const client_db::key_t& key)
   }
 }
 
-template <>
 void
 l3_list::event_handler::show(std::ostream& os)
 {
   db_dump(m_db, os);
 }
 
-template <>
+dependency_t
+l3_list::event_handler::order() const
+{
+  return (dependency_t::ACL);
+}
+
 void
-l3_list::update(const l3_list& obj)
+l3_list::event_handler::handle_replay()
 {
-  /*
-   * always update the instance with the latest rule set
-   */
-  if (rc_t::OK != m_hdl.rc() || obj.m_rules != m_rules) {
-    HW::enqueue(new list_cmds::l3_update_cmd(m_hdl, m_key, m_rules));
-  }
-  /*
-   * We don't, can't, read the priority from VPP,
-   * so the is equals check above does not include the priorty.
-   * but we save it now.
-   */
-  m_rules = obj.m_rules;
+  m_db.replay();
 }
-template <>
+
 void
-l2_list::update(const l2_list& obj)
+l3_list::update(const l3_list& obj)
 {
   /*
    * always update the instance with the latest rule set
    */
   if (rc_t::OK != m_hdl.rc() || obj.m_rules != m_rules) {
-    HW::enqueue(new list_cmds::l2_update_cmd(m_hdl, m_key, m_rules));
+    HW::enqueue(new list_cmds::l3_update_cmd(m_hdl, m_key, m_rules));
   }
   /*
    * We don't, can't, read the priority from VPP,
@@ -177,10 +262,10 @@ l2_list::update(const l2_list& obj)
    */
   m_rules = obj.m_rules;
 }
+
 /**
  * Sweep/reap the object if still stale
  */
-template <>
 void
 l3_list::sweep(void)
 {
@@ -189,20 +274,10 @@ l3_list::sweep(void)
   }
   HW::write();
 }
-template <>
-void
-l2_list::sweep(void)
-{
-  if (m_hdl) {
-    HW::enqueue(new list_cmds::l2_delete_cmd(m_hdl));
-  }
-  HW::write();
-}
 
 /**
  * Replay the objects state to HW
  */
-template <>
 void
 l3_list::replay(void)
 {
@@ -211,15 +286,6 @@ l3_list::replay(void)
     HW::enqueue(new list_cmds::l3_update_cmd(m_hdl, m_key, m_rules));
   }
 }
-template <>
-void
-l2_list::replay(void)
-{
-  if (m_hdl) {
-    m_hdl.data().reset();
-    HW::enqueue(new list_cmds::l2_update_cmd(m_hdl, m_key, m_rules));
-  }
-}
 
 }; // namespace ACL
 }; // namespace VOM
diff --git a/extras/vom/vom/acl_l3_list.hpp b/extras/vom/vom/acl_l3_list.hpp
new file mode 100644 (file)
index 0000000..092bbe3
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __VOM_ACL_L3_LIST_H__
+#define __VOM_ACL_L3_LIST_H__
+
+#include <set>
+
+#include "vom/acl_l3_rule.hpp"
+#include "vom/acl_types.hpp"
+#include "vom/hw.hpp"
+#include "vom/inspect.hpp"
+#include "vom/om.hpp"
+#include "vom/singular_db.hpp"
+
+namespace VOM {
+namespace ACL {
+/**
+ * An L3 ACL list comprises a set of match actions rules to be applied to
+ * packets.
+ * A list is bound to a given interface.
+ */
+class l3_list : public object_base
+{
+public:
+  /**
+   * The KEY can be used to uniquely identify the ACL.
+   * (other choices for keys, like the summation of the properties
+   * of the rules, are rather too cumbersome to use
+   */
+  typedef std::string key_t;
+
+  /**
+   * The rule container type
+   */
+  typedef std::multiset<l3_rule> rules_t;
+
+  /**
+   * Construct a new object matching the desried state
+   */
+  l3_list(const key_t& key);
+
+  l3_list(const handle_t& hdl, const key_t& key);
+
+  l3_list(const key_t& key, const rules_t& rules);
+
+  /**
+   * Copy Constructor
+   */
+  l3_list(const l3_list& o);
+
+  /**
+   * Destructor
+   */
+  ~l3_list();
+
+  /**
+   * Return the 'sigular instance' of the ACL that matches this object
+   */
+  std::shared_ptr<l3_list> singular() const;
+
+  /**
+   * Dump all ACLs into the stream provided
+   */
+  static void dump(std::ostream& os);
+
+  /**
+   * convert to string format for debug purposes
+   */
+  std::string to_string() const;
+
+  /**
+   * Insert priority sorted a rule into the list
+   */
+  void insert(const l3_rule& rule);
+
+  /**
+   * Remove a rule from the list
+   */
+  void remove(const l3_rule& rule);
+
+  /**
+   * Return the VPP assign handle
+   */
+  const handle_t& handle() const;
+
+  static std::shared_ptr<l3_list> find(const handle_t& handle);
+
+  static std::shared_ptr<l3_list> find(const key_t& key);
+  static void add(const key_t& key, const HW::item<handle_t>& item);
+
+  static void remove(const HW::item<handle_t>& item);
+
+  const key_t& key() const;
+
+  const rules_t& rules() const;
+
+  /**
+   * Comparison operator - for UT
+   */
+  bool operator==(const l3_list& l) const;
+
+private:
+  /**
+   * Class definition for listeners to OM events
+   */
+  class event_handler : public OM::listener, public inspect::command_handler
+  {
+  public:
+    event_handler();
+
+    virtual ~event_handler() = default;
+
+    /**
+     * Handle a populate event
+     */
+    void handle_populate(const client_db::key_t& key);
+
+    /**
+     * Handle a replay event
+     */
+    void handle_replay();
+
+    /**
+     * Show the object in the Singular DB
+     */
+    void show(std::ostream& os);
+
+    /**
+     * Get the sortable Id of the listener
+     */
+    dependency_t order() const;
+  };
+
+  /**
+   * event_handler to register with OM
+   */
+  static event_handler m_evh;
+
+  /**
+   * Enqueue commands to the VPP command Q for the update
+   */
+  void update(const l3_list& obj);
+
+  /**
+   * HW assigned handle
+   */
+  HW::item<handle_t> m_hdl;
+
+  /**
+   * Find or add the sigular instance in the DB
+   */
+  static std::shared_ptr<l3_list> find_or_add(const l3_list& temp);
+
+  /**
+   * return the acl-list's handle in the singular instance
+   */
+  const handle_t& handle_i() const;
+
+  /*
+   * It's the VOM::OM class that updates call update
+   */
+  friend class VOM::OM;
+
+  /**
+   * It's the VOM::singular_db class that calls replay()
+   */
+  friend class singular_db<key_t, l3_list>;
+
+  /**
+   * Sweep/reap the object if still stale
+   */
+  void sweep(void);
+
+  /**
+   * Replay the objects state to HW
+   */
+  void replay(void);
+
+  /**
+   * A map of all ACL's against the client's key
+   */
+  static singular_db<key_t, l3_list> m_db;
+
+  /**
+   * A map of all ACLs keyed against VPP's handle
+   */
+  static std::map<handle_t, std::weak_ptr<l3_list>> m_hdl_db;
+
+  /**
+   * The Key is a user defined identifer for this ACL
+   */
+  const key_t m_key;
+
+  /**
+   * A sorted list of the rules
+   */
+  rules_t m_rules;
+};
+
+}; // namesace ACL
+}; // namespace VOM
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
+
+#endif
index ec69773..252dec7 100644 (file)
@@ -16,7 +16,8 @@
 #ifndef __VOM_ACL_LIST_CMDS_H__
 #define __VOM_ACL_LIST_CMDS_H__
 
-#include "vom/acl_list.hpp"
+#include "vom/acl_l2_list.hpp"
+#include "vom/acl_l3_list.hpp"
 #include "vom/dump_cmd.hpp"
 #include "vom/rpc_cmd.hpp"
 
@@ -28,12 +29,12 @@ namespace list_cmds {
 /**
  * A command class that Create the list
  */
-template <typename RULE, typename UPDATE>
+template <typename LIST, typename UPDATE>
 class update_cmd : public rpc_cmd<HW::item<handle_t>, UPDATE>
 {
 public:
-  typedef typename list<RULE>::rules_t cmd_rules_t;
-  typedef typename list<RULE>::key_t cmd_key_t;
+  typedef typename LIST::rules_t cmd_rules_t;
+  typedef typename LIST::key_t cmd_key_t;
 
   /**
    * Constructor
@@ -78,7 +79,7 @@ public:
   void succeeded()
   {
     rpc_cmd<HW::item<handle_t>, UPDATE>::succeeded();
-    list<RULE>::add(m_key, this->item());
+    LIST::add(m_key, this->item());
   }
 
   /**
@@ -106,7 +107,7 @@ private:
   /**
    * add the created acl to the DB
    */
-  void insert_acl() { list<RULE>::add(m_key, this->item()); }
+  void insert_acl() { LIST::add(m_key, this->item()); }
 
   /**
    * The key.
@@ -122,7 +123,7 @@ private:
 /**
  * A cmd class that Deletes an ACL
  */
-template <typename RULE, typename DELETE>
+template <typename LIST, typename DELETE>
 class delete_cmd : public rpc_cmd<HW::item<handle_t>, DELETE>
 {
 public:
@@ -162,7 +163,7 @@ private:
   /**
    * remove the acl from the DB
    */
-  void remove_acl() { list<RULE>::remove(this->item()); }
+  void remove_acl() { LIST::remove(this->item()); }
 };
 
 /**
@@ -196,15 +197,15 @@ public:
 /**
  * Typedef the L3 ACL commands
  */
-typedef update_cmd<l3_rule, vapi::Acl_add_replace> l3_update_cmd;
-typedef delete_cmd<l3_rule, vapi::Acl_del> l3_delete_cmd;
+typedef update_cmd<l3_list, vapi::Acl_add_replace> l3_update_cmd;
+typedef delete_cmd<l3_list, vapi::Acl_del> l3_delete_cmd;
 typedef dump_cmd<vapi::Acl_dump> l3_dump_cmd;
 
 /**
  * Typedef the L2 ACL commands
  */
-typedef update_cmd<l2_rule, vapi::Macip_acl_add> l2_update_cmd;
-typedef delete_cmd<l2_rule, vapi::Macip_acl_del> l2_delete_cmd;
+typedef update_cmd<l2_list, vapi::Macip_acl_add> l2_update_cmd;
+typedef delete_cmd<l2_list, vapi::Macip_acl_del> l2_delete_cmd;
 typedef dump_cmd<vapi::Macip_acl_dump> l2_dump_cmd;
 
 }; // namespace list_cmds
index e517a3d..2f1c3c5 100644 (file)
@@ -16,7 +16,7 @@
 #ifndef __VOM_GBP_CONTRACT_H__
 #define __VOM_GBP_CONTRACT_H__
 
-#include "vom/acl_list.hpp"
+#include "vom/acl_l3_list.hpp"
 #include "vom/gbp_endpoint.hpp"
 #include "vom/gbp_rule.hpp"
 #include "vom/interface.hpp"
index 2665394..569bd8c 100644 (file)
@@ -48,7 +48,8 @@
 #include "vom/sub_interface_cmds.hpp"
 #include "vom/acl_ethertype.hpp"
 #include "vom/acl_ethertype_cmds.hpp"
-#include "vom/acl_list.hpp"
+#include "vom/acl_l2_list.hpp"
+#include "vom/acl_l3_list.hpp"
 #include "vom/acl_binding.hpp"
 #include "vom/acl_list_cmds.hpp"
 #include "vom/acl_binding_cmds.hpp"