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 1315 : MacLearningMgmtDBEntry::MacLearningMgmtDBEntry(Type type, const DBEntry *entry):
79 1315 : type_(type), db_entry_(entry), deleted_(false) {
80 1315 : }
81 :
82 465 : void MacLearningMgmtDBEntry::Change() {
83 465 : deleted_ = false;
84 465 : for (MacLearningEntryList::iterator iter = mac_entry_list_.begin();
85 465 : 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 465 : }
94 :
95 277 : void MacLearningMgmtDBEntry::Delete(bool set_deleted, bool notify_event) {
96 277 : if (set_deleted) {
97 237 : deleted_ = true;
98 : }
99 277 : if (notify_event) {
100 277 : for (MacLearningEntryList::iterator iter = mac_entry_list_.begin();
101 277 : 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 277 : }
110 :
111 264 : bool MacLearningMgmtDBEntry::TryDelete() {
112 264 : if (mac_entry_list_.empty() == false || tree_->Find(this) == NULL) {
113 0 : return false;
114 : }
115 :
116 264 : if (db_entry_ == NULL || deleted_ == true) {
117 : MacLearningEntryRequestPtr req_ptr(new MacLearningEntryRequest(
118 : MacLearningEntryRequest::FREE_DB_ENTRY, db_entry_,
119 237 : gen_id_));
120 : Agent::GetInstance()->mac_learning_proto()->
121 237 : Find(0)->Enqueue(req_ptr);
122 237 : tree_->Erase(this);
123 237 : return true;
124 237 : }
125 :
126 27 : return false;
127 : }
128 :
129 187 : MacLearningMgmtIntfEntry::MacLearningMgmtIntfEntry(const Interface *intf) :
130 187 : MacLearningMgmtDBEntry(INTERFACE, intf) {
131 187 : }
132 :
133 276 : MacLearningMgmtVrfEntry::MacLearningMgmtVrfEntry(const VrfEntry *vrf) :
134 276 : MacLearningMgmtDBEntry(VRF, vrf) {
135 276 : }
136 :
137 48 : MacLearningMgmtVnEntry::MacLearningMgmtVnEntry(const VnEntry *vn) :
138 48 : MacLearningMgmtDBEntry(VN, vn) {
139 48 : }
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 620 : MacLearningMgmtRouteEntry::MacLearningMgmtRouteEntry(const AgentRoute *rt):
151 620 : MacLearningMgmtDBEntry(BRIDGE, rt) {
152 620 : const BridgeRouteEntry *br_rt = dynamic_cast<const BridgeRouteEntry *>(rt);
153 620 : mac_ = br_rt->prefix_address();
154 620 : vrf_ = br_rt->vrf()->GetName();
155 620 : }
156 :
157 152 : bool MacLearningMgmtRouteEntry::TryDelete() {
158 152 : bool ret = MacLearningMgmtDBEntry::TryDelete();
159 152 : 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 152 : VrfKey vrf_key(vrf_);
166 152 : Agent *agent = tree_->mac_learning_mac_manager()->agent();
167 152 : const VrfEntry *vrf = static_cast<const VrfEntry *>(
168 152 : agent->vrf_table()->Find(&vrf_key, true));
169 152 : if (vrf) {
170 152 : MacLearningMgmtVrfEntry mgmt_vrf(vrf);
171 : MacLearningMgmtVrfEntry *mgmt_entry =
172 : static_cast<MacLearningMgmtVrfEntry *>(
173 152 : tree_->mac_learning_mac_manager()->vrf_tree()->Find(&mgmt_vrf));
174 152 : if (mgmt_entry) {
175 152 : mgmt_entry->tree()->TryDelete(mgmt_entry);
176 : }
177 152 : }
178 152 : return ret;
179 152 : }
180 :
181 184 : bool MacLearningMgmtVrfEntry::TryDelete() {
182 184 : const VrfEntry *vrf = static_cast<const VrfEntry *>(db_entry_);
183 184 : if (tree_->mac_learning_mac_manager()->IsVrfRouteEmpty(vrf->GetName())) {
184 59 : return MacLearningMgmtDBEntry::TryDelete();
185 : }
186 125 : return false;
187 : }
188 :
189 184 : MacLearningMgmtRouteEntry::MacLearningMgmtRouteEntry(const std::string &vrf,
190 184 : const MacAddress &mac):
191 184 : MacLearningMgmtDBEntry(BRIDGE, NULL), vrf_(vrf), mac_(mac) {
192 184 : }
193 :
194 237 : void MacLearningMgmtDBTree::Add(MacLearningMgmtDBEntry *entry) {
195 237 : tree_.insert(MacLearningMgmtDBPair(entry, entry));
196 237 : entry->set_tree(this);
197 237 : }
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 1158 : MacLearningMgmtDBTree::Find(MacLearningMgmtDBEntry *e) {
216 1158 : Tree::iterator it = tree_.find(e);
217 1158 : if (it == tree_.end()) {
218 237 : return NULL;
219 : }
220 :
221 921 : return it->second;
222 : }
223 :
224 237 : void MacLearningMgmtDBTree::Erase(MacLearningMgmtDBEntry *e) {
225 237 : tree_.erase(e);
226 237 : }
227 :
228 389 : void MacLearningMgmtDBTree::TryDelete(MacLearningMgmtDBEntry *e) {
229 389 : if (e->TryDelete()) {
230 237 : delete e;
231 : }
232 389 : }
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 465 : void MacLearningMgmtManager::AddDBEntry(MacLearningMgmtRequestPtr ptr) {
284 465 : MacLearningMgmtDBEntry *entry = Locate(ptr->db_entry());
285 465 : entry->set_db_entry(ptr->db_entry());
286 465 : entry->Change();
287 465 : }
288 :
289 237 : void MacLearningMgmtManager::DeleteDBEntry(MacLearningMgmtRequestPtr ptr,
290 : bool notify_event) {
291 237 : MacLearningMgmtDBEntry *entry = Find(ptr->db_entry());
292 237 : if (entry) {
293 237 : entry->Delete(true, notify_event);
294 237 : entry->set_gen_id(ptr->gen_id());
295 237 : entry->tree()->TryDelete(entry);
296 : }
297 237 : }
298 :
299 40 : void MacLearningMgmtManager::DeleteAllEntry(MacLearningMgmtRequestPtr ptr) {
300 40 : MacLearningMgmtDBEntry *entry = Find(ptr->db_entry());
301 40 : if (entry) {
302 40 : entry->Delete(false);
303 : }
304 40 : }
305 :
306 : bool
307 742 : MacLearningMgmtManager::RequestHandler(MacLearningMgmtRequestPtr ptr) {
308 742 : 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 465 : case MacLearningMgmtRequest::ADD_DBENTRY:
319 : case MacLearningMgmtRequest::CHANGE_DBENTRY:
320 465 : AddDBEntry(ptr);
321 465 : break;
322 :
323 237 : case MacLearningMgmtRequest::DELETE_DBENTRY:
324 237 : DeleteDBEntry(ptr);
325 237 : break;
326 :
327 0 : case MacLearningMgmtRequest::DELETE_DBENTRY_NO_OP:
328 0 : DeleteDBEntry(ptr, false);
329 0 : break;
330 40 : case MacLearningMgmtRequest::DELETE_ALL_MAC:
331 40 : DeleteAllEntry(ptr);
332 40 : 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 742 : return true;
347 : }
348 :
349 742 : void MacLearningMgmtManager::Enqueue(MacLearningMgmtRequestPtr &ptr) {
350 742 : request_queue_.Enqueue(ptr);
351 742 : }
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 184 : bool MacLearningMgmtManager::IsVrfRouteEmpty(const std::string &vrf_name) {
368 :
369 184 : MacLearningMgmtRouteEntry rt_entry(vrf_name, MacAddress::ZeroMac());
370 : MacLearningMgmtRouteEntry *rt_entry_ptr =
371 184 : static_cast<MacLearningMgmtRouteEntry *>(rt_tree_.LowerBound(&rt_entry));
372 184 : if (rt_entry_ptr && rt_entry_ptr->vrf() == vrf_name) {
373 125 : return false;
374 : }
375 :
376 59 : return true;
377 184 : }
378 :
379 : MacLearningMgmtDBEntry*
380 277 : MacLearningMgmtManager::Find(const DBEntry *e) {
381 277 : if (e == NULL) {
382 0 : return NULL;
383 : }
384 :
385 277 : MacLearningMgmtDBEntry *mgmt_entry = NULL;
386 277 : const Interface *intf = dynamic_cast<const Interface *>(e);
387 277 : if (intf != NULL) {
388 49 : MacLearningMgmtIntfEntry mgmt_intf(intf);
389 49 : mgmt_entry = intf_tree_.Find(&mgmt_intf);
390 49 : return mgmt_entry;
391 49 : }
392 :
393 228 : const VrfEntry *vrf = dynamic_cast<const VrfEntry *>(e);
394 228 : if (vrf != NULL) {
395 60 : MacLearningMgmtVrfEntry mgmt_vrf(vrf);
396 60 : mgmt_entry = vrf_tree_.Find(&mgmt_vrf);
397 60 : return mgmt_entry;
398 60 : }
399 :
400 168 : const AgentRoute *rt = dynamic_cast<const AgentRoute *>(e);
401 168 : if (rt != NULL) {
402 152 : MacLearningMgmtRouteEntry mgmt_rt(rt);
403 152 : mgmt_entry = rt_tree_.Find(&mgmt_rt);
404 152 : return mgmt_entry;
405 152 : }
406 :
407 16 : const VnEntry *vn = dynamic_cast<const VnEntry *>(e);
408 16 : if (vn != NULL) {
409 16 : MacLearningMgmtVnEntry mgmt_vn(vn);
410 16 : mgmt_entry = vn_tree_.Find(&mgmt_vn);
411 16 : return mgmt_entry;
412 16 : }
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 465 : MacLearningMgmtManager::Locate(const DBEntry *e) {
426 465 : if (e == NULL) {
427 0 : return NULL;
428 : }
429 :
430 465 : MacLearningMgmtDBEntry *mgmt_entry = NULL;
431 465 : const Interface *intf = dynamic_cast<const Interface *>(e);
432 465 : if (intf != NULL) {
433 101 : MacLearningMgmtIntfEntry mgmt_intf(intf);
434 101 : mgmt_entry = intf_tree_.Find(&mgmt_intf);
435 101 : if (mgmt_entry != NULL) {
436 64 : return mgmt_entry;
437 : }
438 :
439 37 : mgmt_entry = new MacLearningMgmtIntfEntry(intf);
440 37 : intf_tree_.Add(mgmt_entry);
441 37 : return mgmt_entry;
442 101 : }
443 :
444 364 : const VrfEntry *vrf = dynamic_cast<const VrfEntry *>(e);
445 364 : if (vrf != NULL) {
446 32 : MacLearningMgmtVrfEntry mgmt_vrf(vrf);
447 32 : mgmt_entry = vrf_tree_.Find(&mgmt_vrf);
448 32 : if (mgmt_entry != NULL) {
449 0 : return mgmt_entry;
450 : }
451 :
452 32 : mgmt_entry = new MacLearningMgmtVrfEntry(vrf);
453 32 : vrf_tree_.Add(mgmt_entry);
454 32 : return mgmt_entry;
455 32 : }
456 :
457 332 : const AgentRoute *rt = dynamic_cast<const AgentRoute *>(e);
458 332 : if (rt != NULL) {
459 316 : MacLearningMgmtRouteEntry mgmt_rt(rt);
460 316 : mgmt_entry = rt_tree_.Find(&mgmt_rt);
461 316 : if (mgmt_entry != NULL) {
462 164 : return mgmt_entry;
463 : }
464 :
465 152 : mgmt_entry = new MacLearningMgmtRouteEntry(rt);
466 152 : rt_tree_.Add(mgmt_entry);
467 152 : return mgmt_entry;
468 316 : }
469 16 : const VnEntry *vn = dynamic_cast<const VnEntry *>(e);
470 16 : if (vn != NULL) {
471 16 : MacLearningMgmtVnEntry mgmt_vn(vn);
472 16 : mgmt_entry = vn_tree_.Find(&mgmt_vn);
473 16 : if (mgmt_entry != NULL) {
474 0 : return mgmt_entry;
475 : }
476 16 : mgmt_entry = new MacLearningMgmtVnEntry(vn);
477 16 : vn_tree_.Add(mgmt_entry);
478 16 : return mgmt_entry;
479 16 : }
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 : }
|