vxlan: vxlan/vxlan.api API cleanup
[vpp.git] / extras / vom / vom / gbp_bridge_domain.cpp
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 #include "vom/gbp_bridge_domain.hpp"
17 #include "vom/gbp_bridge_domain_cmds.hpp"
18 #include "vom/interface.hpp"
19 #include "vom/l2_binding.hpp"
20 #include "vom/singular_db_funcs.hpp"
21
22 namespace VOM {
23
24 const gbp_bridge_domain::flags_t gbp_bridge_domain::flags_t::NONE(0, "none");
25 const gbp_bridge_domain::flags_t gbp_bridge_domain::flags_t::DO_NOT_LEARN(
26   1,
27   "do-not-learn");
28 const gbp_bridge_domain::flags_t gbp_bridge_domain::flags_t::UU_FWD_DROP(
29   2,
30   "uu-fwd-drop");
31 const gbp_bridge_domain::flags_t gbp_bridge_domain::flags_t::MCAST_DROP(
32   4,
33   "mcast-drop");
34 const gbp_bridge_domain::flags_t gbp_bridge_domain::flags_t::UCAST_ARP(
35   8,
36   "ucast-arp");
37
38 gbp_bridge_domain::flags_t::flags_t(int v, const std::string& s)
39   : enum_base<gbp_bridge_domain::flags_t>(v, s)
40 {
41 }
42
43 /**
44  * A DB of al the interfaces, key on the name
45  */
46 singular_db<uint32_t, gbp_bridge_domain> gbp_bridge_domain::m_db;
47
48 gbp_bridge_domain::event_handler gbp_bridge_domain::m_evh;
49
50 /**
51  * Construct a new object matching the desried state
52  */
53 gbp_bridge_domain::gbp_bridge_domain(const bridge_domain& bd,
54                                      const gbp_route_domain& rd,
55                                      const interface& bvi,
56                                      const flags_t& flags)
57   : m_id(bd.id())
58   , m_bd(bd.singular())
59   , m_rd(rd.singular())
60   , m_bvi(bvi.singular())
61   , m_uu_fwd()
62   , m_bm_flood()
63   , m_flags(flags)
64 {
65 }
66
67 gbp_bridge_domain::gbp_bridge_domain(const bridge_domain& bd,
68                                      const gbp_route_domain& rd,
69                                      const interface& bvi,
70                                      const interface& uu_fwd,
71                                      const interface& bm_flood,
72                                      const flags_t& flags)
73   : m_id(bd.id())
74   , m_bd(bd.singular())
75   , m_rd(rd.singular())
76   , m_bvi(bvi.singular())
77   , m_uu_fwd(uu_fwd.singular())
78   , m_bm_flood(bm_flood.singular())
79   , m_flags(flags)
80 {
81 }
82
83 gbp_bridge_domain::gbp_bridge_domain(const bridge_domain& bd,
84                                      const gbp_route_domain& rd,
85                                      const std::shared_ptr<interface> bvi,
86                                      const std::shared_ptr<interface> uu_fwd,
87                                      const std::shared_ptr<interface> bm_flood,
88                                      const flags_t& flags)
89   : m_id(bd.id())
90   , m_bd(bd.singular())
91   , m_rd(rd.singular())
92   , m_bvi(bvi)
93   , m_uu_fwd(uu_fwd)
94   , m_bm_flood(bm_flood)
95   , m_flags(flags)
96 {
97   if (m_bvi)
98     m_bvi = m_bvi->singular();
99   if (m_uu_fwd)
100     m_uu_fwd = m_uu_fwd->singular();
101   if (m_bm_flood)
102     m_bm_flood = m_bm_flood->singular();
103 }
104
105 gbp_bridge_domain::gbp_bridge_domain(const bridge_domain& bd,
106                                      const gbp_route_domain& rd,
107                                      const interface& bvi,
108                                      const std::shared_ptr<interface> uu_fwd,
109                                      const std::shared_ptr<interface> bm_flood,
110                                      const flags_t& flags)
111   : m_id(bd.id())
112   , m_bd(bd.singular())
113   , m_rd(rd.singular())
114   , m_bvi(bvi.singular())
115   , m_uu_fwd(uu_fwd)
116   , m_bm_flood(bm_flood)
117   , m_flags(flags)
118 {
119   if (m_uu_fwd)
120     m_uu_fwd = m_uu_fwd->singular();
121   if (m_bm_flood)
122     m_bm_flood = m_bm_flood->singular();
123 }
124
125 gbp_bridge_domain::gbp_bridge_domain(const gbp_bridge_domain& bd)
126   : m_id(bd.id())
127   , m_bd(bd.m_bd)
128   , m_rd(bd.m_rd)
129   , m_bvi(bd.m_bvi)
130   , m_uu_fwd(bd.m_uu_fwd)
131   , m_bm_flood(bd.m_bm_flood)
132   , m_flags(bd.m_flags)
133 {
134 }
135
136 const gbp_bridge_domain::key_t
137 gbp_bridge_domain::key() const
138 {
139   return (m_bd->key());
140 }
141
142 uint32_t
143 gbp_bridge_domain::id() const
144 {
145   return (m_bd->id());
146 }
147
148 const std::shared_ptr<bridge_domain>
149 gbp_bridge_domain::get_bridge_domain() const
150 {
151   return m_bd;
152 }
153
154 const std::shared_ptr<interface>
155 gbp_bridge_domain::get_bvi() const
156 {
157   return m_bvi;
158 }
159
160 bool
161 gbp_bridge_domain::operator==(const gbp_bridge_domain& b) const
162 {
163   bool equal = true;
164
165   if (m_bvi && b.m_bvi)
166     equal &= (m_bvi->key() == b.m_bvi->key());
167   else if (!m_bvi && !b.m_bvi)
168     ;
169   else
170     equal = false;
171
172   if (m_uu_fwd && b.m_uu_fwd)
173     equal &= (m_uu_fwd->key() == b.m_uu_fwd->key());
174   else if (!m_uu_fwd && !b.m_uu_fwd)
175     ;
176   else
177     equal = false;
178
179   if (m_bm_flood && b.m_bm_flood)
180     equal &= (m_bm_flood->key() == b.m_bm_flood->key());
181   else if (!m_bm_flood && !b.m_bm_flood)
182     ;
183   else
184     equal = false;
185
186   return ((m_bd->key() == b.m_bd->key()) && equal);
187 }
188
189 void
190 gbp_bridge_domain::sweep()
191 {
192   if (rc_t::OK == m_id.rc()) {
193     HW::enqueue(new gbp_bridge_domain_cmds::delete_cmd(m_id));
194   }
195   HW::write();
196 }
197
198 void
199 gbp_bridge_domain::replay()
200 {
201   if (rc_t::OK == m_id.rc()) {
202     HW::enqueue(new gbp_bridge_domain_cmds::create_cmd(
203       m_id, m_rd->id(), (m_bvi ? m_bvi->handle() : handle_t::INVALID),
204       (m_uu_fwd ? m_uu_fwd->handle() : handle_t::INVALID),
205       (m_bm_flood ? m_bm_flood->handle() : handle_t::INVALID), m_flags));
206   }
207 }
208
209 gbp_bridge_domain::~gbp_bridge_domain()
210 {
211   sweep();
212
213   // not in the DB anymore.
214   m_db.release(m_id.data(), this);
215 }
216
217 std::string
218 gbp_bridge_domain::to_string() const
219 {
220   std::ostringstream s;
221   s << "gbp-bridge-domain:[" << m_bd->to_string()
222     << " flags:" << m_flags.to_string();
223
224   if (m_bvi)
225     s << " bvi:" << m_bvi->to_string();
226   if (m_uu_fwd)
227     s << " uu-fwd:" << m_uu_fwd->to_string();
228
229   s << "]";
230
231   return (s.str());
232 }
233
234 std::shared_ptr<gbp_bridge_domain>
235 gbp_bridge_domain::find(const key_t& key)
236 {
237   return (m_db.find(key));
238 }
239
240 void
241 gbp_bridge_domain::update(const gbp_bridge_domain& desired)
242 {
243   /*
244    * the desired state is always that the interface should be created
245    */
246   if (rc_t::OK != m_id.rc()) {
247     HW::enqueue(new gbp_bridge_domain_cmds::create_cmd(
248       m_id, m_rd->id(), (m_bvi ? m_bvi->handle() : handle_t::INVALID),
249       (m_uu_fwd ? m_uu_fwd->handle() : handle_t::INVALID),
250       (m_bm_flood ? m_bm_flood->handle() : handle_t::INVALID), m_flags));
251   }
252 }
253
254 std::shared_ptr<gbp_bridge_domain>
255 gbp_bridge_domain::find_or_add(const gbp_bridge_domain& temp)
256 {
257   return (m_db.find_or_add(temp.m_id.data(), temp));
258 }
259
260 std::shared_ptr<gbp_bridge_domain>
261 gbp_bridge_domain::singular() const
262 {
263   return find_or_add(*this);
264 }
265
266 void
267 gbp_bridge_domain::dump(std::ostream& os)
268 {
269   db_dump(m_db, os);
270 }
271
272 void
273 gbp_bridge_domain::event_handler::handle_populate(const client_db::key_t& key)
274 {
275   /*
276    * dump GBP Bridge domains
277    */
278   std::shared_ptr<gbp_bridge_domain_cmds::dump_cmd> cmd =
279     std::make_shared<gbp_bridge_domain_cmds::dump_cmd>();
280
281   HW::enqueue(cmd);
282   HW::write();
283
284   for (auto& record : *cmd) {
285     auto& payload = record.get_payload();
286
287     std::shared_ptr<interface> uu_fwd =
288       interface::find(payload.bd.uu_fwd_sw_if_index);
289     std::shared_ptr<interface> bm_flood =
290       interface::find(payload.bd.bm_flood_sw_if_index);
291     std::shared_ptr<interface> bvi =
292       interface::find(payload.bd.bvi_sw_if_index);
293     std::shared_ptr<gbp_route_domain> grd =
294       gbp_route_domain::find(payload.bd.rd_id);
295
296     flags_t flags = gbp_bridge_domain::flags_t::NONE;
297     if (payload.bd.flags & GBP_BD_API_FLAG_DO_NOT_LEARN)
298       flags |= gbp_bridge_domain::flags_t::DO_NOT_LEARN;
299     if (payload.bd.flags & GBP_BD_API_FLAG_UU_FWD_DROP)
300       flags |= gbp_bridge_domain::flags_t::UU_FWD_DROP;
301     if (payload.bd.flags & GBP_BD_API_FLAG_MCAST_DROP)
302       flags |= gbp_bridge_domain::flags_t::MCAST_DROP;
303     if (payload.bd.flags & GBP_BD_API_FLAG_UCAST_ARP)
304       flags |= gbp_bridge_domain::flags_t::UCAST_ARP;
305
306     if (uu_fwd && bm_flood && bvi && grd) {
307       gbp_bridge_domain bd(payload.bd.bd_id, *grd, bvi, uu_fwd, bm_flood,
308                            flags);
309       OM::commit(key, bd);
310       VOM_LOG(log_level_t::DEBUG) << "dump: " << bd.to_string();
311     } else if (bvi) {
312       gbp_bridge_domain bd(payload.bd.bd_id, *grd, *bvi, flags);
313       OM::commit(key, bd);
314       VOM_LOG(log_level_t::DEBUG) << "dump: " << bd.to_string();
315     } else {
316       VOM_LOG(log_level_t::ERROR)
317         << "no BVI:" << payload.bd.bvi_sw_if_index
318         << " nor uu-fwd:" << payload.bd.uu_fwd_sw_if_index;
319     }
320   }
321 }
322
323 gbp_bridge_domain::event_handler::event_handler()
324 {
325   OM::register_listener(this);
326   inspect::register_handler({ "gbd", "gbridge" }, "GBP Bridge Domains", this);
327 }
328
329 void
330 gbp_bridge_domain::event_handler::handle_replay()
331 {
332   m_db.replay();
333 }
334
335 dependency_t
336 gbp_bridge_domain::event_handler::order() const
337 {
338   /* order after gbp-route-domains */
339   return (dependency_t::ACL);
340 }
341
342 void
343 gbp_bridge_domain::event_handler::show(std::ostream& os)
344 {
345   db_dump(m_db, os);
346 }
347 }
348
349 /*
350  * fd.io coding-style-patch-verification: ON
351  *
352  * Local Variables:
353  * eval: (c-set-style "mozilla")
354  * End:
355  */