530a0aee6044eff2ecf074d7af8cf6b5ac635651
[vpp.git] / src / vpp-api / vom / acl_ethertype.cpp
1 /*
2  * Copyright (c) 2018 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include "vom/acl_ethertype.hpp"
17 #include "vom/acl_ethertype_cmds.hpp"
18
19 namespace VOM {
20 namespace ACL {
21
22 ethertype_rule_t::ethertype_rule_t(const ethertype_t& eth,
23                                    const direction_t& dir)
24   : m_eth(eth)
25   , m_dir(dir)
26 {
27 }
28
29 std::string
30 ethertype_rule_t::to_string() const
31 {
32   std::ostringstream s;
33
34   s << "["
35     << "ethertype:" << m_eth.to_string() << " dir:" << m_dir.to_string()
36     << "],";
37
38   return (s.str());
39 }
40
41 bool
42 ethertype_rule_t::operator<(const ethertype_rule_t& other) const
43 {
44   return (m_dir > other.m_dir);
45 }
46
47 bool
48 ethertype_rule_t::operator==(const ethertype_rule_t& other) const
49 {
50   return (m_dir == other.m_dir && m_eth == other.m_eth);
51 }
52
53 uint16_t
54 ethertype_rule_t::getEthertype() const
55 {
56   return m_eth.value();
57 }
58
59 const direction_t&
60 ethertype_rule_t::getDirection() const
61 {
62   return m_dir;
63 }
64
65 /**
66  * A DB of all acl ethertype bindings configs
67  */
68 singular_db<interface::key_t, acl_ethertype> acl_ethertype::m_db;
69
70 acl_ethertype::event_handler acl_ethertype::m_evh;
71
72 acl_ethertype::acl_ethertype(const interface& itf,
73                              const acl_ethertype::ethertype_rules_t& le)
74   : m_itf(itf.singular())
75   , m_le(le)
76   , m_binding(true)
77 {
78 }
79
80 acl_ethertype::acl_ethertype(const acl_ethertype& o)
81   : m_itf(o.m_itf)
82   , m_le(o.m_le)
83   , m_binding(o.m_binding)
84 {
85 }
86
87 acl_ethertype::~acl_ethertype()
88 {
89   sweep();
90
91   // not in the DB anymore.
92   m_db.release(m_itf->key(), this);
93 }
94
95 void
96 acl_ethertype::sweep()
97 {
98   if (m_binding) {
99     HW::enqueue(new acl_ethertype_cmds::unbind_cmd(m_binding, m_itf->handle()));
100   }
101   HW::write();
102 }
103
104 const acl_ethertype::key_t&
105 acl_ethertype::key() const
106 {
107   return (m_itf->key());
108 }
109
110 bool
111 acl_ethertype::operator==(const acl_ethertype& other) const
112 {
113   return (m_itf->key() == other.m_itf->key() && m_le == other.m_le);
114 }
115
116 std::shared_ptr<acl_ethertype>
117 acl_ethertype::find(const key_t& key)
118 {
119   return (m_db.find(key));
120 }
121
122 void
123 acl_ethertype::dump(std::ostream& os)
124 {
125   m_db.dump(os);
126 }
127
128 void
129 acl_ethertype::replay()
130 {
131   if (m_binding) {
132     HW::enqueue(
133       new acl_ethertype_cmds::bind_cmd(m_binding, m_itf->handle(), m_le));
134   }
135 }
136
137 std::string
138 acl_ethertype::to_string() const
139 {
140   std::ostringstream s;
141   s << "Acl-Ethertype:" << m_itf->to_string() << " ethertype-rules:";
142   auto it = m_le.cbegin();
143   while (it != m_le.cend()) {
144     s << it->to_string();
145     ++it;
146   }
147   s << " rules-size:" << m_le.size();
148
149   return (s.str());
150 }
151
152 void
153 acl_ethertype::update(const acl_ethertype& desired)
154 {
155   /*
156    * always update the instance with the latest rules
157    */
158   if (!m_binding || desired.m_le != m_le) {
159     HW::enqueue(
160       new acl_ethertype_cmds::bind_cmd(m_binding, m_itf->handle(), m_le));
161   }
162
163   m_le = desired.m_le;
164 }
165
166 std::shared_ptr<acl_ethertype>
167 acl_ethertype::find_or_add(const acl_ethertype& temp)
168 {
169   return (m_db.find_or_add(temp.m_itf->key(), temp));
170 }
171
172 std::shared_ptr<acl_ethertype>
173 acl_ethertype::singular() const
174 {
175   return find_or_add(*this);
176 }
177
178 acl_ethertype::event_handler::event_handler()
179 {
180   OM::register_listener(this);
181   inspect::register_handler({ "acl-ethertype" }, "ACL Ethertype bindings",
182                             this);
183 }
184
185 void
186 acl_ethertype::event_handler::handle_replay()
187 {
188   m_db.replay();
189 }
190
191 void
192 acl_ethertype::event_handler::handle_populate(const client_db::key_t& key)
193 {
194   /*
195    * dump VPP acl ethertypes
196    */
197   std::shared_ptr<acl_ethertype_cmds::dump_cmd> cmd =
198     std::make_shared<acl_ethertype_cmds::dump_cmd>(~0);
199
200   HW::enqueue(cmd);
201   HW::write();
202
203   for (auto& record : *cmd) {
204     auto& payload = record.get_payload();
205     handle_t hdl(payload.sw_if_index);
206     std::shared_ptr<interface> itf = interface::find(hdl);
207     uint8_t n_input = payload.n_input;
208     uint8_t count = payload.count;
209     ethertype_rules_t ler;
210     if (itf) {
211       for (int i = 0; i < count; i++) {
212         ethertype_t e = ethertype_t::from_numeric_val(payload.whitelist[i]);
213         if (n_input) {
214           ethertype_rule_t er(e, direction_t::INPUT);
215           ler.insert(er);
216           n_input--;
217         } else {
218           ethertype_rule_t er(e, direction_t::OUTPUT);
219           ler.insert(er);
220         }
221       }
222       if (!ler.empty()) {
223         acl_ethertype a_e(*itf, ler);
224         VOM_LOG(log_level_t::DEBUG) << "ethertype dump: " << a_e.to_string();
225         OM::commit(key, a_e);
226       }
227     }
228   }
229 }
230
231 dependency_t
232 acl_ethertype::event_handler::order() const
233 {
234   return (dependency_t::BINDING);
235 }
236
237 void
238 acl_ethertype::event_handler::show(std::ostream& os)
239 {
240   m_db.dump(os);
241 }
242 };
243 };
244 /*
245  * fd.io coding-style-patch-verification: ON
246  *
247  * Local Variables:
248  * eval: (c-set-style "mozilla")
249  * End:
250  */