summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vpp-api/vom/Makefile.am3
-rw-r--r--src/vpp-api/vom/acl_ethertype.cpp210
-rw-r--r--src/vpp-api/vom/acl_ethertype.hpp247
-rw-r--r--src/vpp-api/vom/acl_ethertype_cmds.cpp93
-rw-r--r--src/vpp-api/vom/acl_ethertype_cmds.hpp79
-rw-r--r--src/vpp-api/vom/types.cpp49
-rw-r--r--src/vpp-api/vom/types.hpp66
-rw-r--r--test/ext/vom_test.cpp16
8 files changed, 763 insertions, 0 deletions
diff --git a/src/vpp-api/vom/Makefile.am b/src/vpp-api/vom/Makefile.am
index 2cb7f837571..d2a3dde70c5 100644
--- a/src/vpp-api/vom/Makefile.am
+++ b/src/vpp-api/vom/Makefile.am
@@ -37,6 +37,8 @@ libvom_la_SOURCES = \
types.cpp \
acl_binding_cmds.cpp \
acl_binding.cpp \
+ acl_ethertype_cmds.cpp \
+ acl_ethertype.cpp \
acl_l2_rule.cpp \
acl_l3_rule.cpp \
acl_list_cmds.cpp \
@@ -110,6 +112,7 @@ vomincludedir = $(includedir)/vom
vominclude_HEADERS = \
acl_binding.hpp \
+ acl_ethertype.hpp \
acl_l2_rule.hpp \
acl_l3_rule.hpp \
acl_list.hpp \
diff --git a/src/vpp-api/vom/acl_ethertype.cpp b/src/vpp-api/vom/acl_ethertype.cpp
new file mode 100644
index 00000000000..2f0163398d0
--- /dev/null
+++ b/src/vpp-api/vom/acl_ethertype.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2018 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_ethertype.hpp"
+#include "vom/acl_ethertype_cmds.hpp"
+
+namespace VOM {
+namespace ACL {
+
+ethertype_rule_t::ethertype_rule_t(const ethertype_t& eth,
+ const direction_t& dir)
+ : m_eth(eth)
+ , m_dir(dir)
+{
+}
+
+std::string
+ethertype_rule_t::to_string() const
+{
+ std::ostringstream s;
+
+ s << "["
+ << "ethertype:" << m_eth.to_string() << " dir:" << m_dir.to_string()
+ << "],";
+
+ return (s.str());
+}
+
+bool
+ethertype_rule_t::operator<(const ethertype_rule_t& other) const
+{
+ return (m_dir > other.m_dir);
+}
+
+bool
+ethertype_rule_t::operator==(const ethertype_rule_t& other) const
+{
+ return (m_dir == other.m_dir && m_eth == other.m_eth);
+}
+
+uint16_t
+ethertype_rule_t::getEthertype() const
+{
+ return m_eth.value();
+}
+
+const direction_t&
+ethertype_rule_t::getDirection() const
+{
+ return m_dir;
+}
+
+/**
+ * A DB of all acl ethertype bindings configs
+ */
+singular_db<interface::key_t, acl_ethertype> acl_ethertype::m_db;
+
+acl_ethertype::event_handler acl_ethertype::m_evh;
+
+acl_ethertype::acl_ethertype(const interface& itf,
+ acl_ethertype::ethertype_rules_t le)
+ : m_itf(itf.singular())
+ , m_le(le)
+ , m_binding(true)
+{
+}
+
+acl_ethertype::acl_ethertype(const acl_ethertype& o)
+ : m_itf(o.m_itf)
+ , m_le(o.m_le)
+ , m_binding(o.m_binding)
+{
+}
+
+acl_ethertype::~acl_ethertype()
+{
+ sweep();
+
+ // not in the DB anymore.
+ m_db.release(m_itf->key(), this);
+}
+
+void
+acl_ethertype::sweep()
+{
+}
+
+const acl_ethertype::key_t&
+acl_ethertype::key() const
+{
+ return (m_itf->key());
+}
+
+bool
+acl_ethertype::operator==(const acl_ethertype& other) const
+{
+ return (m_itf->key() == other.m_itf->key() && m_le == other.m_le);
+}
+
+std::shared_ptr<acl_ethertype>
+acl_ethertype::find(const key_t& key)
+{
+ return (m_db.find(key));
+}
+
+void
+acl_ethertype::dump(std::ostream& os)
+{
+ m_db.dump(os);
+}
+
+void
+acl_ethertype::replay()
+{
+ if (m_binding) {
+ HW::enqueue(
+ new acl_ethertype_cmds::bind_cmd(m_binding, m_itf->handle(), m_le));
+ }
+}
+
+std::string
+acl_ethertype::to_string() const
+{
+ std::ostringstream s;
+ s << "Acl-Ethertype:" << m_itf->to_string() << " ethertype-rules:";
+ auto it = m_le.cbegin();
+ while (it != m_le.cend()) {
+ s << it->to_string();
+ ++it;
+ }
+ s << " rules-size:" << m_le.size();
+
+ return (s.str());
+}
+
+void
+acl_ethertype::update(const acl_ethertype& old)
+{
+ /*
+ * always update the instance with the latest rules
+ */
+ if (!m_binding || old.m_le != m_le) {
+ HW::enqueue(
+ new acl_ethertype_cmds::bind_cmd(m_binding, m_itf->handle(), m_le));
+ }
+}
+
+std::shared_ptr<acl_ethertype>
+acl_ethertype::find_or_add(const acl_ethertype& temp)
+{
+ return (m_db.find_or_add(temp.m_itf->key(), temp));
+}
+
+std::shared_ptr<acl_ethertype>
+acl_ethertype::singular() const
+{
+ return find_or_add(*this);
+}
+
+acl_ethertype::event_handler::event_handler()
+{
+ OM::register_listener(this);
+ inspect::register_handler({ "acl-ethertype" }, "ACL Ethertype bindings",
+ this);
+}
+
+void
+acl_ethertype::event_handler::handle_replay()
+{
+ m_db.replay();
+}
+
+void
+acl_ethertype::event_handler::handle_populate(const client_db::key_t& key)
+{
+ // FIXME
+}
+
+dependency_t
+acl_ethertype::event_handler::order() const
+{
+ return (dependency_t::BINDING);
+}
+
+void
+acl_ethertype::event_handler::show(std::ostream& os)
+{
+ m_db.dump(os);
+}
+};
+};
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
diff --git a/src/vpp-api/vom/acl_ethertype.hpp b/src/vpp-api/vom/acl_ethertype.hpp
new file mode 100644
index 00000000000..42897aebd6a
--- /dev/null
+++ b/src/vpp-api/vom/acl_ethertype.hpp
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2018 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_ETHERTYPE_H__
+#define __VOM_ACL_ETHERTYPE_H__
+
+#include <set>
+
+#include "vom/hw.hpp"
+#include "vom/inspect.hpp"
+#include "vom/interface.hpp"
+#include "vom/object_base.hpp"
+#include "vom/om.hpp"
+#include "vom/singular_db.hpp"
+
+namespace VOM {
+namespace ACL {
+/**
+ * An ACL ethertype list comprises a set of inbound ether types and out bound
+ * ether types
+ * to be applied to packets.
+ * A list is bound to a given interface.
+ */
+
+struct ethertype_rule_t
+{
+public:
+ /**
+ * Constructor
+ */
+ ethertype_rule_t(const ethertype_t& eth, const direction_t& dir);
+
+ /**
+ * Destructor
+ */
+ ~ethertype_rule_t() = default;
+
+ /**
+ * convert to string
+ */
+ std::string to_string() const;
+
+ /**
+ * comparision operator
+ */
+ bool operator<(const ethertype_rule_t& other) const;
+
+ /**
+ * comparision operator (for testing)
+ */
+ bool operator==(const ethertype_rule_t& other) const;
+
+ /**
+ * get the ether value
+ */
+ uint16_t getEthertype(void) const;
+
+ /**
+ * get the direction
+ */
+ const direction_t& getDirection(void) const;
+
+private:
+ /**
+ * ethertype for this rule
+ */
+ const ethertype_t& m_eth;
+
+ /**
+ * direction in which ethertype will be applied w.r.t. intf
+ */
+ const direction_t& m_dir;
+};
+
+class acl_ethertype : public object_base
+{
+public:
+ /**
+ * The KEY can be used to uniquely identify the ACL ethertype.
+ * (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 ethertype container
+ */
+ typedef std::multiset<ethertype_rule_t> ethertype_rules_t;
+
+ /**
+ * Construct a new object matching the desried state
+ */
+ acl_ethertype(const interface& itf, ethertype_rules_t le);
+
+ /**
+ * Copy Constructor
+ */
+ acl_ethertype(const acl_ethertype& o);
+
+ /**
+ * Destructor
+ */
+ ~acl_ethertype();
+
+ /**
+ * Return the binding's key
+ */
+ const key_t& key() const;
+
+ /**
+ * comparision operator (for testing)
+ */
+ bool operator==(const acl_ethertype& o) const;
+
+ /**
+ * Return the 'singular' of the acl ethertype that matches this object
+ */
+ std::shared_ptr<acl_ethertype> singular() const;
+
+ /**
+ * convert to string format for debug purposes
+ */
+ std::string to_string() const;
+
+ /**
+ * Dump all acl ethertype into the stream provided
+ */
+ static void dump(std::ostream& os);
+
+ /**
+ * Static function to find the acl_ethertype in the model
+ */
+ static std::shared_ptr<acl_ethertype> find(const key_t& key);
+
+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;
+
+ /**
+ * Enque commands to the VPP command Q for the update
+ */
+ void update(const acl_ethertype& obj);
+
+ /**
+ * Find or add acl ethertype to the OM
+ */
+ static std::shared_ptr<acl_ethertype> find_or_add(const acl_ethertype& temp);
+
+ /*
+ * It's the OM class that calls singular()
+ */
+ friend class VOM::OM;
+
+ /**
+ * It's the singular_db class that calls replay()
+ */
+ friend class singular_db<interface::key_t, acl_ethertype>;
+
+ /**
+ * Sweep/reap the object if still stale
+ */
+ void sweep(void);
+
+ /**
+ * replay the object to create it in hardware
+ */
+ void replay(void);
+
+ /**
+ * A reference counting pointer to the interface on which acl ethertype
+ * resides. By holding the reference here, we can guarantee that
+ * this object will outlive the interface
+ */
+ const std::shared_ptr<interface> m_itf;
+
+ /**
+ * Inbound and outbound ethers list applied on given interface
+ */
+ ethertype_rules_t m_le;
+
+ /**
+ * HW configuration for the binding. The bool representing the
+ * do/don't bind.
+ */
+ HW::item<bool> m_binding;
+
+ /**
+ * A map of all acl ethertype keyed against the interface.
+ */
+ static singular_db<interface::key_t, acl_ethertype> m_db;
+};
+};
+};
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
+
+#endif
diff --git a/src/vpp-api/vom/acl_ethertype_cmds.cpp b/src/vpp-api/vom/acl_ethertype_cmds.cpp
new file mode 100644
index 00000000000..91fc7ee6b01
--- /dev/null
+++ b/src/vpp-api/vom/acl_ethertype_cmds.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2018 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_ethertype_cmds.hpp"
+
+namespace VOM {
+namespace ACL {
+namespace acl_ethertype_cmds {
+
+bind_cmd::bind_cmd(HW::item<bool>& item,
+ const handle_t& itf,
+ const acl_ethertype::ethertype_rules_t& le)
+ : rpc_cmd(item)
+ , m_itf(itf)
+ , m_le(le)
+{
+}
+
+bool
+bind_cmd::operator==(const bind_cmd& other) const
+{
+ return (m_itf == other.m_itf && m_le == other.m_le);
+}
+
+rc_t
+bind_cmd::issue(connection& con)
+{
+ msg_t req(con.ctx(), m_le.size(), std::ref(*this));
+ uint32_t i = 0;
+ uint8_t n_input = 0;
+
+ auto& payload = req.get_request().get_payload();
+ payload.sw_if_index = m_itf.value();
+ payload.count = m_le.size();
+
+ auto it = m_le.cbegin();
+ while (it != m_le.cend()) {
+ payload.whitelist[i] = it->getEthertype();
+ if (it->getDirection() == direction_t::INPUT)
+ n_input++;
+ ++it;
+ ++i;
+ }
+
+ payload.n_input = n_input;
+
+ VAPI_CALL(req.execute());
+
+ m_hw_item.set(wait());
+
+ return rc_t::OK;
+}
+
+std::string
+bind_cmd::to_string() const
+{
+ std::ostringstream s;
+ s << "ACL-Ethertype: " << m_hw_item.to_string()
+ << " itf:" << m_itf.to_string() << " ethertype-rules:";
+ auto it = m_le.cbegin();
+ while (it != m_le.cend()) {
+ s << it->to_string();
+ ++it;
+ }
+
+ s << " rules-size:" << m_le.size();
+
+ return (s.str());
+}
+
+}; // namespace acl_ethertype_cmds
+}; // namespace ACL
+}; // namespace VOM
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
diff --git a/src/vpp-api/vom/acl_ethertype_cmds.hpp b/src/vpp-api/vom/acl_ethertype_cmds.hpp
new file mode 100644
index 00000000000..a0af50e8297
--- /dev/null
+++ b/src/vpp-api/vom/acl_ethertype_cmds.hpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2018 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_ETHERTYPE_CMDS_H__
+#define __VOM_ACL_ETHERTYPE_CMDS_H__
+
+#include "vom/acl_ethertype.hpp"
+#include "vom/dump_cmd.hpp"
+#include "vom/rpc_cmd.hpp"
+
+#include <vapi/acl.api.vapi.hpp>
+
+namespace VOM {
+namespace ACL {
+namespace acl_ethertype_cmds {
+/**
+ * A command class that binds the ethertype list to the interface
+ */
+class bind_cmd : public rpc_cmd<HW::item<bool>,
+ rc_t,
+ vapi::Acl_interface_set_etype_whitelist>
+{
+public:
+ /**
+ * Constructor
+ */
+ bind_cmd(HW::item<bool>& item,
+ const handle_t& itf,
+ const acl_ethertype::ethertype_rules_t& le);
+
+ /**
+ * Issue the command to VPP/HW
+ */
+ rc_t issue(connection& con);
+ /**
+ * convert to string format for debug purposes
+ */
+ std::string to_string() const;
+
+ /**
+ * Comparison operator - only used for UT
+ */
+ bool operator==(const bind_cmd& i) const;
+
+private:
+ /**
+ * Reference to the HW::item of the interface to bind
+ */
+ const handle_t& m_itf;
+
+ /**
+ * Ethertype list applied to interface
+ */
+ const acl_ethertype::ethertype_rules_t& m_le;
+};
+};
+};
+};
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
+
+#endif
diff --git a/src/vpp-api/vom/types.cpp b/src/vpp-api/vom/types.cpp
index 4f8884615e2..82f0aec20b2 100644
--- a/src/vpp-api/vom/types.cpp
+++ b/src/vpp-api/vom/types.cpp
@@ -274,6 +274,55 @@ operator<<(std::ostream& os, const direction_t& dir)
return os;
}
+const ethertype_t ethertype_t::ARP(0x0806, "arp");
+const ethertype_t ethertype_t::FCOE(0x8906, "fcoe");
+const ethertype_t ethertype_t::IPV4(0x0800, "ipv4");
+const ethertype_t ethertype_t::IPV6(0x86DD, "ipv6");
+const ethertype_t ethertype_t::MAC_SECURITY(0x88E5, "mac-security");
+const ethertype_t ethertype_t::MPLS_UNICAST(0x8847, "mpls-unicast");
+const ethertype_t ethertype_t::TRILL(0x22F3, "trill");
+const ethertype_t ethertype_t::UNSPECIFIED(0x0, "unspecified");
+
+ethertype_t::ethertype_t(int v, const std::string s)
+ : enum_base(v, s)
+{
+}
+
+std::ostream&
+operator<<(std::ostream& os, const ethertype_t& ether)
+{
+ os << ether.to_string();
+ return os;
+}
+
+const ethertype_t&
+ethertype_t::from_numeric_val(uint16_t numeric)
+{
+ if (0x0806 == numeric) {
+ return (ethertype_t::ARP);
+ }
+ if (0x8906 == numeric) {
+ return (ethertype_t::FCOE);
+ }
+ if (0x0800 == numeric) {
+ return (ethertype_t::IPV4);
+ }
+ if (0x86DD == numeric) {
+ return (ethertype_t::IPV6);
+ }
+ if (0x88E5 == numeric) {
+ return (ethertype_t::MAC_SECURITY);
+ }
+ if (0x8847 == numeric) {
+ return (ethertype_t::MPLS_UNICAST);
+ }
+ if (0x22F3 == numeric) {
+ return (ethertype_t::TRILL);
+ }
+
+ return (ethertype_t::UNSPECIFIED);
+}
+
}; // namespace VOM
/*
diff --git a/src/vpp-api/vom/types.hpp b/src/vpp-api/vom/types.hpp
index 4deb6c489a6..8543a6604bb 100644
--- a/src/vpp-api/vom/types.hpp
+++ b/src/vpp-api/vom/types.hpp
@@ -159,6 +159,72 @@ struct direction_t : public enum_base<direction_t>
std::ostream& operator<<(std::ostream& os, const direction_t& dir);
/**
+ * Feature Ethertype
+ */
+struct ethertype_t : public enum_base<ethertype_t>
+{
+ /**
+ * Constructor
+ */
+ ethertype_t(int v, const std::string s);
+
+ /**
+ * Destructor
+ */
+ ~ethertype_t() = default;
+
+ /**
+ * Ethertype Arp
+ */
+ const static ethertype_t ARP;
+
+ /**
+ * Ethertype FCoE
+ */
+ const static ethertype_t FCOE;
+
+ /**
+ * Ethertype IPv4
+ */
+ const static ethertype_t IPV4;
+
+ /**
+ * Ethertype Ipv6
+ */
+ const static ethertype_t IPV6;
+
+ /**
+ * Ethertype MAC Security
+ */
+ const static ethertype_t MAC_SECURITY;
+
+ /**
+ * Ethertype MPLS unicast
+ */
+ const static ethertype_t MPLS_UNICAST;
+
+ /**
+ * Ethertype TRILL
+ */
+ const static ethertype_t TRILL;
+
+ /**
+ * Ethertype Unspecified
+ */
+ const static ethertype_t UNSPECIFIED;
+
+ /**
+ * Get the ethertype from the numeric value
+ */
+ static const ethertype_t& from_numeric_val(uint16_t numeric);
+};
+
+/**
+ * Output ostream for ethertype_t
+ */
+std::ostream& operator<<(std::ostream& os, const ethertype_t& eth);
+
+/**
* A type declaration of an interface handle in VPP
*/
struct handle_t
diff --git a/test/ext/vom_test.cpp b/test/ext/vom_test.cpp
index 0a687c5017c..d9bd67984f1 100644
--- a/test/ext/vom_test.cpp
+++ b/test/ext/vom_test.cpp
@@ -39,6 +39,8 @@
#include "vom/vxlan_tunnel_cmds.hpp"
#include "vom/sub_interface.hpp"
#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_binding.hpp"
#include "vom/acl_list_cmds.hpp"
@@ -280,6 +282,10 @@ public:
{
rc = handle_derived<sub_interface_cmds::delete_cmd>(f_exp, f_act);
}
+ else if (typeid(*f_exp) == typeid(ACL::acl_ethertype_cmds::bind_cmd))
+ {
+ rc = handle_derived<ACL::acl_ethertype_cmds::bind_cmd>(f_exp, f_act);
+ }
else if (typeid(*f_exp) == typeid(ACL::list_cmds::l3_update_cmd))
{
rc = handle_derived<ACL::list_cmds::l3_update_cmd>(f_exp, f_act);
@@ -984,6 +990,15 @@ BOOST_AUTO_TEST_CASE(test_acl) {
ADD_EXPECT(interface_cmds::state_change_cmd(hw_as_up, hw_ifh));
TRY_CHECK_RC(OM::write(fyodor, itf1));
+ ACL::ethertype_rule_t e1(ethertype_t::ARP, direction_t::INPUT);
+ ACL::ethertype_rule_t e2(ethertype_t::ARP, direction_t::OUTPUT);
+ ACL::ethertype_rule_t e3(ethertype_t::IPV4, direction_t::INPUT);
+ ACL::acl_ethertype::ethertype_rules_t l_e = {e1, e2, e3};
+ ACL::acl_ethertype *a_e = new ACL::acl_ethertype(itf1, l_e);
+ HW::item<bool> ae_binding(true, rc_t::OK);
+ ADD_EXPECT(ACL::acl_ethertype_cmds::bind_cmd(ae_binding, hw_ifh.data(), l_e));
+ TRY_CHECK_RC(OM::write(fyodor, *a_e));
+
route::prefix_t src("10.10.10.10", 32);
ACL::l3_rule r1(10, ACL::action_t::PERMIT, src, route::prefix_t::ZERO);
ACL::l3_rule r2(20, ACL::action_t::DENY, route::prefix_t::ZERO, route::prefix_t::ZERO);
@@ -1038,6 +1053,7 @@ BOOST_AUTO_TEST_CASE(test_acl) {
TRY_CHECK(OM::remove(leo));
delete l3b;
+ delete a_e;
HW::item<interface::admin_state_t> hw_as_down(interface::admin_state_t::DOWN,
rc_t::OK);
STRICT_ORDER_OFF();