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