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