GBP V2
[vpp.git] / src / vpp-api / vom / 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/bridge_domain.hpp"
17 #include "vom/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 bridge_domain::learning_mode_t bridge_domain::learning_mode_t::ON(1,
25                                                                         "on");
26 const bridge_domain::learning_mode_t bridge_domain::learning_mode_t::OFF(0,
27                                                                          "off");
28
29 bridge_domain::learning_mode_t::learning_mode_t(int v, const std::string& s)
30   : enum_base<bridge_domain::learning_mode_t>(v, s)
31 {
32 }
33
34 const bridge_domain::flood_mode_t bridge_domain::flood_mode_t::ON(1, "on");
35 const bridge_domain::flood_mode_t bridge_domain::flood_mode_t::OFF(0, "off");
36
37 bridge_domain::flood_mode_t::flood_mode_t(int v, const std::string& s)
38   : enum_base<bridge_domain::flood_mode_t>(v, s)
39 {
40 }
41
42 const bridge_domain::mac_age_mode_t bridge_domain::mac_age_mode_t::ON(1, "on");
43 const bridge_domain::mac_age_mode_t bridge_domain::mac_age_mode_t::OFF(0,
44                                                                        "off");
45
46 bridge_domain::mac_age_mode_t::mac_age_mode_t(int v, const std::string& s)
47   : enum_base<bridge_domain::mac_age_mode_t>(v, s)
48 {
49 }
50
51 const bridge_domain::arp_term_mode_t bridge_domain::arp_term_mode_t::ON(1,
52                                                                         "on");
53 const bridge_domain::arp_term_mode_t bridge_domain::arp_term_mode_t::OFF(0,
54                                                                          "off");
55
56 bridge_domain::arp_term_mode_t::arp_term_mode_t(int v, const std::string& s)
57   : enum_base<bridge_domain::arp_term_mode_t>(v, s)
58 {
59 }
60
61 /**
62  * A DB of al the interfaces, key on the name
63  */
64 singular_db<uint32_t, bridge_domain> bridge_domain::m_db;
65
66 bridge_domain::event_handler bridge_domain::m_evh;
67
68 /**
69  * Construct a new object matching the desried state
70  */
71 bridge_domain::bridge_domain(uint32_t id,
72                              const learning_mode_t& lmode,
73                              const arp_term_mode_t& amode,
74                              const flood_mode_t& fmode,
75                              const mac_age_mode_t& mmode)
76   : m_id(id)
77   , m_learning_mode(lmode)
78   , m_arp_term_mode(amode)
79   , m_flood_mode(fmode)
80   , m_mac_age_mode(mmode)
81 {
82 }
83
84 bridge_domain::bridge_domain(const bridge_domain& o)
85   : m_id(o.m_id)
86   , m_learning_mode(o.m_learning_mode)
87   , m_arp_term_mode(o.m_arp_term_mode)
88   , m_flood_mode(o.m_flood_mode)
89   , m_mac_age_mode(o.m_mac_age_mode)
90 {
91 }
92
93 const bridge_domain::key_t&
94 bridge_domain::key() const
95 {
96   return (m_id.data());
97 }
98
99 uint32_t
100 bridge_domain::id() const
101 {
102   return (m_id.data());
103 }
104
105 bool
106 bridge_domain::operator==(const bridge_domain& b) const
107 {
108   return ((m_learning_mode == b.m_learning_mode) &&
109           (m_flood_mode == b.m_flood_mode) &&
110           (m_mac_age_mode == b.m_mac_age_mode) &&
111           (m_arp_term_mode == b.m_arp_term_mode) && id() == b.id());
112 }
113
114 void
115 bridge_domain::sweep()
116 {
117   if (rc_t::OK == m_id.rc()) {
118     HW::enqueue(new bridge_domain_cmds::delete_cmd(m_id));
119   }
120   HW::write();
121 }
122
123 void
124 bridge_domain::replay()
125 {
126   if (rc_t::OK == m_id.rc()) {
127     HW::enqueue(new bridge_domain_cmds::create_cmd(
128       m_id, m_learning_mode, m_arp_term_mode, m_flood_mode, m_mac_age_mode));
129   }
130 }
131
132 bridge_domain::~bridge_domain()
133 {
134   sweep();
135
136   // not in the DB anymore.
137   m_db.release(m_id.data(), this);
138 }
139
140 std::string
141 bridge_domain::to_string() const
142 {
143   std::ostringstream s;
144   s << "bridge-domain:[" << m_id.to_string()
145     << " learning-mode:" << m_learning_mode.to_string() << "]";
146
147   return (s.str());
148 }
149
150 std::shared_ptr<bridge_domain>
151 bridge_domain::find(const key_t& key)
152 {
153   return (m_db.find(key));
154 }
155
156 void
157 bridge_domain::update(const bridge_domain& desired)
158 {
159   /*
160    * the desired state is always that the interface should be created
161    */
162   if (rc_t::OK != m_id.rc()) {
163     HW::enqueue(new bridge_domain_cmds::create_cmd(
164       m_id, m_learning_mode, m_arp_term_mode, m_flood_mode, m_mac_age_mode));
165   }
166 }
167
168 std::shared_ptr<bridge_domain>
169 bridge_domain::find_or_add(const bridge_domain& temp)
170 {
171   return (m_db.find_or_add(temp.m_id.data(), temp));
172 }
173
174 std::shared_ptr<bridge_domain>
175 bridge_domain::singular() const
176 {
177   return find_or_add(*this);
178 }
179
180 void
181 bridge_domain::dump(std::ostream& os)
182 {
183   db_dump(m_db, os);
184 }
185
186 void
187 bridge_domain::event_handler::handle_populate(const client_db::key_t& key)
188 {
189   /*
190    * dump VPP Bridge domains
191    */
192   std::shared_ptr<bridge_domain_cmds::dump_cmd> cmd =
193     std::make_shared<bridge_domain_cmds::dump_cmd>();
194
195   HW::enqueue(cmd);
196   HW::write();
197
198   for (auto& record : *cmd) {
199     auto& payload = record.get_payload();
200
201     bridge_domain bd(payload.bd_id);
202
203     VOM_LOG(log_level_t::DEBUG) << "dump: " << bd.to_string();
204
205     /*
206      * Write each of the discovered bridge-domains into the OM,
207      * but disable the HW Command q whilst we do, so that no
208      * commands are sent to VPP
209      */
210     OM::commit(key, bd);
211
212     /**
213      * For each interface in the BD construct an l2_binding
214      */
215     for (unsigned int ii = 0; ii < payload.n_sw_ifs; ii++) {
216       std::shared_ptr<interface> itf =
217         interface::find(payload.sw_if_details[ii].sw_if_index);
218       if (itf) {
219         l2_binding l2(*itf, bd);
220         OM::commit(key, l2);
221       }
222     }
223   }
224 }
225
226 bridge_domain::event_handler::event_handler()
227 {
228   OM::register_listener(this);
229   inspect::register_handler({ "bd", "bridge" }, "Bridge Domains", this);
230 }
231
232 void
233 bridge_domain::event_handler::handle_replay()
234 {
235   m_db.replay();
236 }
237
238 dependency_t
239 bridge_domain::event_handler::order() const
240 {
241   return (dependency_t::TABLE);
242 }
243
244 void
245 bridge_domain::event_handler::show(std::ostream& os)
246 {
247   db_dump(m_db, os);
248 }
249 }
250
251 /*
252  * fd.io coding-style-patch-verification: ON
253  *
254  * Local Variables:
255  * eval: (c-set-style "mozilla")
256  * End:
257  */