GBP: add allowed ethertypes to contracts
[vpp.git] / extras / vom / vom / acl_list.hpp
1 /*
2  * Copyright (c) 2017 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 #ifndef __VOM_ACL_LIST_H__
17 #define __VOM_ACL_LIST_H__
18
19 #include <set>
20
21 #include "vom/acl_l2_rule.hpp"
22 #include "vom/acl_l3_rule.hpp"
23 #include "vom/acl_types.hpp"
24 #include "vom/hw.hpp"
25 #include "vom/inspect.hpp"
26 #include "vom/om.hpp"
27 #include "vom/singular_db.hpp"
28
29 namespace VOM {
30 namespace ACL {
31 /**
32  * An ACL list comprises a set of match actions rules to be applied to
33  * packets.
34  * A list is bound to a given interface.
35  */
36 template <typename RULE>
37 class list : public object_base
38 {
39 public:
40   /**
41    * The KEY can be used to uniquely identify the ACL.
42    * (other choices for keys, like the summation of the properties
43    * of the rules, are rather too cumbersome to use
44    */
45   typedef std::string key_t;
46
47   /**
48    * The rule container type
49    */
50   typedef std::multiset<RULE> rules_t;
51
52   /**
53    * Construct a new object matching the desried state
54    */
55   list(const key_t& key)
56     : m_hdl(handle_t::INVALID)
57     , m_key(key)
58   {
59   }
60
61   list(const handle_t& hdl, const key_t& key)
62     : m_hdl(hdl)
63     , m_key(key)
64   {
65   }
66
67   list(const key_t& key, const rules_t& rules)
68     : m_hdl(handle_t::INVALID)
69     , m_key(key)
70     , m_rules(rules)
71   {
72   }
73
74   /**
75    * Copy Constructor
76    */
77   list(const list& o)
78     : m_hdl(o.m_hdl)
79     , m_key(o.m_key)
80     , m_rules(o.m_rules)
81   {
82   }
83
84   /**
85    * Destructor
86    */
87   ~list()
88   {
89     sweep();
90     m_db.release(m_key, this);
91   }
92
93   /**
94    * Return the 'sigular instance' of the ACL that matches this object
95    */
96   std::shared_ptr<list> singular() const { return find_or_add(*this); }
97
98   /**
99    * Dump all ACLs into the stream provided
100    */
101   static void dump(std::ostream& os) { m_db.dump(os); }
102
103   /**
104    * convert to string format for debug purposes
105    */
106   std::string to_string() const
107   {
108     std::ostringstream s;
109     s << "acl-list:[" << m_key << " " << m_hdl.to_string() << " rules:[";
110
111     for (auto rule : m_rules) {
112       s << rule.to_string() << " ";
113     }
114
115     s << "]]";
116
117     return (s.str());
118   }
119
120   /**
121    * Insert priority sorted a rule into the list
122    */
123   void insert(const RULE& rule) { m_rules.insert(rule); }
124
125   /**
126    * Remove a rule from the list
127    */
128   void remove(const RULE& rule) { m_rules.erase(rule); }
129
130   /**
131    * Return the VPP assign handle
132    */
133   const handle_t& handle() const { return (singular()->handle_i()); }
134
135   static std::shared_ptr<list> find(const handle_t& handle)
136   {
137     return (m_hdl_db[handle].lock());
138   }
139
140   static std::shared_ptr<list> find(const key_t& key)
141   {
142     return (m_db.find(key));
143   }
144
145   static void add(const key_t& key, const HW::item<handle_t>& item)
146   {
147     std::shared_ptr<list> sp = find(key);
148
149     if (sp && item) {
150       m_hdl_db[item.data()] = sp;
151     }
152   }
153
154   static void remove(const HW::item<handle_t>& item)
155   {
156     m_hdl_db.erase(item.data());
157   }
158
159   const key_t& key() const { return m_key; }
160
161   const rules_t& rules() const { return m_rules; }
162
163   /**
164    * Comparison operator - for UT
165    */
166   bool operator==(const list& l) const
167   {
168     return (key() == l.key() && rules() == l.rules());
169   }
170
171 private:
172   /**
173    * Class definition for listeners to OM events
174    */
175   class event_handler : public OM::listener, public inspect::command_handler
176   {
177   public:
178     event_handler();
179
180     virtual ~event_handler() = default;
181
182     /**
183      * Handle a populate event
184      */
185     void handle_populate(const client_db::key_t& key);
186
187     /**
188      * Handle a replay event
189      */
190     void handle_replay() { m_db.replay(); }
191
192     /**
193      * Show the object in the Singular DB
194      */
195     void show(std::ostream& os);
196
197     /**
198      * Get the sortable Id of the listener
199      */
200     dependency_t order() const { return (dependency_t::ACL); }
201   };
202
203   /**
204    * event_handler to register with OM
205    */
206   static event_handler m_evh;
207
208   /**
209    * Enqueue commands to the VPP command Q for the update
210    */
211   void update(const list& obj);
212
213   /**
214    * HW assigned handle
215    */
216   HW::item<handle_t> m_hdl;
217
218   /**
219    * Find or add the sigular instance in the DB
220    */
221   static std::shared_ptr<list> find_or_add(const list& temp)
222   {
223     return (m_db.find_or_add(temp.key(), temp));
224   }
225
226   /**
227    * return the acl-list's handle in the singular instance
228    */
229   const handle_t& handle_i() const { return (m_hdl.data()); }
230
231   /*
232    * It's the VOM::OM class that updates call update
233    */
234   friend class VOM::OM;
235
236   /**
237    * It's the VOM::singular_db class that calls replay()
238    */
239   friend class singular_db<key_t, list>;
240
241   /**
242    * Sweep/reap the object if still stale
243    */
244   void sweep(void);
245
246   /**
247    * Replay the objects state to HW
248    */
249   void replay(void);
250
251   /**
252    * A map of all ACL's against the client's key
253    */
254   static singular_db<key_t, list> m_db;
255
256   /**
257    * A map of all ACLs keyed against VPP's handle
258    */
259   static std::map<handle_t, std::weak_ptr<list>> m_hdl_db;
260
261   /**
262    * The Key is a user defined identifer for this ACL
263    */
264   const key_t m_key;
265
266   /**
267    * A sorted list of the rules
268    */
269   rules_t m_rules;
270 };
271
272 /**
273  * Typedef the L3 ACL type
274  */
275 typedef list<l3_rule> l3_list;
276
277 /**
278  * Typedef the L2 ACL type
279  */
280 typedef list<l2_rule> l2_list;
281
282 /**
283  * Definition of the static singular_db for ACL Lists
284  */
285 template <typename RULE>
286 singular_db<typename ACL::list<RULE>::key_t, ACL::list<RULE>> list<RULE>::m_db;
287
288 /**
289  * Definition of the static per-handle DB for ACL Lists
290  */
291 template <typename RULE>
292 std::map<handle_t, std::weak_ptr<ACL::list<RULE>>> list<RULE>::m_hdl_db;
293
294 template <typename RULE>
295 typename ACL::list<RULE>::event_handler list<RULE>::m_evh;
296 };
297 };
298
299 /*
300  * fd.io coding-style-patch-verification: ON
301  *
302  * Local Variables:
303  * eval: (c-set-style "mozilla")
304  * End:
305  */
306
307 #endif