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