diff options
author | Neale Ranns <nranns@cisco.com> | 2019-02-22 00:44:40 -0800 |
---|---|---|
committer | Neale Ranns <nranns@cisco.com> | 2019-02-22 15:41:51 +0000 |
commit | 5637e653649692eb04fbec5c97e0fd427404c1dd (patch) | |
tree | 72105c0ee0e85ad17305e8cf98cbe0e08294e5e5 | |
parent | ba94462c42a27f7447e10ca55a3b212970448ceb (diff) |
VOM: De-template the ACL code.
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>
-rw-r--r-- | extras/vom/vom/CMakeLists.txt | 6 | ||||
-rw-r--r-- | extras/vom/vom/acl_binding.hpp | 3 | ||||
-rw-r--r-- | extras/vom/vom/acl_l2_list.cpp | 283 | ||||
-rw-r--r-- | extras/vom/vom/acl_l2_list.hpp (renamed from extras/vom/vom/acl_list.hpp) | 149 | ||||
-rw-r--r-- | extras/vom/vom/acl_l3_list.cpp (renamed from extras/vom/vom/acl_list.cpp) | 232 | ||||
-rw-r--r-- | extras/vom/vom/acl_l3_list.hpp | 224 | ||||
-rw-r--r-- | extras/vom/vom/acl_list_cmds.hpp | 25 | ||||
-rw-r--r-- | extras/vom/vom/gbp_contract.hpp | 2 | ||||
-rw-r--r-- | test/ext/vom_test.cpp | 3 |
9 files changed, 711 insertions, 216 deletions
diff --git a/extras/vom/vom/CMakeLists.txt b/extras/vom/vom/CMakeLists.txt index a0a5f9783e9..26dd3e46574 100644 --- a/extras/vom/vom/CMakeLists.txt +++ b/extras/vom/vom/CMakeLists.txt @@ -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() diff --git a/extras/vom/vom/acl_binding.hpp b/extras/vom/vom/acl_binding.hpp index 3a123a853cd..2c9923b8266 100644 --- a/extras/vom/vom/acl_binding.hpp +++ b/extras/vom/vom/acl_binding.hpp @@ -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 index 00000000000..939fb348d0b --- /dev/null +++ b/extras/vom/vom/acl_l2_list.cpp @@ -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: + */ diff --git a/extras/vom/vom/acl_list.hpp b/extras/vom/vom/acl_l2_list.hpp index eff5e1c5a52..82cfd072fe7 100644 --- a/extras/vom/vom/acl_list.hpp +++ b/extras/vom/vom/acl_l2_list.hpp @@ -13,13 +13,12 @@ * 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" @@ -29,12 +28,11 @@ 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 diff --git a/extras/vom/vom/acl_list.cpp b/extras/vom/vom/acl_l3_list.cpp index 651eb87a4a9..d3e44746ae1 100644 --- a/extras/vom/vom/acl_list.cpp +++ b/extras/vom/vom/acl_l3_list.cpp @@ -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" @@ -21,76 +21,168 @@ 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 index 00000000000..092bbe37dc0 --- /dev/null +++ b/extras/vom/vom/acl_l3_list.hpp @@ -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 diff --git a/extras/vom/vom/acl_list_cmds.hpp b/extras/vom/vom/acl_list_cmds.hpp index ec69773f857..252dec7175d 100644 --- a/extras/vom/vom/acl_list_cmds.hpp +++ b/extras/vom/vom/acl_list_cmds.hpp @@ -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 diff --git a/extras/vom/vom/gbp_contract.hpp b/extras/vom/vom/gbp_contract.hpp index e517a3d6428..2f1c3c5a950 100644 --- a/extras/vom/vom/gbp_contract.hpp +++ b/extras/vom/vom/gbp_contract.hpp @@ -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" diff --git a/test/ext/vom_test.cpp b/test/ext/vom_test.cpp index 26653940d2e..569bd8c1fd9 100644 --- a/test/ext/vom_test.cpp +++ b/test/ext/vom_test.cpp @@ -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" |