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