blob: 4c7f3915cf298e57dc0719fbcb4b3040a944c867 [file] [log] [blame]
Neale Ranns812ed392017-10-16 04:20:13 -07001/*
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_INTERFACE_IP6_ND_H__
17#define __VOM_INTERFACE_IP6_ND_H__
18
19#include "vom/dump_cmd.hpp"
20#include "vom/hw.hpp"
21#include "vom/inspect.hpp"
22#include "vom/interface.hpp"
23#include "vom/object_base.hpp"
24#include "vom/om.hpp"
25#include "vom/ra_config.hpp"
26#include "vom/ra_prefix.hpp"
27#include "vom/rpc_cmd.hpp"
28#include "vom/singular_db.hpp"
29#include "vom/sub_interface.hpp"
30
Neale Ranns812ed392017-10-16 04:20:13 -070031namespace VOM {
32/**
33 * A representation of L3 configuration on an interface
34 */
35template <typename CLASS, typename CMD>
36class interface_ip6_nd : public object_base
37{
38public:
39 typedef CLASS class_t;
40 /**
41 * Construct a new object matching the desried state
42 */
43 interface_ip6_nd(const interface& itf, const class_t cls)
44 : m_itf(itf.singular())
45 , m_cls(cls)
46 , m_config(true)
47 {
48 }
49
50 /**
51 * Copy Constructor
52 */
53 interface_ip6_nd(const interface_ip6_nd& o)
54 : m_itf(o.m_itf)
55 , m_cls(o.m_cls)
56 , m_config(o.m_config)
57 {
58 }
59
60 /**
61 * Destructor
62 */
63 ~interface_ip6_nd()
64 {
65 sweep();
66 m_db.release(m_itf->key(), this);
67 }
68
69 /**
70 * Return the 'singular instance' of the interface ip6nd that matches
71 * this object
72 */
73 std::shared_ptr<interface_ip6_nd> singular() const
74 {
75 return find_or_add(*this);
76 }
77
78 /**
79 * convert to string format for debug purposes
80 */
81 std::string to_string() const
82 {
83 std::ostringstream s;
84 s << "interface-ip6-nd:["
85 << " itf:" << m_itf->to_string() << " " << m_cls.to_string() << " "
86 << m_config.to_string() << "]";
87
88 return (s.str());
89 }
90
91 /**
92 * Dump all config into the stream provided
93 */
94 static void dump(std::ostream& os) { m_db.dump(os); }
95
96 /**
97 * The key type for interface ip6 nd
98 */
99 typedef interface::key_type key_t;
100
101 /**
102 * Find an singular instance in the DB for the interface passed
103 */
104 static std::shared_ptr<interface_ip6_nd> find(const interface& i)
105 {
106 /*
107 * Loop throught the entire map looking for matching interface.
108 * not the most efficient algorithm, but it will do for now. The
109 * number of ra configs is low.
110 */
111 std::deque<std::shared_ptr<interface_ip6_nd>> rac;
112
113 auto it = m_db.cbegin();
114
115 while (it != m_db.cend()) {
116 /*
117 * The key in the DB is a pair of the interface's name.
118 * If the keys match, save the ra-config
119 */
120 auto key = it->first;
121
122 if (i.key() == key.first) {
123 rac.push_back(it->second.lock());
124 }
125
126 ++it;
127 }
128
129 return (rac);
130 }
131
132 /**
133 * A functor class that binds the ra config to the interface
134 */
135 class config_cmd : public rpc_cmd<HW::item<bool>, rc_t, CMD>
136 {
137 public:
138 /**
139 * Constructor
140 */
141 config_cmd(HW::item<bool>& item, const handle_t& itf, const class_t& cls)
142 : rpc_cmd<HW::item<bool>, rc_t, CMD>(item)
143 , m_itf(itf)
144 , m_cls(cls)
145 {
146 }
147
148 /**
149 * Issue the command to VPP/HW
150 */
151 rc_t issue(connection& con);
152
153 /**
154 * convert to string format for debug purposes
155 */
156 std::string to_string() const
157 {
158 std::ostringstream s;
159 s << "interface-ip6-nd: " << this->item().to_string()
160 << " itf:" << m_itf.to_string() << " " << m_cls.to_string();
161
162 return (s.str());
163 }
164
165 /**
166 * Comparison operator - only used for UT
167 */
168 bool operator==(const config_cmd& other) const
169 {
170 return ((m_itf == other.m_itf) && (m_cls == other.m_cls));
171 }
172
173 private:
174 /**
175 * Reference to the interface to bind to
176 */
177 const handle_t& m_itf;
178
179 /**
180 * Reference to the config class
181 */
182 const class_t& m_cls;
183 };
184
185 /**
186 * A cmd class that Unbinds L3 Config from an interface
187 */
188 class unconfig_cmd : public rpc_cmd<HW::item<bool>, rc_t, CMD>
189 {
190 public:
191 /**
192 * Constructor
193 */
194 unconfig_cmd(HW::item<bool>& item, const handle_t& itf, const class_t& cls)
195 : rpc_cmd<HW::item<bool>, rc_t, CMD>(item)
196 , m_itf(itf)
197 , m_cls(cls)
198 {
199 }
200
201 /**
202 * Issue the command to VPP/HW
203 */
204 rc_t issue(connection& con);
205
206 /**
207 * convert to string format for debug purposes
208 */
209 std::string to_string() const
210 {
211 std::ostringstream s;
212 s << "interface-ip6-nd: " << this->item().to_string()
213 << " itf:" << m_itf.to_string() << " " << m_cls.to_string();
214
215 return (s.str());
216 }
217
218 /**
219 * Comparison operator - only used for UT
220 */
221 bool operator==(const unconfig_cmd& other) const
222 {
223 return ((m_itf == other.m_itf) && (m_cls == other.m_cls));
224 }
225
226 private:
227 /**
228 * Reference to the interface to unbind fomr
229 */
230 const handle_t& m_itf;
231
232 /**
233 * Reference to the config class to undo configurations
234 */
235 const class_t& m_cls;
236 };
237
238private:
239 /**
240 * Class definition for listeners to OM events
241 */
242 class event_handler : public OM::listener, public inspect::command_handler
243 {
244 public:
245 event_handler()
246 {
247 OM::register_listener(this);
248 inspect::register_handler({ "ip6_nd " }, "interface ip6 nd", this);
249 }
250
251 virtual ~event_handler() = default;
252
253 /**
254 * Handle a populate event
255 */
256 void handle_populate(const client_db::key_t& key)
257 {
258 /**
259 * VPP provides no dump for ra config
260 */
261 }
262
263 /**
264 * Handle a replay event
265 */
266 void handle_replay() { m_db.replay(); }
267
268 /**
269 * Show the object in the Singular DB
270 */
271 void show(std::ostream& os) { m_db.dump(os); }
272
273 /**
274 * Get the sortable Id of the listener
275 */
276 dependency_t order() const { return (dependency_t::BINDING); }
277 };
278
279 /**
280 * event_handler to register with OM
281 */
282 static event_handler m_evh;
283
284 /**
285 * Enqueue commands to the VPP for the update
286 */
287 void update(const interface_ip6_nd& obj)
288 {
289 if (!m_config) {
290 HW::enqueue(new config_cmd(m_config, m_itf->handle(), m_cls));
291 }
292 }
293
294 void sweep()
295 {
296 if (m_config) {
297 HW::enqueue(new unconfig_cmd(m_config, m_itf->handle(), m_cls));
298 }
299 HW::write();
300 }
301
302 /**
303 * Replay the objects state to HW
304 */
305 void replay(void)
306 {
307 if (m_config) {
308 HW::enqueue(new config_cmd(m_config, m_itf->handle(), m_cls));
309 }
310 }
311
312 /**
313 * Find or add the singular instance in the DB
314 */
315 static std::shared_ptr<interface_ip6_nd> find_or_add(
316 const interface_ip6_nd& temp)
317 {
318 return (m_db.find_or_add(temp.m_itf->key(), temp));
319 }
320
321 /*
322 * It's the VPPHW class that updates the objects in HW
323 */
324 friend class OM;
325
326 /**
327 * It's the singular_db class that calls replay()
328 */
329 friend class singular_db<key_t, interface_ip6_nd>;
330
331 const std::shared_ptr<interface> m_itf;
332
333 const class_t m_cls;
334
335 const key_t m_key;
336
337 /**
338 * HW configuration for the binding. The bool representing the
339 * do/don't bind.
340 */
341 HW::item<bool> m_config;
342
343 /**
344 * A map of all interface ip6 nd keyed against a combination of the
345 * interface and subnet's keys.
346 */
347 static singular_db<key_t, interface_ip6_nd> m_db;
348};
349
350/**
351 * Typedef the ip6nd_ra_config
352 */
353typedef interface_ip6_nd<ra_config, vapi::Sw_interface_ip6nd_ra_config>
354 ip6nd_ra_config;
355
356/**
357 * Typedef the ip6nd_ra_prefix
358 */
359typedef interface_ip6_nd<ra_prefix, vapi::Sw_interface_ip6nd_ra_prefix>
360 ip6nd_ra_prefix;
361
362/**
363 * Definition of the static singular_db for ACL Lists
364 */
365template <typename CLASS, typename CMD>
366singular_db<typename interface_ip6_nd<CLASS, CMD>::key_t,
367 interface_ip6_nd<CLASS, CMD>>
368 interface_ip6_nd<CLASS, CMD>::m_db;
369
370template <typename CLASS, typename CMD>
371typename interface_ip6_nd<CLASS, CMD>::event_handler
372 interface_ip6_nd<CLASS, CMD>::m_evh;
373};
374
375/*
376 * fd.io coding-style-patch-verification: ON
377 *
378 * Local Variables:
379 * eval: (c-set-style "mozilla")
380 * End:
381 */
382
383#endif