Line data Source code
1 : /*
2 : * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <cmn/agent_cmn.h>
7 : #include <vnc_cfg_types.h>
8 : #include <agent_types.h>
9 : #include <init/agent_param.h>
10 : #include <cfg/cfg_init.h>
11 : #include <ifmap/ifmap_node.h>
12 : #include <cmn/agent_cmn.h>
13 : #include <oper/ifmap_dependency_manager.h>
14 : #include <bgp_schema_types.h>
15 : #include <oper/config_manager.h>
16 : #include <oper/agent_sandesh.h>
17 : #include <oper/vn.h>
18 : #include <oper/vrf.h>
19 : #include "oper/bridge_domain.h"
20 :
21 0 : BridgeDomainEntry::BridgeDomainEntry(const BridgeDomainTable *table,
22 0 : const boost::uuids::uuid &id) :
23 0 : AgentOperDBEntry(), table_(table), uuid_(id), isid_(0), bmac_vrf_name_(""),
24 0 : learning_enabled_(false), pbb_etree_enabled_(false), layer2_control_word_(false) {
25 0 : }
26 :
27 0 : bool BridgeDomainEntry::IsLess(const DBEntry &rhs) const {
28 0 : const BridgeDomainEntry &bd =
29 : static_cast<const BridgeDomainEntry &>(rhs);
30 0 : return (uuid_ < bd.uuid_);
31 : }
32 :
33 0 : std::string BridgeDomainEntry::ToString() const {
34 0 : return UuidToString(uuid_);
35 : }
36 :
37 0 : DBEntryBase::KeyPtr BridgeDomainEntry::GetDBRequestKey() const {
38 0 : BridgeDomainKey *key = new BridgeDomainKey(uuid_);
39 0 : return DBEntryBase::KeyPtr(key);
40 : }
41 :
42 0 : void BridgeDomainEntry::SetKey(const DBRequestKey *key) {
43 0 : const BridgeDomainKey *k =
44 : static_cast<const BridgeDomainKey *>(key);
45 0 : uuid_ = k->uuid_;
46 0 : }
47 :
48 0 : bool BridgeDomainEntry::DBEntrySandesh(Sandesh *sresp,
49 : std::string &name) const {
50 0 : BridgeDomainSandeshResp *resp =
51 : static_cast<BridgeDomainSandeshResp *>(sresp);
52 :
53 0 : BridgeDomainSandeshData data;
54 0 : data.set_uuid(UuidToString(uuid_));
55 0 : data.set_name(name_);
56 0 : data.set_isid(isid_);
57 0 : if (vn_.get()) {
58 0 : data.set_vn(UuidToString(vn_->GetUuid()));
59 : }
60 :
61 0 : if (vrf_.get()) {
62 0 : data.set_vrf(vrf_->GetName());
63 : }
64 :
65 0 : if (learning_enabled_) {
66 0 : data.set_learning_enabled("True");
67 : } else {
68 0 : data.set_learning_enabled("False");
69 : }
70 :
71 0 : if (pbb_etree_enabled_) {
72 0 : data.set_pbb_etree_enabled("True");
73 : } else {
74 0 : data.set_pbb_etree_enabled("False");
75 : }
76 :
77 : std::vector<BridgeDomainSandeshData> &list =
78 0 : const_cast<std::vector<BridgeDomainSandeshData>&>(resp->get_bd_list());
79 0 : list.push_back(data);
80 0 : return true;
81 0 : }
82 :
83 0 : void BridgeDomainEntry::UpdateVrf(const BridgeDomainData *data) {
84 0 : std::ostringstream str;
85 0 : str << data->bmac_vrf_name_ << ":" << UuidToString(uuid_);
86 :
87 0 : bmac_vrf_name_ = data->bmac_vrf_name_;
88 :
89 0 : VrfKey key(str.str());
90 0 : vrf_ = static_cast<VrfEntry *>(table_->agent()->
91 0 : vrf_table()->Find(&key, true));
92 0 : if (vrf_ && vrf_->IsDeleted()) {
93 0 : vrf_ = NULL;
94 0 : return;
95 : }
96 :
97 0 : table_->agent()->vrf_table()->CreateVrf(str.str(), data->vn_uuid_,
98 : VrfData::PbbVrf, isid_,
99 0 : data->bmac_vrf_name_,
100 0 : data->mac_aging_time_,
101 0 : data->learning_enabled_);
102 :
103 0 : vrf_ = static_cast<VrfEntry *>(table_->agent()->vrf_table()->
104 0 : FindActiveEntry(&key));
105 0 : assert(vrf_);
106 :
107 0 : vrf_->CreateTableLabel(data->learning_enabled_, true,
108 0 : vn_->flood_unknown_unicast(),
109 0 : vn_->layer2_control_word());
110 0 : mac_aging_time_ = data->mac_aging_time_;
111 0 : layer2_control_word_ = vn_->layer2_control_word();
112 0 : }
113 :
114 0 : bool BridgeDomainEntry::Change(const BridgeDomainTable *table,
115 : const BridgeDomainData *data) {
116 0 : bool ret = false;
117 0 : bool update_vrf = false;
118 :
119 0 : name_ = data->name_;
120 0 : VnEntry *vn = table_->agent()->vn_table()->Find(data->vn_uuid_);
121 0 : if (vn_ != vn) {
122 0 : vn_ = vn;
123 0 : update_vrf = true;
124 0 : ret = true;
125 : }
126 :
127 0 : if (isid_ != data->isid_) {
128 0 : isid_ = data->isid_;
129 0 : update_vrf = true;
130 0 : ret = true;
131 : }
132 :
133 0 : if (isid_ == 0) {
134 0 : OPER_TRACE_ENTRY(BridgeDomain, table,
135 : "Ignoring bridge-domain update with ISID 0",
136 : UuidToString(uuid_), isid_);
137 0 : return ret;
138 : }
139 :
140 0 : if (mac_aging_time_ != data->mac_aging_time_) {
141 0 : mac_aging_time_ = data->mac_aging_time_;
142 0 : update_vrf = true;
143 0 : ret = true;
144 : }
145 :
146 0 : if (learning_enabled_ != data->learning_enabled_) {
147 0 : learning_enabled_ = data->learning_enabled_;
148 0 : update_vrf = true;
149 0 : ret = true;
150 : }
151 :
152 0 : if (vn && layer2_control_word_ != vn->layer2_control_word()) {
153 0 : layer2_control_word_ = vn->layer2_control_word();
154 0 : update_vrf = true;
155 0 : ret = true;
156 : }
157 :
158 0 : if (pbb_etree_enabled_ != data->pbb_etree_enabled_) {
159 0 : pbb_etree_enabled_ = data->pbb_etree_enabled_;
160 0 : ret = true;
161 : }
162 :
163 0 : if (bmac_vrf_name_ != data->bmac_vrf_name_) {
164 0 : bmac_vrf_name_ = data->bmac_vrf_name_;
165 0 : update_vrf = true;
166 0 : ret = true;
167 : }
168 :
169 0 : if (vrf_ == NULL) {
170 0 : update_vrf = true;
171 : }
172 :
173 0 : if (vn_ && data->bmac_vrf_name_ != Agent::NullString() && update_vrf) {
174 0 : OPER_TRACE_ENTRY(BridgeDomain, table, "Creating C-VRF",
175 : UuidToString(uuid_), isid_);
176 0 : UpdateVrf(data);
177 : }
178 :
179 0 : return ret;
180 : }
181 :
182 0 : void BridgeDomainEntry::Delete() {
183 0 : BridgeDomainTable *table = static_cast<BridgeDomainTable *>(get_table());
184 0 : OPER_TRACE_ENTRY(BridgeDomain, table, "Deleting bridge-domain",
185 : UuidToString(uuid_), isid_);
186 0 : if (vrf_.get()) {
187 0 : table_->agent()->vrf_table()->DeleteVrf(vrf_->GetName(),
188 : VrfData::PbbVrf);
189 0 : vrf_.reset();
190 : }
191 0 : }
192 :
193 2 : BridgeDomainTable::BridgeDomainTable(Agent *agent, DB *db,
194 2 : const std::string &name) :
195 2 : AgentOperDBTable(db, name) {
196 2 : set_agent(agent);
197 2 : }
198 :
199 4 : BridgeDomainTable::~BridgeDomainTable() {
200 4 : }
201 :
202 2 : DBTableBase *BridgeDomainTable::CreateTable(Agent *agent, DB *db,
203 : const std::string &name) {
204 2 : BridgeDomainTable *table = new BridgeDomainTable(agent, db, name);
205 2 : table->Init();
206 2 : return table;
207 : }
208 :
209 : std::unique_ptr<DBEntry>
210 0 : BridgeDomainTable::AllocEntry(const DBRequestKey *k) const {
211 0 : const BridgeDomainKey *key = static_cast<const BridgeDomainKey *>(k);
212 0 : BridgeDomainEntry *bd = new BridgeDomainEntry(this, key->uuid_);
213 0 : return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(bd));
214 : }
215 :
216 0 : DBEntry *BridgeDomainTable::OperDBAdd(const DBRequest *req) {
217 0 : BridgeDomainKey *key = static_cast<BridgeDomainKey *>(req->key.get());
218 0 : BridgeDomainData *data = static_cast<BridgeDomainData *>(req->data.get());
219 0 : BridgeDomainEntry *bd = new BridgeDomainEntry(this, key->uuid_);
220 0 : bd->Change(this, data);
221 0 : return bd;
222 : }
223 :
224 0 : bool BridgeDomainTable::OperDBOnChange(DBEntry *entry, const DBRequest *req) {
225 0 : BridgeDomainEntry *bd = static_cast<BridgeDomainEntry *>(entry);
226 0 : BridgeDomainData *data = dynamic_cast<BridgeDomainData *>(req->data.get());
227 0 : bool ret = bd->Change(this, data);
228 0 : return ret;
229 : }
230 :
231 0 : bool BridgeDomainTable::OperDBResync(DBEntry *entry, const DBRequest *req) {
232 0 : return OperDBOnChange(entry, req);
233 : }
234 :
235 0 : bool BridgeDomainTable::OperDBDelete(DBEntry *entry, const DBRequest *req) {
236 0 : BridgeDomainEntry *bd = static_cast<BridgeDomainEntry *>(entry);
237 0 : bd->Delete();
238 0 : return true;
239 : }
240 :
241 0 : static BridgeDomainKey *BuildKey(const boost::uuids::uuid &u) {
242 0 : return new BridgeDomainKey(u);
243 : }
244 :
245 0 : static void BuildVrfData (Agent *agent, IFMapNode *vn_node,
246 : BridgeDomainData *data) {
247 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(vn_node->table());
248 0 : DBGraph *graph = table->GetGraph();
249 :
250 0 : for (DBGraphVertex::adjacency_iterator iter = vn_node->begin(graph);
251 0 : iter != vn_node->end(table->GetGraph()); ++iter) {
252 :
253 0 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
254 0 : if (agent->config_manager()->SkipNode(adj_node)) {
255 0 : continue;
256 : }
257 :
258 0 : if (adj_node->table() == agent->cfg()->cfg_vrf_table()) {
259 : autogen::RoutingInstance *vrf =
260 0 : static_cast<autogen::RoutingInstance *>(adj_node->GetObject());
261 0 : if(vrf->is_default()) {
262 0 : data->bmac_vrf_name_ = adj_node->name();
263 : }
264 : }
265 : }
266 0 : }
267 :
268 0 : static BridgeDomainData *BuildData(Agent *agent, IFMapNode *node,
269 : const autogen::BridgeDomain *bd) {
270 0 : IFMapAgentTable *table = static_cast<IFMapAgentTable *>(node->table());
271 0 : DBGraph *graph = table->GetGraph();
272 0 : boost::uuids::uuid vn_uuid = boost::uuids::nil_uuid();
273 0 : BridgeDomainData *bdd = new BridgeDomainData(agent, node);
274 :
275 0 : for (DBGraphVertex::adjacency_iterator iter = node->begin(graph);
276 0 : iter != node->end(table->GetGraph()); ++iter) {
277 :
278 0 : IFMapNode *adj_node = static_cast<IFMapNode *>(iter.operator->());
279 0 : if (agent->config_manager()->SkipNode(adj_node)) {
280 0 : continue;
281 : }
282 :
283 0 : if (adj_node->table() == agent->cfg()->cfg_vn_table()) {
284 : autogen::VirtualNetwork *vn =
285 0 : static_cast<autogen::VirtualNetwork *>(adj_node->GetObject());
286 0 : autogen::IdPermsType id_perms = vn->id_perms();
287 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong,
288 : vn_uuid);
289 0 : bdd->pbb_etree_enabled_ = vn->pbb_etree_enable();
290 0 : BuildVrfData(agent, adj_node, bdd);
291 0 : }
292 : }
293 :
294 0 : bdd->name_ = node->name();
295 0 : bdd->isid_ = bd->isid();
296 0 : bdd->vn_uuid_ = vn_uuid;
297 0 : bdd->learning_enabled_ = bd->mac_learning_enabled();
298 0 : bdd->mac_aging_time_ = bd->mac_aging_time();
299 0 : return bdd;
300 : }
301 :
302 0 : bool BridgeDomainTable::IFNodeToReq(IFMapNode *node, DBRequest &req,
303 : const boost::uuids::uuid &u) {
304 : autogen::BridgeDomain *bd =
305 0 : static_cast<autogen::BridgeDomain *>(node->GetObject());
306 0 : assert(bd);
307 :
308 0 : assert(!u.is_nil());
309 :
310 0 : req.key.reset(BuildKey(u));
311 0 : if ((req.oper == DBRequest::DB_ENTRY_DELETE) || node->IsDeleted()) {
312 0 : req.oper = DBRequest::DB_ENTRY_DELETE;
313 0 : return true;
314 : }
315 :
316 0 : agent()->config_manager()->AddBridgeDomainNode(node);
317 0 : return false;
318 : }
319 :
320 0 : bool BridgeDomainTable::ProcessConfig(IFMapNode *node, DBRequest &req,
321 : const boost::uuids::uuid &u) {
322 : autogen::BridgeDomain *bd =
323 0 : static_cast <autogen::BridgeDomain *>(node->GetObject());
324 0 : assert(bd);
325 :
326 0 : req.key.reset(BuildKey(u));
327 0 : if (node->IsDeleted()) {
328 0 : return false;
329 : }
330 :
331 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
332 0 : req.data.reset(BuildData(agent(), node, bd));
333 0 : return true;
334 : }
335 :
336 0 : bool BridgeDomainTable::IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &u) {
337 : autogen::BridgeDomain *bd =
338 0 : static_cast<autogen::BridgeDomain *>(node->GetObject());
339 0 : autogen::IdPermsType id_perms = bd->id_perms();
340 0 : CfgUuidSet(id_perms.uuid.uuid_mslong, id_perms.uuid.uuid_lslong, u);
341 0 : return true;
342 0 : }
343 :
344 0 : BridgeDomainEntry *BridgeDomainTable::Find(const boost::uuids::uuid &u) {
345 0 : BridgeDomainKey key(u);
346 0 : return static_cast<BridgeDomainEntry *>(FindActiveEntry(&key));
347 0 : }
348 :
349 : AgentSandeshPtr
350 0 : BridgeDomainTable::GetAgentSandesh(const AgentSandeshArguments *args,
351 : const std::string &context) {
352 : return AgentSandeshPtr(new BridgeDomainSandesh(context,
353 0 : args->GetString("uuid"),
354 0 : args->GetString("name")));
355 : }
356 :
357 0 : void BridgeDomainSandeshReq::HandleRequest() const {
358 0 : AgentSandeshPtr sand(new BridgeDomainSandesh(context(), get_uuid(),
359 0 : get_name()));
360 0 : sand->DoSandesh(sand);
361 0 : }
|