From 5637e653649692eb04fbec5c97e0fd427404c1dd Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Fri, 22 Feb 2019 00:44:40 -0800 Subject: 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 --- extras/vom/vom/CMakeLists.txt | 6 +- extras/vom/vom/acl_binding.hpp | 3 +- extras/vom/vom/acl_l2_list.cpp | 283 ++++++++++++++++++++++++++++++++++++ extras/vom/vom/acl_l2_list.hpp | 224 ++++++++++++++++++++++++++++ extras/vom/vom/acl_l3_list.cpp | 299 ++++++++++++++++++++++++++++++++++++++ extras/vom/vom/acl_l3_list.hpp | 224 ++++++++++++++++++++++++++++ extras/vom/vom/acl_list.cpp | 233 ----------------------------- extras/vom/vom/acl_list.hpp | 307 --------------------------------------- extras/vom/vom/acl_list_cmds.hpp | 25 ++-- extras/vom/vom/gbp_contract.hpp | 2 +- 10 files changed, 1050 insertions(+), 556 deletions(-) create mode 100644 extras/vom/vom/acl_l2_list.cpp create mode 100644 extras/vom/vom/acl_l2_list.hpp create mode 100644 extras/vom/vom/acl_l3_list.cpp create mode 100644 extras/vom/vom/acl_l3_list.hpp delete mode 100644 extras/vom/vom/acl_list.cpp delete mode 100644 extras/vom/vom/acl_list.hpp (limited to 'extras') 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 -#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::m_db; + +/** + * Definition of the static per-handle DB for ACL Lists + */ +std::map> 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::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::find(const handle_t& handle) +{ + return (m_hdl_db[handle].lock()); +} + +std::shared_ptr +l2_list::find(const key_t& key) +{ + return (m_db.find(key)); +} + +std::shared_ptr +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& item) +{ + std::shared_ptr sp = find(key); + + if (sp && item) { + m_hdl_db[item.data()] = sp; + } +} + +void +l2_list::remove(const HW::item& 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 cmd = + std::make_shared(); + + 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(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_l2_list.hpp b/extras/vom/vom/acl_l2_list.hpp new file mode 100644 index 00000000000..82cfd072fe7 --- /dev/null +++ b/extras/vom/vom/acl_l2_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_L2_LIST_H__ +#define __VOM_ACL_L2_LIST_H__ + +#include + +#include "vom/acl_l2_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 L2 ACL list comprises a set of match actions rules to be applied to + * packets. + * A list is bound to a given interface. + */ +class l2_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 rules_t; + + /** + * Construct a new object matching the desried state + */ + l2_list(const key_t& key); + + l2_list(const handle_t& hdl, const key_t& key); + + l2_list(const key_t& key, const rules_t& rules); + + /** + * Copy Constructor + */ + l2_list(const l2_list& o); + + /** + * Destructor + */ + ~l2_list(); + + /** + * Return the 'sigular instance' of the ACL that matches this object + */ + std::shared_ptr 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 l2_rule& rule); + + /** + * Remove a rule from the list + */ + void remove(const l2_rule& rule); + + /** + * Return the VPP assign handle + */ + const handle_t& handle() const; + + static std::shared_ptr find(const handle_t& handle); + + static std::shared_ptr find(const key_t& key); + static void add(const key_t& key, const HW::item& item); + + static void remove(const HW::item& item); + + const key_t& key() const; + + const rules_t& rules() const; + + /** + * Comparison operator - for UT + */ + bool operator==(const l2_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 l2_list& obj); + + /** + * HW assigned handle + */ + HW::item m_hdl; + + /** + * Find or add the sigular instance in the DB + */ + static std::shared_ptr find_or_add(const l2_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; + + /** + * 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 m_db; + + /** + * A map of all ACLs keyed against VPP's handle + */ + static std::map> 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_l3_list.cpp b/extras/vom/vom/acl_l3_list.cpp new file mode 100644 index 00000000000..d3e44746ae1 --- /dev/null +++ b/extras/vom/vom/acl_l3_list.cpp @@ -0,0 +1,299 @@ +/* + * 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_l3_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 l3_list::m_db; + +/** + * Definition of the static per-handle DB for ACL Lists + */ +std::map> 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({ "l3-acl-list" }, "L3 ACL lists", this); +} + +l3_list::l3_list(const key_t& key) + : m_hdl(handle_t::INVALID) + , m_key(key) +{ +} + +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::singular() const +{ + return find_or_add(*this); +} + +/** + * Dump all ACLs into the stream provided + */ +void +l3_list::dump(std::ostream& os) +{ + db_dump(m_db, os); +} + +/** + * 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:["; + + for (auto rule : m_rules) { + s << rule.to_string() << " "; + } + + s << "]]"; + + return (s.str()); +} + +void +l3_list::insert(const l3_rule& rule) +{ + m_rules.insert(rule); +} + +void +l3_list::remove(const l3_rule& rule) +{ + m_rules.erase(rule); +} + +const handle_t& +l3_list::handle() const +{ + return (singular()->handle_i()); +} + +std::shared_ptr +l3_list::find(const handle_t& handle) +{ + return (m_hdl_db[handle].lock()); +} + +std::shared_ptr +l3_list::find(const key_t& key) +{ + return (m_db.find(key)); +} + +std::shared_ptr +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& item) +{ + std::shared_ptr sp = find(key); + + if (sp && item) { + m_hdl_db[item.data()] = sp; + } +} + +void +l3_list::remove(const HW::item& item) +{ + m_hdl_db.erase(item.data()); +} + +const l3_list::key_t& +l3_list::key() const +{ + 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()); +} + +void +l3_list::event_handler::handle_populate(const client_db::key_t& key) +{ + /* + * dump L3 ACLs Bridge domains + */ + std::shared_ptr cmd = + std::make_shared(); + + HW::enqueue(cmd); + HW::write(); + + for (auto& record : *cmd) { + auto& payload = record.get_payload(); + + const handle_t hdl(payload.acl_index); + l3_list acl(hdl, std::string(reinterpret_cast(payload.tag))); + + for (unsigned int ii = 0; ii < payload.count; ii++) { + const route::prefix_t src(payload.r[ii].is_ipv6, + payload.r[ii].src_ip_addr, + payload.r[ii].src_ip_prefix_len); + const route::prefix_t dst(payload.r[ii].is_ipv6, + payload.r[ii].dst_ip_addr, + payload.r[ii].dst_ip_prefix_len); + l3_rule rule(ii, action_t::from_int(payload.r[ii].is_permit), src, dst); + + rule.set_proto(payload.r[ii].proto); + rule.set_src_from_port(payload.r[ii].srcport_or_icmptype_first); + rule.set_src_to_port(payload.r[ii].srcport_or_icmptype_last); + rule.set_dst_from_port(payload.r[ii].dstport_or_icmpcode_first); + rule.set_dst_to_port(payload.r[ii].dstport_or_icmpcode_last); + rule.set_tcp_flags_mask(payload.r[ii].tcp_flags_mask); + rule.set_tcp_flags_value(payload.r[ii].tcp_flags_value); + + 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 +l3_list::event_handler::show(std::ostream& os) +{ + db_dump(m_db, os); +} + +dependency_t +l3_list::event_handler::order() const +{ + return (dependency_t::ACL); +} + +void +l3_list::event_handler::handle_replay() +{ + m_db.replay(); +} + +void +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::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; +} + +/** + * Sweep/reap the object if still stale + */ +void +l3_list::sweep(void) +{ + if (m_hdl) { + HW::enqueue(new list_cmds::l3_delete_cmd(m_hdl)); + } + HW::write(); +} + +/** + * Replay the objects state to HW + */ +void +l3_list::replay(void) +{ + if (m_hdl) { + m_hdl.data().reset(); + HW::enqueue(new list_cmds::l3_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_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 + +#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 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 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 find(const handle_t& handle); + + static std::shared_ptr find(const key_t& key); + static void add(const key_t& key, const HW::item& item); + + static void remove(const HW::item& 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 m_hdl; + + /** + * Find or add the sigular instance in the DB + */ + static std::shared_ptr 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; + + /** + * 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 m_db; + + /** + * A map of all ACLs keyed against VPP's handle + */ + static std::map> 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.cpp b/extras/vom/vom/acl_list.cpp deleted file mode 100644 index 651eb87a4a9..00000000000 --- a/extras/vom/vom/acl_list.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* - * 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_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() -{ - OM::register_listener(this); - inspect::register_handler({ "l2-acl-list" }, "L2 ACL lists", this); -} - -template <> -void -l2_list::event_handler::handle_populate(const client_db::key_t& key) -{ - /* hack to get this function instantiated */ - m_evh.order(); - - /* - * dump VPP Bridge domains - */ - std::shared_ptr cmd = - std::make_shared(); - - 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(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); - } -} - -template <> -void -l2_list::event_handler::show(std::ostream& os) -{ - db_dump(m_db, os); -} - -template <> -l3_list::event_handler::event_handler() -{ - OM::register_listener(this); - inspect::register_handler({ "l3-acl-list" }, "L3 ACL lists", this); -} - -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 - */ - std::shared_ptr cmd = - std::make_shared(); - - HW::enqueue(cmd); - HW::write(); - - for (auto& record : *cmd) { - auto& payload = record.get_payload(); - - const handle_t hdl(payload.acl_index); - l3_list acl(hdl, std::string(reinterpret_cast(payload.tag))); - - for (unsigned int ii = 0; ii < payload.count; ii++) { - const route::prefix_t src(payload.r[ii].is_ipv6, - payload.r[ii].src_ip_addr, - payload.r[ii].src_ip_prefix_len); - const route::prefix_t dst(payload.r[ii].is_ipv6, - payload.r[ii].dst_ip_addr, - payload.r[ii].dst_ip_prefix_len); - l3_rule rule(ii, action_t::from_int(payload.r[ii].is_permit), src, dst); - - rule.set_proto(payload.r[ii].proto); - rule.set_src_from_port(payload.r[ii].srcport_or_icmptype_first); - rule.set_src_to_port(payload.r[ii].srcport_or_icmptype_last); - rule.set_dst_from_port(payload.r[ii].dstport_or_icmpcode_first); - rule.set_dst_to_port(payload.r[ii].dstport_or_icmpcode_last); - rule.set_tcp_flags_mask(payload.r[ii].tcp_flags_mask); - rule.set_tcp_flags_value(payload.r[ii].tcp_flags_value); - - 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); - } -} - -template <> -void -l3_list::event_handler::show(std::ostream& os) -{ - db_dump(m_db, os); -} - -template <> -void -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::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; -} -template <> -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; -} -/** - * Sweep/reap the object if still stale - */ -template <> -void -l3_list::sweep(void) -{ - if (m_hdl) { - HW::enqueue(new list_cmds::l3_delete_cmd(m_hdl)); - } - 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) -{ - if (m_hdl) { - m_hdl.data().reset(); - 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 - -/* - * 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_list.hpp deleted file mode 100644 index eff5e1c5a52..00000000000 --- a/extras/vom/vom/acl_list.hpp +++ /dev/null @@ -1,307 +0,0 @@ -/* - * 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_LIST_H__ -#define __VOM_ACL_LIST_H__ - -#include - -#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" -#include "vom/om.hpp" -#include "vom/singular_db.hpp" - -namespace VOM { -namespace ACL { -/** - * An ACL list comprises a set of match actions rules to be applied to - * packets. - * A list is bound to a given interface. - */ -template -class 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 rules_t; - - /** - * Construct a new object matching the desried state - */ - list(const key_t& key) - : m_hdl(handle_t::INVALID) - , m_key(key) - { - } - - list(const handle_t& hdl, const key_t& key) - : m_hdl(hdl) - , m_key(key) - { - } - - list(const key_t& key, const rules_t& rules) - : m_hdl(handle_t::INVALID) - , m_key(key) - , m_rules(rules) - { - } - - /** - * Copy Constructor - */ - list(const list& o) - : m_hdl(o.m_hdl) - , m_key(o.m_key) - , m_rules(o.m_rules) - { - } - - /** - * Destructor - */ - ~list() - { - sweep(); - m_db.release(m_key, this); - } - - /** - * Return the 'sigular instance' of the ACL that matches this object - */ - std::shared_ptr singular() const { return find_or_add(*this); } - - /** - * Dump all ACLs into the stream provided - */ - static void dump(std::ostream& os) { m_db.dump(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()); - } - - /** - * Insert priority sorted a rule into the list - */ - void insert(const RULE& rule) { m_rules.insert(rule); } - - /** - * Remove a rule from the list - */ - void remove(const RULE& rule) { m_rules.erase(rule); } - - /** - * Return the VPP assign handle - */ - const handle_t& handle() const { return (singular()->handle_i()); } - - static std::shared_ptr find(const handle_t& handle) - { - return (m_hdl_db[handle].lock()); - } - - static std::shared_ptr find(const key_t& key) - { - return (m_db.find(key)); - } - - static void add(const key_t& key, const HW::item& item) - { - std::shared_ptr sp = find(key); - - if (sp && item) { - m_hdl_db[item.data()] = sp; - } - } - - static void remove(const HW::item& item) - { - m_hdl_db.erase(item.data()); - } - - const key_t& key() const { return m_key; } - - const rules_t& rules() const { return m_rules; } - - /** - * Comparison operator - for UT - */ - bool operator==(const list& l) const - { - return (key() == l.key() && rules() == l.rules()); - } - -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() { m_db.replay(); } - - /** - * Show the object in the Singular DB - */ - void show(std::ostream& os); - - /** - * Get the sortable Id of the listener - */ - dependency_t order() const { return (dependency_t::ACL); } - }; - - /** - * event_handler to register with OM - */ - static event_handler m_evh; - - /** - * Enqueue commands to the VPP command Q for the update - */ - void update(const list& obj); - - /** - * HW assigned handle - */ - HW::item m_hdl; - - /** - * Find or add the sigular instance in the DB - */ - static std::shared_ptr find_or_add(const list& temp) - { - return (m_db.find_or_add(temp.key(), temp)); - } - - /** - * return the acl-list's handle in the singular instance - */ - const handle_t& handle_i() const { return (m_hdl.data()); } - - /* - * 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; - - /** - * 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 m_db; - - /** - * A map of all ACLs keyed against VPP's handle - */ - static std::map> 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; -}; - -/** - * Typedef the L3 ACL type - */ -typedef list l3_list; - -/** - * Typedef the L2 ACL type - */ -typedef list l2_list; - -/** - * Definition of the static singular_db for ACL Lists - */ -template -singular_db::key_t, ACL::list> list::m_db; - -/** - * Definition of the static per-handle DB for ACL Lists - */ -template -std::map>> list::m_hdl_db; - -template -typename ACL::list::event_handler list::m_evh; -}; -}; - -/* - * 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 +template class update_cmd : public rpc_cmd, UPDATE> { public: - typedef typename list::rules_t cmd_rules_t; - typedef typename list::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, UPDATE>::succeeded(); - list::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::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 +template class delete_cmd : public rpc_cmd, DELETE> { public: @@ -162,7 +163,7 @@ private: /** * remove the acl from the DB */ - void remove_acl() { list::remove(this->item()); } + void remove_acl() { LIST::remove(this->item()); } }; /** @@ -196,15 +197,15 @@ public: /** * Typedef the L3 ACL commands */ -typedef update_cmd l3_update_cmd; -typedef delete_cmd l3_delete_cmd; +typedef update_cmd l3_update_cmd; +typedef delete_cmd l3_delete_cmd; typedef dump_cmd l3_dump_cmd; /** * Typedef the L2 ACL commands */ -typedef update_cmd l2_update_cmd; -typedef delete_cmd l2_delete_cmd; +typedef update_cmd l2_update_cmd; +typedef delete_cmd l2_delete_cmd; typedef dump_cmd 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" -- cgit 1.2.3-korg