Line data Source code
1 : /*
2 : * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include <oper/vn.h>
7 : #include <oper/vrf.h>
8 : #include <oper/nexthop.h>
9 : #include <oper/interface_common.h>
10 : #include <oper/route_common.h>
11 : #include "mac_learning_proto.h"
12 : #include "mac_learning_proto_handler.h"
13 : #include "mac_learning.h"
14 : #include "mac_learning_mgmt.h"
15 : #include "mac_ip_learning.h"
16 :
17 0 : MacLearningMgmtNode::MacLearningMgmtNode(MacLearningEntryPtr ptr):
18 0 : mac_entry_(ptr), intf_(this), vrf_(this), rt_(this), vn_(this),
19 0 : hc_service_(this) {
20 0 : }
21 :
22 0 : MacLearningMgmtNode::~MacLearningMgmtNode() {
23 0 : MacLearningMgmtDBEntry *entry = vrf_.get();
24 0 : vrf_.reset(NULL);
25 0 : if (entry) {
26 0 : entry->tree()->TryDelete(entry);
27 : }
28 :
29 0 : entry = intf_.get();
30 0 : intf_.reset(NULL);
31 0 : if (entry) {
32 0 : entry->tree()->TryDelete(entry);
33 : }
34 :
35 0 : entry = rt_.get();
36 0 : rt_.reset(NULL);
37 0 : if (entry) {
38 0 : entry->tree()->TryDelete(entry);
39 : }
40 :
41 0 : entry = vn_.get();
42 0 : vn_.reset(NULL);
43 0 : if (entry) {
44 0 : entry->tree()->TryDelete(entry);
45 : }
46 :
47 0 : entry = hc_service_.get();
48 0 : hc_service_.reset(NULL);
49 0 : if (entry) {
50 0 : entry->tree()->TryDelete(entry);
51 : }
52 0 : }
53 :
54 0 : void MacLearningMgmtNode::UpdateRef(MacLearningMgmtManager *mgr) {
55 0 : vrf_.reset(mgr->Locate(mac_entry_->vrf()));
56 :
57 : MacLearningEntryLocal *le =
58 0 : dynamic_cast<MacLearningEntryLocal *>(mac_entry_.get());
59 0 : if (le != NULL) {
60 0 : intf_.reset(mgr->Locate(le->intf()));
61 : }
62 :
63 : MacLearningEntryPBB *pbb_mac =
64 0 : dynamic_cast<MacLearningEntryPBB *>(mac_entry_.get());
65 0 : if (pbb_mac) {
66 0 : rt_.reset(mgr->Locate(pbb_mac->vrf()->bmac_vrf_name(),
67 : pbb_mac->bmac()));
68 : }
69 : MacIpLearningEntry *mac_ip_entry =
70 0 : dynamic_cast<MacIpLearningEntry *>(mac_entry_.get());
71 0 : if (mac_ip_entry != NULL) {
72 0 : intf_.reset(mgr->Locate(mac_ip_entry->intf()));
73 0 : vn_.reset(mgr->Locate(mac_ip_entry->Vn()));
74 0 : hc_service_.reset(mgr->Locate(mac_ip_entry->HcService()));
75 : }
76 :
77 0 : }
78 :
79 4398 : MacLearningMgmtDBEntry::MacLearningMgmtDBEntry(Type type, const DBEntry *entry):
80 4398 : type_(type), db_entry_(entry), deleted_(false) {
81 4398 : }
82 :
83 2002 : void MacLearningMgmtDBEntry::Change() {
84 2002 : deleted_ = false;
85 2002 : for (MacLearningEntryList::iterator iter = mac_entry_list_.begin();
86 2002 : iter != mac_entry_list_.end(); iter++) {
87 0 : MacLearningMgmtNode *ptr = iter.operator->();
88 : MacLearningEntryRequestPtr req_ptr(new MacLearningEntryRequest(
89 : MacLearningEntryRequest::RESYNC_MAC,
90 0 : ptr->mac_learning_entry()));
91 :
92 0 : ptr->mac_learning_entry()->EnqueueToTable(req_ptr);
93 0 : }
94 2002 : }
95 :
96 738 : void MacLearningMgmtDBEntry::Delete(bool set_deleted, bool notify_event) {
97 738 : if (set_deleted) {
98 736 : deleted_ = true;
99 : }
100 738 : if (notify_event) {
101 738 : for (MacLearningEntryList::iterator iter = mac_entry_list_.begin();
102 738 : iter != mac_entry_list_.end(); iter++) {
103 0 : MacLearningMgmtNode *ptr = iter.operator->();
104 : MacLearningEntryRequestPtr req_ptr(new MacLearningEntryRequest(
105 : MacLearningEntryRequest::DELETE_MAC,
106 0 : ptr->mac_learning_entry()));
107 0 : ptr->mac_learning_entry()->EnqueueToTable(req_ptr);
108 0 : }
109 : }
110 738 : }
111 :
112 810 : bool MacLearningMgmtDBEntry::TryDelete() {
113 810 : if (mac_entry_list_.empty() == false || tree_->Find(this) == NULL) {
114 0 : return false;
115 : }
116 :
117 810 : if (db_entry_ == NULL || deleted_ == true) {
118 : MacLearningEntryRequestPtr req_ptr(new MacLearningEntryRequest(
119 : MacLearningEntryRequest::FREE_DB_ENTRY, db_entry_,
120 736 : gen_id_));
121 : Agent::GetInstance()->mac_learning_proto()->
122 736 : Find(0)->Enqueue(req_ptr);
123 736 : tree_->Erase(this);
124 736 : return true;
125 736 : }
126 :
127 74 : return false;
128 : }
129 :
130 761 : MacLearningMgmtIntfEntry::MacLearningMgmtIntfEntry(const Interface *intf) :
131 761 : MacLearningMgmtDBEntry(INTERFACE, intf) {
132 761 : }
133 :
134 648 : MacLearningMgmtVrfEntry::MacLearningMgmtVrfEntry(const VrfEntry *vrf) :
135 648 : MacLearningMgmtDBEntry(VRF, vrf) {
136 648 : }
137 :
138 207 : MacLearningMgmtVnEntry::MacLearningMgmtVnEntry(const VnEntry *vn) :
139 207 : MacLearningMgmtDBEntry(VN, vn) {
140 207 : }
141 :
142 0 : MacLearningMgmtHcServiceEntry::MacLearningMgmtHcServiceEntry(
143 0 : const HealthCheckService *hc) :
144 0 : MacLearningMgmtDBEntry(HC_SERVICE, hc) {
145 0 : }
146 :
147 10 : MacLearningMgmtDBTree::MacLearningMgmtDBTree(MacLearningMgmtManager *mgr) :
148 10 : mac_learning_mac_manager_(mgr) {
149 10 : }
150 :
151 2284 : MacLearningMgmtRouteEntry::MacLearningMgmtRouteEntry(const AgentRoute *rt):
152 2284 : MacLearningMgmtDBEntry(BRIDGE, rt) {
153 2284 : const BridgeRouteEntry *br_rt = dynamic_cast<const BridgeRouteEntry *>(rt);
154 2284 : mac_ = br_rt->prefix_address();
155 2284 : vrf_ = br_rt->vrf()->GetName();
156 2284 : }
157 :
158 424 : bool MacLearningMgmtRouteEntry::TryDelete() {
159 424 : bool ret = MacLearningMgmtDBEntry::TryDelete();
160 424 : if (ret == false) {
161 0 : return ret;
162 : }
163 :
164 : //If route entry can be deleted, check if VRF entry can be
165 : //deleted
166 424 : VrfKey vrf_key(vrf_);
167 424 : Agent *agent = tree_->mac_learning_mac_manager()->agent();
168 424 : const VrfEntry *vrf = static_cast<const VrfEntry *>(
169 424 : agent->vrf_table()->Find(&vrf_key, true));
170 424 : if (vrf) {
171 424 : MacLearningMgmtVrfEntry mgmt_vrf(vrf);
172 : MacLearningMgmtVrfEntry *mgmt_entry =
173 : static_cast<MacLearningMgmtVrfEntry *>(
174 424 : tree_->mac_learning_mac_manager()->vrf_tree()->Find(&mgmt_vrf));
175 424 : if (mgmt_entry) {
176 424 : mgmt_entry->tree()->TryDelete(mgmt_entry);
177 : }
178 424 : }
179 424 : return ret;
180 424 : }
181 :
182 498 : bool MacLearningMgmtVrfEntry::TryDelete() {
183 498 : const VrfEntry *vrf = static_cast<const VrfEntry *>(db_entry_);
184 498 : if (tree_->mac_learning_mac_manager()->IsVrfRouteEmpty(vrf->GetName())) {
185 148 : return MacLearningMgmtDBEntry::TryDelete();
186 : }
187 350 : return false;
188 : }
189 :
190 498 : MacLearningMgmtRouteEntry::MacLearningMgmtRouteEntry(const std::string &vrf,
191 498 : const MacAddress &mac):
192 498 : MacLearningMgmtDBEntry(BRIDGE, NULL), vrf_(vrf), mac_(mac) {
193 498 : }
194 :
195 736 : void MacLearningMgmtDBTree::Add(MacLearningMgmtDBEntry *entry) {
196 736 : tree_.insert(MacLearningMgmtDBPair(entry, entry));
197 736 : entry->set_tree(this);
198 736 : }
199 :
200 0 : void MacLearningMgmtDBTree::Change(MacLearningMgmtDBEntry *e) {
201 0 : MacLearningMgmtDBEntry *entry = Find(e);
202 0 : if (entry) {
203 0 : entry->Change();
204 : }
205 0 : }
206 :
207 0 : void MacLearningMgmtDBTree::Delete(MacLearningMgmtDBEntry *e) {
208 0 : MacLearningMgmtDBEntry *entry = Find(e);
209 0 : if (entry) {
210 0 : entry->Delete(true);
211 0 : TryDelete(entry);
212 : }
213 0 : }
214 :
215 : MacLearningMgmtDBEntry*
216 3974 : MacLearningMgmtDBTree::Find(MacLearningMgmtDBEntry *e) {
217 3974 : Tree::iterator it = tree_.find(e);
218 3974 : if (it == tree_.end()) {
219 736 : return NULL;
220 : }
221 :
222 3238 : return it->second;
223 : }
224 :
225 736 : void MacLearningMgmtDBTree::Erase(MacLearningMgmtDBEntry *e) {
226 736 : tree_.erase(e);
227 736 : }
228 :
229 1160 : void MacLearningMgmtDBTree::TryDelete(MacLearningMgmtDBEntry *e) {
230 1160 : if (e->TryDelete()) {
231 736 : delete e;
232 : }
233 1160 : }
234 :
235 : void
236 0 : MacLearningMgmtManager::AddMacLearningEntry(MacLearningMgmtRequestPtr ptr) {
237 : MacPbbLearningEntry *entry =
238 0 : dynamic_cast<MacPbbLearningEntry *>(ptr->mac_learning_entry().get());
239 : MacLearningNodeTree::iterator it =
240 0 : mac_learning_node_tree_.find(entry->key());
241 0 : if (it == mac_learning_node_tree_.end()) {
242 : MacLearningMgmtNodePtr node(new MacLearningMgmtNode(
243 0 : ptr->mac_learning_entry()));
244 0 : node->UpdateRef(this);
245 0 : MacLearningNodePair pair(entry->key(), node);
246 0 : mac_learning_node_tree_.insert(pair);
247 0 : } else {
248 0 : it->second->set_mac_learning_entry(ptr->mac_learning_entry());
249 0 : it->second->UpdateRef(this);
250 : }
251 0 : }
252 :
253 : void
254 0 : MacLearningMgmtManager::AddMacIpLearningEntry(MacLearningMgmtRequestPtr ptr) {
255 : MacIpLearningEntry *entry =
256 0 : dynamic_cast<MacIpLearningEntry *>(ptr->mac_learning_entry().get());
257 :
258 : MacIpLearningNodeTree::iterator it =
259 0 : mac_ip_learning_node_tree_.find(entry->key());
260 0 : if (it == mac_ip_learning_node_tree_.end()) {
261 : MacLearningMgmtNodePtr node(new MacLearningMgmtNode(
262 0 : ptr->mac_learning_entry()));
263 0 : node->UpdateRef(this);
264 0 : MacIpLearningNodePair pair(entry->key(), node);
265 0 : mac_ip_learning_node_tree_.insert(pair);
266 0 : } else {
267 0 : it->second->set_mac_learning_entry(ptr->mac_learning_entry());
268 0 : it->second->UpdateRef(this);
269 : }
270 0 : }
271 : void
272 0 : MacLearningMgmtManager::DeleteMacLearningEntry(MacLearningMgmtRequestPtr ptr) {
273 : MacPbbLearningEntry *entry =
274 0 : dynamic_cast<MacPbbLearningEntry *>(ptr->mac_learning_entry().get());
275 0 : mac_learning_node_tree_.erase(entry->key());
276 0 : }
277 :
278 0 : void MacLearningMgmtManager::DeleteMacIpLearningEntry(MacLearningMgmtRequestPtr ptr) {
279 : MacIpLearningEntry *entry =
280 0 : dynamic_cast<MacIpLearningEntry *>(ptr->mac_learning_entry().get());
281 0 : mac_ip_learning_node_tree_.erase(entry->key());
282 0 : }
283 :
284 2002 : void MacLearningMgmtManager::AddDBEntry(MacLearningMgmtRequestPtr ptr) {
285 2002 : MacLearningMgmtDBEntry *entry = Locate(ptr->db_entry());
286 2002 : entry->set_db_entry(ptr->db_entry());
287 2002 : entry->Change();
288 2002 : }
289 :
290 736 : void MacLearningMgmtManager::DeleteDBEntry(MacLearningMgmtRequestPtr ptr,
291 : bool notify_event) {
292 736 : MacLearningMgmtDBEntry *entry = Find(ptr->db_entry());
293 736 : if (entry) {
294 736 : entry->Delete(true, notify_event);
295 736 : entry->set_gen_id(ptr->gen_id());
296 736 : entry->tree()->TryDelete(entry);
297 : }
298 736 : }
299 :
300 2 : void MacLearningMgmtManager::DeleteAllEntry(MacLearningMgmtRequestPtr ptr) {
301 2 : MacLearningMgmtDBEntry *entry = Find(ptr->db_entry());
302 2 : if (entry) {
303 2 : entry->Delete(false);
304 : }
305 2 : }
306 :
307 : bool
308 2740 : MacLearningMgmtManager::RequestHandler(MacLearningMgmtRequestPtr ptr) {
309 2740 : switch(ptr->event()) {
310 0 : case MacLearningMgmtRequest::ADD_MAC:
311 : case MacLearningMgmtRequest::CHANGE_MAC:
312 0 : AddMacLearningEntry(ptr);
313 0 : break;
314 :
315 0 : case MacLearningMgmtRequest::DELETE_MAC:
316 0 : DeleteMacLearningEntry(ptr);
317 0 : break;
318 :
319 2002 : case MacLearningMgmtRequest::ADD_DBENTRY:
320 : case MacLearningMgmtRequest::CHANGE_DBENTRY:
321 2002 : AddDBEntry(ptr);
322 2002 : break;
323 :
324 736 : case MacLearningMgmtRequest::DELETE_DBENTRY:
325 736 : DeleteDBEntry(ptr);
326 736 : break;
327 :
328 0 : case MacLearningMgmtRequest::DELETE_DBENTRY_NO_OP:
329 0 : DeleteDBEntry(ptr, false);
330 0 : break;
331 2 : case MacLearningMgmtRequest::DELETE_ALL_MAC:
332 2 : DeleteAllEntry(ptr);
333 2 : break;
334 :
335 0 : case MacLearningMgmtRequest::ADD_MAC_IP:
336 : case MacLearningMgmtRequest::CHANGE_MAC_IP:
337 0 : AddMacIpLearningEntry(ptr);
338 0 : break;
339 :
340 0 : case MacLearningMgmtRequest::DELETE_MAC_IP:
341 0 : DeleteMacIpLearningEntry(ptr);
342 0 : break;
343 0 : default:
344 0 : assert(0);
345 : }
346 :
347 2740 : return true;
348 : }
349 :
350 2740 : void MacLearningMgmtManager::Enqueue(MacLearningMgmtRequestPtr &ptr) {
351 2740 : request_queue_.Enqueue(ptr);
352 2740 : }
353 :
354 : MacLearningMgmtDBEntry*
355 0 : MacLearningMgmtManager::Locate(const std::string &vrf, const MacAddress &mac) {
356 0 : MacLearningMgmtRouteEntry mgmt_rt(vrf, mac);
357 : MacLearningMgmtRouteEntry *mgmt_entry =
358 0 : static_cast<MacLearningMgmtRouteEntry *>(rt_tree_.Find(&mgmt_rt));
359 0 : if (mgmt_entry != NULL) {
360 0 : return mgmt_entry;
361 : }
362 :
363 0 : mgmt_entry = new MacLearningMgmtRouteEntry(vrf, mac);
364 0 : rt_tree_.Add(mgmt_entry);
365 0 : return mgmt_entry;
366 0 : }
367 :
368 498 : bool MacLearningMgmtManager::IsVrfRouteEmpty(const std::string &vrf_name) {
369 :
370 498 : MacLearningMgmtRouteEntry rt_entry(vrf_name, MacAddress::ZeroMac());
371 : MacLearningMgmtRouteEntry *rt_entry_ptr =
372 498 : static_cast<MacLearningMgmtRouteEntry *>(rt_tree_.LowerBound(&rt_entry));
373 498 : if (rt_entry_ptr && rt_entry_ptr->vrf() == vrf_name) {
374 350 : return false;
375 : }
376 :
377 148 : return true;
378 498 : }
379 :
380 : MacLearningMgmtDBEntry*
381 738 : MacLearningMgmtManager::Find(const DBEntry *e) {
382 738 : if (e == NULL) {
383 0 : return NULL;
384 : }
385 :
386 738 : MacLearningMgmtDBEntry *mgmt_entry = NULL;
387 738 : const Interface *intf = dynamic_cast<const Interface *>(e);
388 738 : if (intf != NULL) {
389 169 : MacLearningMgmtIntfEntry mgmt_intf(intf);
390 169 : mgmt_entry = intf_tree_.Find(&mgmt_intf);
391 169 : return mgmt_entry;
392 169 : }
393 :
394 569 : const VrfEntry *vrf = dynamic_cast<const VrfEntry *>(e);
395 569 : if (vrf != NULL) {
396 76 : MacLearningMgmtVrfEntry mgmt_vrf(vrf);
397 76 : mgmt_entry = vrf_tree_.Find(&mgmt_vrf);
398 76 : return mgmt_entry;
399 76 : }
400 :
401 493 : const AgentRoute *rt = dynamic_cast<const AgentRoute *>(e);
402 493 : if (rt != NULL) {
403 424 : MacLearningMgmtRouteEntry mgmt_rt(rt);
404 424 : mgmt_entry = rt_tree_.Find(&mgmt_rt);
405 424 : return mgmt_entry;
406 424 : }
407 :
408 69 : const VnEntry *vn = dynamic_cast<const VnEntry *>(e);
409 69 : if (vn != NULL) {
410 69 : MacLearningMgmtVnEntry mgmt_vn(vn);
411 69 : mgmt_entry = vn_tree_.Find(&mgmt_vn);
412 69 : return mgmt_entry;
413 69 : }
414 :
415 0 : const HealthCheckService *hc = dynamic_cast<const HealthCheckService *>(e);
416 0 : if (hc != NULL) {
417 0 : MacLearningMgmtHcServiceEntry mgmt_hc(hc);
418 0 : mgmt_entry = hc_tree_.Find(&mgmt_hc);
419 0 : return mgmt_entry;
420 0 : }
421 0 : return NULL;
422 : }
423 :
424 :
425 : MacLearningMgmtDBEntry*
426 2002 : MacLearningMgmtManager::Locate(const DBEntry *e) {
427 2002 : if (e == NULL) {
428 0 : return NULL;
429 : }
430 :
431 2002 : MacLearningMgmtDBEntry *mgmt_entry = NULL;
432 2002 : const Interface *intf = dynamic_cast<const Interface *>(e);
433 2002 : if (intf != NULL) {
434 423 : MacLearningMgmtIntfEntry mgmt_intf(intf);
435 423 : mgmt_entry = intf_tree_.Find(&mgmt_intf);
436 423 : if (mgmt_entry != NULL) {
437 254 : return mgmt_entry;
438 : }
439 :
440 169 : mgmt_entry = new MacLearningMgmtIntfEntry(intf);
441 169 : intf_tree_.Add(mgmt_entry);
442 169 : return mgmt_entry;
443 423 : }
444 :
445 1579 : const VrfEntry *vrf = dynamic_cast<const VrfEntry *>(e);
446 1579 : if (vrf != NULL) {
447 74 : MacLearningMgmtVrfEntry mgmt_vrf(vrf);
448 74 : mgmt_entry = vrf_tree_.Find(&mgmt_vrf);
449 74 : if (mgmt_entry != NULL) {
450 0 : return mgmt_entry;
451 : }
452 :
453 74 : mgmt_entry = new MacLearningMgmtVrfEntry(vrf);
454 74 : vrf_tree_.Add(mgmt_entry);
455 74 : return mgmt_entry;
456 74 : }
457 :
458 1505 : const AgentRoute *rt = dynamic_cast<const AgentRoute *>(e);
459 1505 : if (rt != NULL) {
460 1436 : MacLearningMgmtRouteEntry mgmt_rt(rt);
461 1436 : mgmt_entry = rt_tree_.Find(&mgmt_rt);
462 1436 : if (mgmt_entry != NULL) {
463 1012 : return mgmt_entry;
464 : }
465 :
466 424 : mgmt_entry = new MacLearningMgmtRouteEntry(rt);
467 424 : rt_tree_.Add(mgmt_entry);
468 424 : return mgmt_entry;
469 1436 : }
470 69 : const VnEntry *vn = dynamic_cast<const VnEntry *>(e);
471 69 : if (vn != NULL) {
472 69 : MacLearningMgmtVnEntry mgmt_vn(vn);
473 69 : mgmt_entry = vn_tree_.Find(&mgmt_vn);
474 69 : if (mgmt_entry != NULL) {
475 0 : return mgmt_entry;
476 : }
477 69 : mgmt_entry = new MacLearningMgmtVnEntry(vn);
478 69 : vn_tree_.Add(mgmt_entry);
479 69 : return mgmt_entry;
480 69 : }
481 0 : const HealthCheckService *hc = dynamic_cast<const HealthCheckService *>(e);
482 0 : if (hc != NULL) {
483 0 : MacLearningMgmtHcServiceEntry mgmt_hc(hc);
484 0 : mgmt_entry = hc_tree_.Find(&mgmt_hc);
485 0 : if (mgmt_entry != NULL) {
486 0 : return mgmt_entry;
487 : }
488 0 : mgmt_entry = new MacLearningMgmtHcServiceEntry(hc);
489 0 : hc_tree_.Add(mgmt_entry);
490 0 : return mgmt_entry;
491 :
492 0 : }
493 0 : return NULL;
494 : }
495 :
496 2 : MacLearningMgmtManager::MacLearningMgmtManager(Agent *agent) :
497 2 : agent_(agent), intf_tree_(this), vrf_tree_(this), rt_tree_(this),
498 2 : vn_tree_(NULL), hc_tree_(NULL),
499 2 : request_queue_(agent_->task_scheduler()->GetTaskId(kTaskMacLearningMgmt), 0,
500 : boost::bind(&MacLearningMgmtManager::RequestHandler,
501 2 : this, _1)) {
502 2 : }
|