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