Line data Source code
1 : /*
2 : * Copyright (c) 2013-2024 Juniper Networks, Inc. All rights reserved.
3 : * Copyright (c) 2024 Elena Zizganova
4 : */
5 :
6 : #include <boost/uuid/uuid_io.hpp>
7 : #include <boost/foreach.hpp>
8 : #include <cmn/agent_cmn.h>
9 : #include "ifmap/ifmap_node.h"
10 : #include <vnc_cfg_types.h>
11 : #include "base/task_annotations.h"
12 : #include <base/logging.h>
13 : #include <oper/route_common.h>
14 : #include <oper/interface_common.h>
15 : #include <oper/nexthop.h>
16 : #include <oper/mirror_table.h>
17 : #include <oper/multicast.h>
18 : #include <oper/tunnel_nh.h>
19 : #include <oper/vrf.h>
20 : #include <oper/agent_sandesh.h>
21 : #include <oper/crypt_tunnel.h>
22 :
23 : using namespace std;
24 :
25 : NextHopTable *NextHopTable::nexthop_table_;
26 :
27 : /////////////////////////////////////////////////////////////////////////////
28 : // TunnelTyperoutines
29 : /////////////////////////////////////////////////////////////////////////////
30 : TunnelType::Type TunnelType::default_type_;
31 : TunnelType::PriorityList TunnelType::priority_list_;
32 :
33 1383 : TunnelType::Type TunnelType::ComputeType(TunnelType::TypeBmap bmap) {
34 1383 : for (PriorityList::const_iterator it = priority_list_.begin();
35 1383 : it != priority_list_.end(); it++) {
36 0 : if (bmap & (1 << *it)) {
37 0 : return *it;
38 : }
39 : }
40 :
41 : //There is no match found in priority list of config,
42 : //pick the advertised Tunnel type according to the order.
43 1383 : if (bmap & (1 << MPLS_GRE))
44 1265 : return MPLS_GRE;
45 118 : else if (bmap & (1 << MPLS_UDP))
46 0 : return MPLS_UDP;
47 118 : else if (bmap & (1 << VXLAN))
48 53 : return VXLAN;
49 65 : else if (bmap & (1 << NATIVE))
50 50 : return NATIVE;
51 15 : else if (bmap & (1 << MPLS_OVER_MPLS))
52 0 : return MPLS_OVER_MPLS;
53 :
54 15 : return DefaultType();
55 : }
56 :
57 : // Confg triggers for change in encapsulation priority
58 4 : bool TunnelType::EncapPrioritySync(const std::vector<std::string> &cfg_list) {
59 4 : PriorityList l;
60 :
61 4 : for (std::vector<std::string>::const_iterator it = cfg_list.begin();
62 4 : it != cfg_list.end(); it++) {
63 0 : if (*it == "MPLSoGRE")
64 0 : l.push_back(MPLS_GRE);
65 0 : if (*it == "MPLSoUDP")
66 0 : l.push_back(MPLS_UDP);
67 0 : if (*it == "VXLAN")
68 0 : l.push_back(VXLAN);
69 : }
70 :
71 4 : bool encap_changed = (priority_list_ != l);
72 4 : priority_list_ = l;
73 :
74 4 : return encap_changed;
75 4 : }
76 :
77 2 : void TunnelType::DeletePriorityList() {
78 2 : priority_list_.clear();
79 2 : }
80 :
81 : /////////////////////////////////////////////////////////////////////////////
82 : // NextHop routines
83 : /////////////////////////////////////////////////////////////////////////////
84 15 : void NextHop::SendObjectLog(const NextHopTable *table,
85 : AgentLogEvent::type event) const {
86 15 : NextHopObjectLogInfo info;
87 :
88 15 : FillObjectLog(event, info);
89 15 : OPER_TRACE_ENTRY(NextHop, table, info);
90 15 : }
91 :
92 1521 : NextHop::~NextHop() {
93 1521 : if (id_ != kInvalidIndex) {
94 145 : static_cast<NextHopTable *>(get_table())->FreeInterfaceId(id_);
95 : }
96 1521 : }
97 :
98 0 : void NextHop::SetKey(const DBRequestKey *key) {
99 0 : const NextHopKey *nh_key = static_cast<const NextHopKey *>(key);
100 0 : type_ = nh_key->type_;
101 0 : policy_ = nh_key->policy_;
102 0 : };
103 :
104 : // Allocate label for nexthop
105 73 : MplsLabel *NextHop::AllocateLabel(Agent *agent, const NextHopKey *key) {
106 73 : return agent->mpls_table()->AllocLabel(key);
107 : }
108 :
109 145 : void NextHop::Add(Agent *agent, const DBRequest *req) {
110 145 : ChangeEntry(req);
111 145 : }
112 :
113 141 : void NextHop::Change(const DBRequest *req) {
114 141 : Agent *agent = static_cast<NextHopTable *>(get_table())->agent();
115 : // Allocate mpls label if required
116 141 : if (NeedMplsLabel() && (mpls_label() == NULL)) {
117 : const NextHopKey *key =
118 0 : static_cast<const NextHopKey *>(req->key.get());
119 0 : mpls_label_ = AllocateLabel(agent, key);
120 : }
121 141 : }
122 :
123 145 : void NextHop::PostAdd() {
124 145 : Agent *agent = static_cast<NextHopTable *>(get_table())->agent();
125 145 : DBEntryBase::KeyPtr key = GetDBRequestKey();
126 145 : const NextHopKey *key1 = static_cast<const NextHopKey *>(key.get());
127 : // Mpls Label stores a pointer to NH oper db entry. It uses db table Find
128 : // api to retrieve NH db entry. Hence Allocate Mpls label if required
129 : // in PostAdd api which ensures presence of NH db entry in db table.
130 145 : if (NeedMplsLabel()) {
131 73 : mpls_label_ = AllocateLabel(agent, key1);
132 : }
133 145 : }
134 :
135 0 : void NextHop::EnqueueResync() const {
136 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
137 0 : req.key = GetDBRequestKey();
138 0 : (static_cast<NextHopKey *>(req.key.get()))->sub_op_ = AgentKey::RESYNC;
139 0 : get_table()->Enqueue(&req);
140 0 : }
141 :
142 433 : void NextHop::FillObjectLog(AgentLogEvent::type event,
143 : NextHopObjectLogInfo &info) const {
144 1299 : string type_str, policy_str("Disabled"), valid_str("Invalid"), str;
145 433 : switch (type_) {
146 7 : case NextHop::DISCARD:
147 7 : type_str.assign("DISCARD");
148 7 : break;
149 :
150 20 : case NextHop::RECEIVE:
151 20 : type_str.assign("RECEIVE");
152 20 : break;
153 :
154 4 : case NextHop::RESOLVE:
155 4 : type_str.assign("RESOLVE");
156 4 : break;
157 :
158 9 : case NextHop::ARP:
159 9 : type_str.assign("ARP");
160 9 : break;
161 :
162 0 : case NextHop::NDP:
163 0 : type_str.assign("NDP");
164 0 : break;
165 :
166 232 : case NextHop::INTERFACE:
167 232 : type_str.assign("INTERFACE");
168 232 : break;
169 :
170 6 : case NextHop::VRF:
171 6 : type_str.assign("VRF");
172 6 : break;
173 :
174 20 : case NextHop::TUNNEL:
175 20 : type_str.assign("TUNNEL");
176 20 : break;
177 :
178 0 : case NextHop::MIRROR:
179 0 : type_str.assign("MIRROR");
180 0 : break;
181 :
182 0 : case NextHop::VLAN:
183 0 : type_str.assign("VLAN");
184 0 : break;
185 :
186 131 : case NextHop::COMPOSITE:
187 131 : type_str.assign("COMPOSITE");
188 131 : break;
189 :
190 0 : case NextHop::PBB:
191 0 : type_str.assign("PBB_INDIRECT");
192 0 : break;
193 :
194 4 : default:
195 4 : type_str.assign("unknown");
196 : }
197 433 : if (policy_) {
198 107 : policy_str.assign("Enabled");
199 : }
200 433 : if (valid_) {
201 404 : valid_str.assign("Valid");
202 : }
203 433 : switch (event) {
204 145 : case AgentLogEvent::ADD:
205 145 : str.assign("Addition ");
206 145 : break;
207 146 : case AgentLogEvent::DEL:
208 146 : str.assign("Deletion ");
209 146 : break;
210 141 : case AgentLogEvent::CHANGE:
211 141 : str.assign("Modification ");
212 141 : break;
213 1 : case AgentLogEvent::RESYNC:
214 1 : str.assign("Resync ");
215 1 : break;
216 0 : default:
217 0 : str.assign("unknown");
218 : }
219 433 : info.set_event(str);
220 433 : info.set_type(type_str);
221 433 : info.set_policy(policy_str);
222 433 : info.set_valid(valid_str);
223 433 : info.set_id(id_);
224 433 : }
225 :
226 261 : void NextHop::FillObjectLogIntf(const Interface *intf,
227 : NextHopObjectLogInfo &info) {
228 261 : if (intf) {
229 261 : string if_type_str;
230 261 : switch(intf->type()) {
231 242 : case Interface::VM_INTERFACE:
232 242 : if_type_str.assign("VM_INTERFACE");
233 242 : break;
234 11 : case Interface::PHYSICAL:
235 11 : if_type_str.assign("ETH");
236 11 : break;
237 0 : case Interface::INET:
238 0 : if_type_str.assign("VIRTUAL_HOST");
239 0 : break;
240 8 : case Interface::PACKET:
241 8 : if_type_str.assign("PKT");
242 8 : break;
243 0 : default:
244 0 : if_type_str.assign("Invalid");
245 0 : break;
246 : }
247 261 : info.set_intf_type(if_type_str);
248 261 : info.set_intf_uuid(UuidToString(intf->GetUuid()));
249 261 : info.set_intf_name(intf->name());
250 261 : }
251 261 : }
252 :
253 241 : void NextHop::FillObjectLogMac(const unsigned char *m,
254 : NextHopObjectLogInfo &info) {
255 : char mstr[32];
256 241 : snprintf(mstr, 32, "%02x:%02x:%02x:%02x:%02x:%02x",
257 241 : m[0], m[1], m[2], m[3], m[4], m[5]);
258 241 : string mac(mstr);
259 241 : info.set_mac(mac);
260 241 : }
261 :
262 2 : bool NextHop::NexthopToInterfacePolicy() const {
263 2 : if (GetType() == NextHop::INTERFACE) {
264 2 : const InterfaceNH *intf_nh =
265 : static_cast<const InterfaceNH *>(this);
266 2 : const VmInterface *intf = dynamic_cast<const VmInterface *>
267 2 : (intf_nh->GetInterface());
268 2 : if (intf && intf->policy_enabled()) {
269 2 : return true;
270 : }
271 : }
272 0 : return false;
273 : }
274 :
275 : /////////////////////////////////////////////////////////////////////////////
276 : // NextHopTable routines
277 : /////////////////////////////////////////////////////////////////////////////
278 2 : NextHopTable::NextHopTable(DB *db, const string &name) : AgentDBTable(db, name){
279 : // nh-index 0 is reserved by vrouter. So, pre-allocate the first index so
280 : // that nh added by agent use index 1 and above
281 2 : int id = index_table_.Insert(NULL);
282 2 : assert(id == 0);
283 2 : }
284 :
285 4 : NextHopTable::~NextHopTable() {
286 2 : FreeInterfaceId(0);
287 4 : }
288 :
289 2 : uint32_t NextHopTable::ReserveIndex() {
290 2 : return index_table_.Insert(NULL);
291 : }
292 :
293 1127 : std::unique_ptr<DBEntry> NextHopTable::AllocEntry(const DBRequestKey *k) const {
294 1127 : return std::unique_ptr<DBEntry>(static_cast<DBEntry *>(AllocWithKey(k)));
295 : }
296 :
297 1272 : NextHop *NextHopTable::AllocWithKey(const DBRequestKey *k) const {
298 1272 : const NextHopKey *key = static_cast<const NextHopKey *>(k);
299 1272 : return key->AllocEntry();
300 : }
301 :
302 0 : std::unique_ptr<DBEntry> NextHopTable::GetEntry(const DBRequestKey *key) const {
303 0 : return std::unique_ptr<DBEntry>(AllocWithKey(key));
304 : }
305 :
306 145 : DBEntry *NextHopTable::Add(const DBRequest *req) {
307 145 : const NextHopKey *key = static_cast<const NextHopKey *>(req->key.get());
308 145 : NextHop *nh = AllocWithKey(key);
309 :
310 145 : if (nh->CanAdd() == false) {
311 0 : delete nh;
312 0 : return NULL;
313 : }
314 145 : CheckVrNexthopLimit();
315 145 : nh->set_id(index_table_.Insert(nh));
316 145 : nh->Add(agent(), req);
317 145 : nh->SendObjectLog(this, AgentLogEvent::ADD);
318 145 : return static_cast<DBEntry *>(nh);
319 : }
320 :
321 141 : bool NextHopTable::OnChange(DBEntry *entry, const DBRequest *req) {
322 141 : NextHop *nh = static_cast<NextHop *>(entry);
323 141 : bool delcleared = false;
324 : //Since as part of label addition later, active nh entries are looked
325 : //up. So makes sense to clear delete now so as to allow proper label
326 : //binding.
327 141 : if (entry->IsDeleted()) {
328 0 : entry->ClearDelete();
329 0 : delcleared = true;
330 : }
331 141 : nh->Change(req);
332 141 : bool ret = nh->ChangeEntry(req);
333 141 : nh->SendObjectLog(this, AgentLogEvent::CHANGE);
334 141 : return (ret | delcleared);
335 : }
336 :
337 1 : bool NextHopTable::Resync(DBEntry *entry, const DBRequest *req) {
338 1 : NextHop *nh = static_cast<NextHop *>(entry);
339 1 : bool ret = nh->ChangeEntry(req);
340 1 : nh->SendObjectLog(this, AgentLogEvent::RESYNC);
341 1 : return ret;
342 : }
343 :
344 146 : bool NextHopTable::Delete(DBEntry *entry, const DBRequest *req) {
345 146 : NextHop *nh = static_cast<NextHop *>(entry);
346 146 : nh->Delete(req);
347 146 : nh->SendObjectLog(this, AgentLogEvent::DEL);
348 146 : CheckVrNexthopLimit();
349 146 : return true;
350 : }
351 :
352 2 : DBTableBase *NextHopTable::CreateTable(DB *db, const std::string &name) {
353 2 : nexthop_table_ = new NextHopTable(db, name);
354 2 : nexthop_table_->Init();
355 2 : return nexthop_table_;
356 : };
357 :
358 7 : Interface *NextHopTable::FindInterface(const InterfaceKey &key) const {
359 7 : return static_cast<Interface *>
360 14 : (Agent::GetInstance()->interface_table()->FindActiveEntry(&key));
361 : }
362 :
363 0 : VrfEntry *NextHopTable::FindVrfEntry(const VrfKey &key) const {
364 0 : return static_cast<VrfEntry *>(Agent::GetInstance()->vrf_table()->FindActiveEntry(&key));
365 : }
366 :
367 436 : void NextHopTable::Process(DBRequest &req) {
368 436 : agent()->ConcurrencyCheck();
369 : DBTablePartition *tpart =
370 436 : static_cast<DBTablePartition *>(GetTablePartition(req.key.get()));
371 436 : tpart->Process(NULL, &req);
372 436 : }
373 :
374 0 : void NextHopTable::RemoveWithoutDelete(DBEntry *entry) {
375 0 : agent()->ConcurrencyCheck();
376 : DBTablePartition *tpart =
377 0 : static_cast<DBTablePartition *>(GetTablePartition(entry));
378 0 : tpart->RemoveWithoutDelete(entry);
379 0 : }
380 :
381 0 : void NextHopTable::AddWithoutAlloc(DBEntry *entry) {
382 0 : agent()->ConcurrencyCheck();
383 : DBTablePartition *tpart =
384 0 : static_cast<DBTablePartition *>(GetTablePartition(entry));
385 0 : tpart->AddWithoutAlloc(entry);
386 0 : }
387 :
388 149 : void NextHopTable::OnZeroRefcount(AgentDBEntry *e) {
389 149 : NextHop *nh = static_cast<NextHop *>(e);
390 :
391 : // Release mpls db entry reference
392 149 : nh->ResetMplsRef();
393 149 : if (nh->DeleteOnZeroRefCount() == false) {
394 90 : return;
395 : }
396 :
397 59 : agent()->ConcurrencyCheck();
398 59 : nh->OnZeroRefCount();
399 :
400 59 : DBRequest req;
401 59 : req.oper = DBRequest::DB_ENTRY_DELETE;
402 59 : DBEntryBase::KeyPtr key = nh->GetDBRequestKey();
403 59 : req.key = std::move(key);
404 59 : req.data.reset(NULL);
405 59 : Process(req);
406 59 : }
407 :
408 291 : void NextHopTable::CheckVrNexthopLimit() {
409 291 : VrLimitExceeded &vr_limits = agent()->get_vr_limits_exceeded_map();
410 291 : VrLimitExceeded::iterator vr_limit_itr = vr_limits.find("vr_nexthops");
411 291 : if (vr_limit_itr->second == "Normal") {
412 15 : if (index_table_.InUseIndexCount() >= ((agent()->vr_limit_high_watermark() *
413 15 : agent()->vrouter_max_nexthops())/100) ) {
414 2 : vr_limit_itr->second.assign(std::string("Exceeded"));
415 2 : LOG(ERROR, "Vrouter Nexthop Index Exceeded.");
416 : }
417 276 : } else if ( vr_limit_itr->second == "Exceeded") {
418 3 : if (index_table_.InUseIndexCount() >= agent()->vrouter_max_nexthops()) {
419 2 : vr_limit_itr->second.assign(std::string("TableLimit"));
420 2 : LOG(ERROR, "Vrouter Nexthop Table Limit Reached. Skip NH Add.");
421 1 : } else if ( index_table_.InUseIndexCount() < ((agent()->vr_limit_low_watermark() *
422 1 : agent()->vrouter_max_nexthops())/100) ) {
423 1 : vr_limit_itr->second.assign(std::string("Normal"));
424 : }
425 273 : } else if ( vr_limit_itr->second == "TableLimit" ) {
426 273 : if (index_table_.InUseIndexCount() <
427 273 : ((agent()->vrouter_max_nexthops()*95)/100) ) {
428 1 : vr_limit_itr->second.assign(std::string("Exceeded"));
429 1 : LOG(ERROR, "Vrouter Nexthop Index Exceeded.");
430 : }
431 : }
432 291 : agent()->set_vr_limits_exceeded_map(vr_limits);
433 291 : }
434 :
435 : /////////////////////////////////////////////////////////////////////////////
436 : // ARP NH routines
437 : /////////////////////////////////////////////////////////////////////////////
438 24 : NextHop *ArpNHKey::AllocEntry() const {
439 24 : VrfEntry *vrf = static_cast<VrfEntry *>
440 24 : (Agent::GetInstance()->vrf_table()->Find(&vrf_key_, true));
441 24 : return new ArpNH(vrf, dip_);
442 : }
443 :
444 2 : bool ArpNH::CanAdd() const {
445 2 : if (vrf_ == NULL) {
446 0 : LOG(ERROR, "Invalid VRF in ArpNH. Skip Add");
447 0 : return false;
448 : }
449 :
450 2 : return true;
451 : }
452 :
453 40 : bool ArpNH::NextHopIsLess(const DBEntry &rhs) const {
454 40 : const ArpNH &a = static_cast<const ArpNH &>(rhs);
455 :
456 40 : if (vrf_.get() != a.vrf_.get()) {
457 0 : return vrf_.get() < a.vrf_.get();
458 : }
459 :
460 40 : return (ip_ < a.ip_);
461 : }
462 :
463 0 : void ArpNH::SetKey(const DBRequestKey *k) {
464 0 : const ArpNHKey *key = static_cast<const ArpNHKey *>(k);
465 :
466 0 : NextHop::SetKey(k);
467 0 : vrf_ = NextHopTable::GetInstance()->FindVrfEntry(key->vrf_key_);
468 0 : ip_ = key->dip_;
469 0 : }
470 :
471 7 : bool ArpNH::ChangeEntry(const DBRequest *req) {
472 7 : bool ret= false;
473 : //const ArpNHKey *key = static_cast<const ArpNHKey *>(req->key.get());
474 7 : const ArpNHData *data = static_cast<const ArpNHData *>(req->data.get());
475 7 : if (valid_ != data->resolved_) {
476 0 : valid_ = data->resolved_;
477 0 : ret = true;
478 : }
479 :
480 : Interface *pinterface = NextHopTable::GetInstance()->FindInterface
481 7 : (*data->intf_key_.get());
482 7 : if (interface_.get() != pinterface) {
483 4 : interface_ = pinterface;
484 4 : ret = true;
485 : }
486 :
487 7 : if (!data->valid_) {
488 4 : mac_.Zero();
489 4 : return ret;
490 : }
491 :
492 3 : if (data->resolved_ != true) {
493 : // If ARP is not resolved mac will be invalid
494 3 : return ret;
495 : }
496 :
497 0 : if (mac_.CompareTo(data->mac_) != 0) {
498 0 : mac_ = data->mac_;
499 0 : ret = true;
500 : }
501 :
502 0 : return ret;
503 : }
504 :
505 22 : const uint32_t ArpNH::vrf_id() const {
506 22 : return vrf_->vrf_id();
507 : }
508 :
509 4 : ArpNH::KeyPtr ArpNH::GetDBRequestKey() const {
510 4 : NextHopKey *key = new ArpNHKey(vrf_->GetName(), ip_, policy_);
511 4 : return DBEntryBase::KeyPtr(key);
512 : }
513 :
514 0 : const boost::uuids::uuid &ArpNH::GetIfUuid() const {
515 0 : return interface_->GetUuid();
516 : }
517 :
518 9 : void ArpNH::SendObjectLog(const NextHopTable *table,
519 : AgentLogEvent::type event) const {
520 9 : NextHopObjectLogInfo info;
521 :
522 9 : FillObjectLog(event, info);
523 :
524 9 : const Interface *intf = GetInterface();
525 9 : FillObjectLogIntf(intf, info);
526 :
527 9 : const VrfEntry *vrf = GetVrf();
528 9 : if (vrf) {
529 9 : info.set_vrf(vrf->GetName());
530 : }
531 9 : const Ip4Address *ip = GetIp();
532 9 : info.set_dest_ip(ip->to_string());
533 :
534 9 : const unsigned char *m = GetMac().GetData();
535 9 : FillObjectLogMac(m, info);
536 :
537 9 : OPER_TRACE_ENTRY(NextHop, table, info);
538 9 : }
539 :
540 : /////////////////////////////////////////////////////////////////////////////
541 : // NDP NH routines
542 : /////////////////////////////////////////////////////////////////////////////
543 0 : NextHop *NdpNHKey::AllocEntry() const {
544 0 : VrfEntry *vrf = static_cast<VrfEntry *>
545 0 : (Agent::GetInstance()->vrf_table()->Find(&vrf_key_, true));
546 0 : return new NdpNH(vrf, dip_);
547 : }
548 :
549 0 : bool NdpNH::CanAdd() const {
550 0 : if (vrf_ == NULL) {
551 0 : LOG(ERROR, "Invalid VRF in NdpNH. Skip Add");
552 0 : return false;
553 : }
554 :
555 0 : return true;
556 : }
557 :
558 0 : bool NdpNH::NextHopIsLess(const DBEntry &rhs) const {
559 0 : const NdpNH &a = static_cast<const NdpNH &>(rhs);
560 :
561 0 : if (vrf_.get() != a.vrf_.get()) {
562 0 : return vrf_.get() < a.vrf_.get();
563 : }
564 :
565 0 : return (ip_ < a.ip_);
566 : }
567 :
568 0 : void NdpNH::SetKey(const DBRequestKey *k) {
569 0 : const NdpNHKey *key = static_cast<const NdpNHKey *>(k);
570 :
571 0 : NextHop::SetKey(k);
572 0 : vrf_ = NextHopTable::GetInstance()->FindVrfEntry(key->vrf_key_);
573 0 : ip_ = key->dip_;
574 0 : }
575 :
576 0 : bool NdpNH::ChangeEntry(const DBRequest *req) {
577 0 : bool ret= false;
578 : //const NdpNHKey *key = static_cast<const NdpNHKey *>(req->key.get());
579 0 : const NdpNHData *data = static_cast<const NdpNHData *>(req->data.get());
580 0 : if (valid_ != data->resolved_) {
581 0 : valid_ = data->resolved_;
582 0 : ret = true;
583 : }
584 :
585 : Interface *pinterface = NextHopTable::GetInstance()->FindInterface
586 0 : (*data->intf_key_.get());
587 0 : if (interface_.get() != pinterface) {
588 0 : interface_ = pinterface;
589 0 : ret = true;
590 : }
591 :
592 0 : if (!data->valid_) {
593 0 : mac_.Zero();
594 0 : return ret;
595 : }
596 :
597 0 : if (data->resolved_ != true) {
598 : // If ARP is not resolved mac will be invalid
599 0 : return ret;
600 : }
601 :
602 0 : if (mac_.CompareTo(data->mac_) != 0) {
603 0 : mac_ = data->mac_;
604 0 : ret = true;
605 : }
606 :
607 0 : return ret;
608 : }
609 :
610 0 : const uint32_t NdpNH::vrf_id() const {
611 0 : return vrf_->vrf_id();
612 : }
613 :
614 0 : NdpNH::KeyPtr NdpNH::GetDBRequestKey() const {
615 0 : NextHopKey *key = new NdpNHKey(vrf_->GetName(), ip_, policy_);
616 0 : return DBEntryBase::KeyPtr(key);
617 : }
618 :
619 0 : const boost::uuids::uuid &NdpNH::GetIfUuid() const {
620 0 : return interface_->GetUuid();
621 : }
622 :
623 0 : void NdpNH::SendObjectLog(const NextHopTable *table,
624 : AgentLogEvent::type event) const {
625 0 : NextHopObjectLogInfo info;
626 :
627 0 : FillObjectLog(event, info);
628 :
629 0 : const Interface *intf = GetInterface();
630 0 : FillObjectLogIntf(intf, info);
631 :
632 0 : const VrfEntry *vrf = GetVrf();
633 0 : if (vrf) {
634 0 : info.set_vrf(vrf->GetName());
635 : }
636 0 : const IpAddress *ip = GetIp();
637 0 : info.set_dest_ip(ip->to_string());
638 :
639 0 : const unsigned char *m = GetMac().GetData();
640 0 : FillObjectLogMac(m, info);
641 :
642 0 : OPER_TRACE_ENTRY(NextHop, table, info);
643 0 : }
644 :
645 : /////////////////////////////////////////////////////////////////////////////
646 : // Interface NH routines
647 : /////////////////////////////////////////////////////////////////////////////
648 755 : NextHop *InterfaceNHKey::AllocEntry() const {
649 755 : Interface *intf = static_cast<Interface *>
650 755 : (Agent::GetInstance()->interface_table()->Find(intf_key_.get(), true));
651 755 : if (intf && intf->IsDeleted() && intf->GetRefCount() == 0) {
652 : //Ignore interface which are deleted, and there are no reference to it
653 : //taking reference on deleted interface with refcount 0, would result
654 : //in DB state set on deleted interface entry
655 0 : intf = NULL;
656 : }
657 755 : return new InterfaceNH(intf, policy_, flags_, dmac_);
658 : }
659 :
660 78 : bool InterfaceNH::CanAdd() const {
661 78 : if (interface_ == NULL) {
662 0 : LOG(ERROR, "Invalid Interface in InterfaceNH. Skip Add");
663 0 : return false;
664 : }
665 :
666 78 : return true;
667 : }
668 :
669 4425 : bool InterfaceNH::NextHopIsLess(const DBEntry &rhs) const {
670 4425 : const InterfaceNH &a = static_cast<const InterfaceNH &>(rhs);
671 :
672 4425 : if (interface_.get() != a.interface_.get()) {
673 2007 : return interface_.get() < a.interface_.get();
674 : }
675 :
676 2418 : if (flags_ != a.flags_) {
677 912 : return flags_ < a.flags_;
678 : }
679 :
680 1506 : return dmac_ < a.dmac_;
681 : }
682 :
683 91 : InterfaceNH::KeyPtr InterfaceNH::GetDBRequestKey() const {
684 : NextHopKey *key =
685 : new InterfaceNHKey(static_cast<InterfaceKey *>(
686 91 : interface_->GetDBRequestKey().release()),
687 91 : policy_, flags_, dmac_);
688 91 : return DBEntryBase::KeyPtr(key);
689 : }
690 :
691 0 : void InterfaceNH::SetKey(const DBRequestKey *k) {
692 0 : const InterfaceNHKey *key = static_cast<const InterfaceNHKey *>(k);
693 :
694 0 : NextHop::SetKey(k);
695 0 : interface_ = NextHopTable::GetInstance()->FindInterface(*key->intf_key_.get());
696 0 : flags_ = key->flags_;
697 0 : dmac_ = key->dmac_;
698 0 : }
699 :
700 153 : bool InterfaceNH::ChangeEntry(const DBRequest *req) {
701 : const InterfaceNHData *data =
702 153 : static_cast<const InterfaceNHData *>(req->data.get());
703 153 : bool ret = false;
704 :
705 153 : VrfEntry *vrf = static_cast<VrfEntry *>
706 153 : (Agent::GetInstance()->vrf_table()->FindActiveEntry(&data->vrf_key_));
707 153 : if (vrf_.get() != vrf) {
708 74 : vrf_ = vrf;
709 74 : ret = true;
710 : }
711 :
712 153 : if (learning_enabled_ != data->learning_enabled_) {
713 0 : learning_enabled_ = data->learning_enabled_;
714 0 : ret = true;
715 : }
716 :
717 153 : if (etree_leaf_ != data->etree_leaf_) {
718 0 : etree_leaf_ = data->etree_leaf_;
719 0 : ret = true;
720 : }
721 :
722 153 : if (layer2_control_word_ != data->layer2_control_word_) {
723 0 : layer2_control_word_ = data->layer2_control_word_;
724 0 : ret = true;
725 : }
726 :
727 153 : return ret;
728 : }
729 :
730 5 : const boost::uuids::uuid &InterfaceNH::GetIfUuid() const {
731 5 : return interface_->GetUuid();
732 : }
733 :
734 145 : static void AddInterfaceNH(const boost::uuids::uuid &intf_uuid,
735 : const MacAddress &dmac, uint8_t flags,
736 : bool policy, const string vrf_name,
737 : bool learning_enabled, bool etree_leaf,
738 : bool layer2_control_word, const string &name) {
739 145 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
740 145 : req.key.reset(new InterfaceNHKey
741 145 : (new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, intf_uuid, name),
742 145 : policy, flags, dmac));
743 290 : req.data.reset(new InterfaceNHData(vrf_name, learning_enabled,
744 145 : etree_leaf, layer2_control_word));
745 145 : Agent::GetInstance()->nexthop_table()->Process(req);
746 145 : }
747 :
748 : // Create 3 InterfaceNH for every Vm interface. One with policy another without
749 : // policy, third one is for multicast.
750 29 : void InterfaceNH::CreateL3VmInterfaceNH(const boost::uuids::uuid &intf_uuid,
751 : const MacAddress &dmac,
752 : const string &vrf_name,
753 : bool learning_enabled,
754 : const string &intf_name) {
755 29 : AddInterfaceNH(intf_uuid, dmac, InterfaceNHFlags::INET4, true, vrf_name,
756 : learning_enabled, false, false, intf_name);
757 29 : AddInterfaceNH(intf_uuid, dmac, InterfaceNHFlags::INET4, false, vrf_name,
758 : learning_enabled, false, false, intf_name);
759 29 : }
760 :
761 14 : void InterfaceNH::DeleteL3InterfaceNH(const boost::uuids::uuid &intf_uuid,
762 : const MacAddress &mac,
763 : const string &intf_name) {
764 14 : DeleteNH(intf_uuid, false, InterfaceNHFlags::INET4, mac, intf_name);
765 14 : DeleteNH(intf_uuid, true, InterfaceNHFlags::INET4, mac, intf_name);
766 14 : }
767 :
768 29 : void InterfaceNH::CreateL2VmInterfaceNH(const boost::uuids::uuid &intf_uuid,
769 : const MacAddress &dmac,
770 : const string &vrf_name,
771 : bool learning_enabled,
772 : bool etree_leaf,
773 : bool layer2_control_word,
774 : const string &intf_name) {
775 29 : AddInterfaceNH(intf_uuid, dmac, InterfaceNHFlags::BRIDGE, false, vrf_name,
776 : learning_enabled, etree_leaf, layer2_control_word, intf_name);
777 29 : AddInterfaceNH(intf_uuid, dmac, InterfaceNHFlags::BRIDGE, true, vrf_name,
778 : learning_enabled, etree_leaf, layer2_control_word, intf_name);
779 29 : }
780 :
781 14 : void InterfaceNH::DeleteL2InterfaceNH(const boost::uuids::uuid &intf_uuid,
782 : const MacAddress &dmac,
783 : const string &intf_name) {
784 14 : DeleteNH(intf_uuid, false, InterfaceNHFlags::BRIDGE, dmac, intf_name);
785 14 : DeleteNH(intf_uuid, true, InterfaceNHFlags::BRIDGE, dmac, intf_name);
786 14 : }
787 :
788 29 : void InterfaceNH::CreateMulticastVmInterfaceNH(const boost::uuids::uuid &intf_uuid,
789 : const MacAddress &dmac,
790 : const string &vrf_name,
791 : const string &intf_name) {
792 29 : AddInterfaceNH(intf_uuid, dmac, (InterfaceNHFlags::INET4 |
793 : InterfaceNHFlags::MULTICAST), false,
794 : vrf_name, false, false, false, intf_name);
795 29 : }
796 :
797 14 : void InterfaceNH::DeleteMulticastVmInterfaceNH(const boost::uuids::uuid &intf_uuid,
798 : const MacAddress &dmac,
799 : const string &intf_name) {
800 14 : DeleteNH(intf_uuid, false, (InterfaceNHFlags::INET4 |
801 : InterfaceNHFlags::MULTICAST),
802 : dmac, intf_name);
803 14 : }
804 :
805 70 : void InterfaceNH::DeleteNH(const boost::uuids::uuid &intf_uuid, bool policy,
806 : uint8_t flags, const MacAddress &mac,
807 : const string &intf_name) {
808 70 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
809 70 : req.key.reset(new InterfaceNHKey
810 70 : (new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, intf_uuid,
811 70 : intf_name),
812 70 : policy, flags, mac));
813 70 : req.data.reset(NULL);
814 70 : NextHopTable::GetInstance()->Process(req);
815 70 : }
816 :
817 0 : void InterfaceNH::CreateInetInterfaceNextHop(const string &ifname,
818 : const string &vrf_name,
819 : const MacAddress &mac) {
820 0 : DBRequest req;
821 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
822 :
823 0 : NextHopKey *key = new InterfaceNHKey(new InetInterfaceKey(ifname),
824 : false, InterfaceNHFlags::INET4,
825 0 : mac);
826 0 : req.key.reset(key);
827 :
828 0 : InterfaceNHData *data = new InterfaceNHData(vrf_name);
829 0 : req.data.reset(data);
830 0 : NextHopTable::GetInstance()->Process(req);
831 0 : }
832 :
833 0 : void InterfaceNH::DeleteInetInterfaceNextHop(const string &ifname,
834 : const MacAddress &mac) {
835 0 : DBRequest req;
836 0 : req.oper = DBRequest::DB_ENTRY_DELETE;
837 :
838 : NextHopKey *key = new InterfaceNHKey
839 0 : (new InetInterfaceKey(ifname), false,
840 0 : InterfaceNHFlags::INET4, mac);
841 0 : req.key.reset(key);
842 :
843 0 : req.data.reset(NULL);
844 0 : NextHopTable::GetInstance()->Process(req);
845 0 : }
846 :
847 2 : void InterfaceNH::CreatePacketInterfaceNh(Agent *agent, const string &ifname) {
848 2 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
849 :
850 : // create nexthop without policy
851 2 : req.key.reset(new InterfaceNHKey(
852 2 : new PacketInterfaceKey(boost::uuids::nil_uuid(), ifname), false,
853 2 : InterfaceNHFlags::INET4, agent->pkt_interface_mac()));
854 2 : req.data.reset(new InterfaceNHData(""));
855 2 : agent->nexthop_table()->Process(req);
856 :
857 : // create nexthop with relaxed policy
858 2 : req.key.reset(new InterfaceNHKey(
859 2 : new PacketInterfaceKey(boost::uuids::nil_uuid(), ifname), true,
860 2 : InterfaceNHFlags::INET4, agent->pkt_interface_mac()));
861 2 : req.data.reset(new InterfaceNHData(""));
862 2 : agent->nexthop_table()->Process(req);
863 2 : }
864 :
865 4 : void InterfaceNH::CreatePhysicalInterfaceNh(const string &ifname,
866 : const MacAddress &mac) {
867 4 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
868 8 : req.key.reset(new InterfaceNHKey(new PhysicalInterfaceKey(ifname),
869 4 : false, InterfaceNHFlags::INET4, mac));
870 4 : req.data.reset(new InterfaceNHData(Agent::GetInstance()->fabric_vrf_name()));
871 4 : NextHopTable::GetInstance()->Process(req);
872 4 : }
873 :
874 5 : void InterfaceNH::DeletePhysicalInterfaceNh(const string &ifname,
875 : const MacAddress &mac) {
876 5 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
877 10 : req.key.reset(new InterfaceNHKey(new PhysicalInterfaceKey(ifname),
878 5 : false, InterfaceNHFlags::INET4, mac));
879 5 : req.data.reset(NULL);
880 5 : NextHopTable::GetInstance()->Process(req);
881 5 : }
882 :
883 232 : void InterfaceNH::SendObjectLog(const NextHopTable *table,
884 : AgentLogEvent::type event) const {
885 232 : NextHopObjectLogInfo info;
886 :
887 232 : FillObjectLog(event, info);
888 :
889 232 : const Interface *intf = GetInterface();
890 232 : FillObjectLogIntf(intf, info);
891 :
892 232 : const unsigned char *m = (unsigned char *)GetDMac().GetData();
893 232 : FillObjectLogMac(m, info);
894 :
895 232 : OPER_TRACE_ENTRY(NextHop, table, info);
896 232 : }
897 :
898 153 : bool InterfaceNH::NeedMplsLabel() {
899 153 : const Interface *itf = GetInterface();
900 : //Label is required only for VMInterface and InetInterface
901 161 : if (dynamic_cast<const VmInterface *>(itf) ||
902 8 : dynamic_cast<const InetInterface *>(itf)) {
903 145 : return true;
904 : }
905 8 : return false;
906 : }
907 :
908 : /////////////////////////////////////////////////////////////////////////////
909 : // VRF NH routines
910 : /////////////////////////////////////////////////////////////////////////////
911 3 : bool VrfNH::CanAdd() const {
912 3 : if (vrf_ == NULL) {
913 0 : LOG(ERROR, "Invalid VRF in VrfNH. Skip Add");
914 0 : return false;
915 : }
916 :
917 3 : return true;
918 : }
919 :
920 15 : NextHop *VrfNHKey::AllocEntry() const {
921 15 : VrfEntry *vrf = static_cast<VrfEntry *>
922 15 : (Agent::GetInstance()->vrf_table()->Find(&vrf_key_, true));
923 15 : return new VrfNH(vrf, policy_, bridge_nh_);
924 : }
925 :
926 30 : bool VrfNH::NextHopIsLess(const DBEntry &rhs) const {
927 30 : const VrfNH &a = static_cast<const VrfNH &>(rhs);
928 :
929 30 : if (vrf_.get() != a.vrf_.get()) {
930 0 : return (vrf_.get() < a.vrf_.get());
931 : }
932 :
933 30 : return bridge_nh_ < a.bridge_nh_;
934 : }
935 :
936 0 : void VrfNH::SetKey(const DBRequestKey *k) {
937 0 : const VrfNHKey *key = static_cast<const VrfNHKey *>(k);
938 0 : NextHop::SetKey(k);
939 0 : vrf_ = NextHopTable::GetInstance()->FindVrfEntry(key->vrf_key_);
940 0 : bridge_nh_ = key->bridge_nh_;
941 0 : }
942 :
943 6 : VrfNH::KeyPtr VrfNH::GetDBRequestKey() const {
944 6 : NextHopKey *key = new VrfNHKey(vrf_->GetName(), policy_, bridge_nh_);
945 6 : return DBEntryBase::KeyPtr(key);
946 : }
947 :
948 3 : bool VrfNH::ChangeEntry(const DBRequest *req) {
949 3 : bool ret = false;
950 3 : const VrfNHData *data = static_cast<const VrfNHData *>(req->data.get());
951 :
952 3 : if (data->flood_unknown_unicast_ != flood_unknown_unicast_) {
953 0 : flood_unknown_unicast_ = data->flood_unknown_unicast_;
954 0 : ret = true;
955 : }
956 :
957 3 : if (learning_enabled_ != data->learning_enabled_) {
958 0 : learning_enabled_ = data->learning_enabled_;
959 0 : ret = true;
960 : }
961 :
962 3 : if (layer2_control_word_ != data->layer2_control_word_) {
963 1 : layer2_control_word_ = data->layer2_control_word_;
964 1 : ret = true;
965 : }
966 :
967 3 : return ret;
968 : }
969 :
970 6 : void VrfNH::SendObjectLog(const NextHopTable *table,
971 : AgentLogEvent::type event) const {
972 6 : NextHopObjectLogInfo info;
973 6 : FillObjectLog(event, info);
974 :
975 6 : const VrfEntry *vrf = GetVrf();
976 6 : if (vrf) {
977 6 : info.set_vrf(vrf->GetName());
978 : }
979 6 : OPER_TRACE_ENTRY(NextHop, table, info);
980 6 : }
981 :
982 : /////////////////////////////////////////////////////////////////////////////
983 : // Tunnel NH routines
984 : /////////////////////////////////////////////////////////////////////////////
985 58 : TunnelNH::TunnelNH(VrfEntry *vrf, const Ip4Address &sip, const Ip4Address &dip,
986 58 : bool policy, TunnelType type, const MacAddress &rewrite_dmac) :
987 58 : NextHop(NextHop::TUNNEL, false, policy), vrf_(vrf, this), sip_(sip),
988 58 : dip_(dip), tunnel_type_(type), tunnel_dst_rt_(NULL), crypt_(false),
989 116 : crypt_tunnel_available_(false), crypt_interface_(NULL), rewrite_dmac_(rewrite_dmac) {
990 :
991 116 : for (size_t i = 0;
992 116 : i < Agent::GetInstance()->vhost_default_gateway().size(); i++) {
993 58 : EncapDataPtr data(new EncapData(this, NULL));
994 58 : encap_list_.push_back(data);
995 58 : }
996 58 : }
997 :
998 116 : TunnelNH::~TunnelNH() {
999 116 : }
1000 :
1001 9 : bool TunnelNH::CanAdd() const {
1002 9 : if (vrf_ == NULL) {
1003 0 : LOG(ERROR, "Invalid VRF in TunnelNH. Skip Add");
1004 0 : return false;
1005 : }
1006 :
1007 9 : if (dip_.to_ulong() == 0) {
1008 0 : LOG(ERROR, "Invalid tunnel-destination in TunnelNH");
1009 : }
1010 :
1011 9 : return true;
1012 : }
1013 :
1014 58 : NextHop *TunnelNHKey::AllocEntry() const {
1015 58 : VrfEntry *vrf = static_cast<VrfEntry *>
1016 58 : (Agent::GetInstance()->vrf_table()->Find(&vrf_key_, true));
1017 58 : return new TunnelNH(vrf, sip_, dip_, policy_, tunnel_type_,
1018 116 : rewrite_dmac_);
1019 : }
1020 :
1021 151 : bool TunnelNH::NextHopIsLess(const DBEntry &rhs) const {
1022 151 : const TunnelNH &a = static_cast<const TunnelNH &>(rhs);
1023 :
1024 : bool ret;
1025 151 : if (vrf_.get() != a.vrf_.get()) {
1026 0 : return vrf_.get() < a.vrf_.get();
1027 : }
1028 :
1029 151 : if (sip_ != a.sip_) {
1030 0 : return sip_ < a.sip_;
1031 : }
1032 :
1033 151 : if (dip_ != a.dip_) {
1034 47 : return dip_ < a.dip_;
1035 : }
1036 :
1037 104 : if (!tunnel_type_.Compare(a.tunnel_type_)) {
1038 12 : return tunnel_type_.IsLess(a.tunnel_type_);
1039 : }
1040 :
1041 92 : if (rewrite_dmac_ != a.rewrite_dmac_) {
1042 0 : return rewrite_dmac_ < a.rewrite_dmac_;
1043 : }
1044 92 : ret = TunnelNextHopIsLess(rhs);
1045 92 : return ret;
1046 : }
1047 :
1048 0 : void TunnelNH::SetKey(const DBRequestKey *k) {
1049 0 : const TunnelNHKey *key = static_cast<const TunnelNHKey *>(k);
1050 0 : NextHop::SetKey(k);
1051 0 : vrf_ = NextHopTable::GetInstance()->FindVrfEntry(key->vrf_key_);
1052 0 : sip_ = key->sip_;
1053 0 : dip_ = key->dip_;
1054 0 : tunnel_type_ = key->tunnel_type_;
1055 0 : policy_ = key->policy_;
1056 0 : rewrite_dmac_ = key->rewrite_dmac_;
1057 0 : }
1058 :
1059 18 : TunnelNH::KeyPtr TunnelNH::GetDBRequestKey() const {
1060 18 : NextHopKey *key = new TunnelNHKey(vrf_->GetName(), sip_, dip_, policy_,
1061 18 : tunnel_type_, rewrite_dmac_);
1062 18 : return DBEntryBase::KeyPtr(key);
1063 : }
1064 :
1065 33 : const uint32_t TunnelNH::vrf_id() const {
1066 33 : return vrf_->vrf_id();
1067 : }
1068 :
1069 11 : bool TunnelNH::ChangeEntry(const DBRequest *req) {
1070 11 : bool ret = false;
1071 11 : bool valid = false;
1072 :
1073 : InetUnicastAgentRouteTable *rt_table =
1074 11 : (GetVrf()->GetInet4UnicastRouteTable());
1075 11 : InetUnicastRouteEntry *rt = rt_table->FindLPM(dip_);
1076 : const NextHop *anh;
1077 11 : if (!rt) {
1078 : //No route to reach destination, add to unresolved list
1079 0 : valid = false;
1080 0 : rt_table->AddUnresolvedNH(this);
1081 11 : } else if ((anh = rt->GetActiveNextHop()) == NULL) {
1082 0 : valid = false;
1083 0 : rt_table->AddUnresolvedNH(this);
1084 11 : } else if (anh->GetType() == NextHop::RESOLVE) {
1085 : //Trigger ARP resolution
1086 0 : valid = false;
1087 0 : rt_table->AddUnresolvedNH(this);
1088 :
1089 0 : const ResolveNH *nh = static_cast<const ResolveNH *>(anh);
1090 0 : std::string nexthop_vrf = nh->get_interface()->vrf()->GetName();
1091 0 : if (nh->get_interface()->vrf()->forwarding_vrf()) {
1092 0 : nexthop_vrf = nh->get_interface()->vrf()->forwarding_vrf()->GetName();
1093 : }
1094 :
1095 0 : InetUnicastAgentRouteTable::AddArpReq(GetVrf()->GetName(), dip_,
1096 : nexthop_vrf,
1097 : nh->get_interface(),
1098 0 : nh->PolicyEnabled(),
1099 : rt->GetActivePath()->dest_vn_list(),
1100 : rt->GetActivePath()->sg_list(),
1101 : rt->GetActivePath()->tag_list());
1102 0 : rt = NULL;
1103 0 : } else {
1104 11 : valid = anh->IsValid();
1105 : }
1106 :
1107 11 : if (valid != valid_) {
1108 0 : valid_ = valid;
1109 0 : ret = true;
1110 : }
1111 :
1112 11 : if (tunnel_dst_rt_ != rt) {
1113 9 : tunnel_dst_rt_ = rt;
1114 9 : ret = true;
1115 : }
1116 :
1117 11 : if (encap_list_[0]->arp_rt_.get() != rt) {
1118 9 : encap_list_[0]->arp_rt_.reset(rt);
1119 9 : ret = true;
1120 : }
1121 :
1122 11 : Agent *agent = Agent::GetInstance();
1123 11 : if (agent->crypt_interface() != crypt_interface_) {
1124 0 : crypt_interface_ = agent->crypt_interface();
1125 0 : ret = true;
1126 : }
1127 : bool crypt, crypt_tunnel_available;
1128 11 : agent->crypt_tunnel_table()->CryptAvailability(dip_.to_string(),
1129 : crypt, crypt_tunnel_available);
1130 11 : if (crypt_tunnel_available != crypt_tunnel_available_) {
1131 0 : crypt_tunnel_available_ = crypt_tunnel_available;
1132 0 : ret = true;
1133 : }
1134 11 : if (crypt != crypt_) {
1135 0 : crypt_ = crypt;
1136 0 : ret = true;
1137 : }
1138 :
1139 : //If route is present, check if the interface or mac
1140 : //address changed for the dependent route
1141 11 : if (valid_ && rt) {
1142 : //Check if the interface or mac
1143 : //of the dependent route has changed
1144 : //only then notify the route
1145 0 : const NextHop *active_nh = rt->GetActiveNextHop();
1146 0 : if (active_nh == NULL) {
1147 0 : return ret;
1148 : }
1149 0 : const Interface *intf = NULL;
1150 0 : MacAddress dmac;
1151 0 : if (active_nh->GetType() == NextHop::ARP) {
1152 0 : const ArpNH *arp_nh = static_cast<const ArpNH *>(active_nh);
1153 0 : dmac = arp_nh->GetMac();
1154 0 : intf = arp_nh->GetInterface();
1155 0 : } else if (active_nh->GetType() == NextHop::NDP) {
1156 0 : const NdpNH *ndp_nh = static_cast<const NdpNH *>(active_nh);
1157 0 : dmac = ndp_nh->GetMac();
1158 0 : intf = ndp_nh->GetInterface();
1159 0 : } else if (active_nh->GetType() == NextHop::INTERFACE) {
1160 0 : const InterfaceNH *intf_nh =
1161 : static_cast<const InterfaceNH *>(active_nh);
1162 0 : intf = intf_nh->GetInterface();
1163 0 : encap_list_[0]->dmac_.Zero();
1164 : }
1165 :
1166 0 : if (encap_list_[0]->dmac_ != dmac) {
1167 0 : encap_list_[0]->dmac_ = dmac;
1168 0 : ret = true;
1169 : }
1170 :
1171 0 : if (encap_list_[0]->interface_ != intf) {
1172 0 : encap_list_[0]->interface_ = intf;
1173 0 : ret = true;
1174 : }
1175 :
1176 0 : if (active_nh->GetType() == NextHop::COMPOSITE) {
1177 0 : valid_ = false;
1178 0 : const CompositeNH *cnh = dynamic_cast<const CompositeNH*>(active_nh);
1179 : ComponentNHList::const_iterator component_nh_it =
1180 0 : cnh->begin();
1181 0 : int i = 0;
1182 0 : while (component_nh_it != cnh->end()) {
1183 0 : const NextHop *component_nh = NULL;
1184 0 : if (*component_nh_it) {
1185 0 : component_nh = (*component_nh_it)->nh();
1186 0 : if (component_nh->GetType() == NextHop::ARP) {
1187 0 : const ArpNH *anh = dynamic_cast<const ArpNH*>(component_nh);
1188 0 : encap_list_[i]->dmac_ = anh->GetMac();
1189 0 : encap_list_[i]->interface_ = anh->GetInterface();
1190 0 : encap_list_[i]->valid_ = anh->IsValid();
1191 0 : rt = rt_table->FindLPM(agent->vhost_default_gateway()[i]);
1192 0 : encap_list_[i]->arp_rt_.reset(rt);
1193 : /* if any single encap is valid then set tunnel flag to valid */
1194 0 : if (encap_list_[i]->valid_) {
1195 0 : valid_ = true;
1196 : }
1197 0 : ret = true;
1198 0 : i++;
1199 : }
1200 : }
1201 0 : component_nh_it++;
1202 : }
1203 0 : return ret;
1204 : }
1205 : }
1206 :
1207 11 : return ret;
1208 : }
1209 :
1210 9 : void TunnelNH::Delete(const DBRequest *req) {
1211 : InetUnicastAgentRouteTable *rt_table =
1212 9 : (GetVrf()->GetInet4UnicastRouteTable());
1213 9 : if (rt_table)
1214 9 : rt_table->RemoveUnresolvedNH(this);
1215 9 : }
1216 :
1217 20 : void TunnelNH::SendObjectLog(const NextHopTable *table,
1218 : AgentLogEvent::type event) const {
1219 20 : NextHopObjectLogInfo info;
1220 20 : FillObjectLog(event, info);
1221 :
1222 20 : const VrfEntry *vrf = GetVrf();
1223 20 : if (vrf) {
1224 20 : info.set_vrf(vrf->GetName());
1225 : }
1226 20 : const Ip4Address *sip = GetSip();
1227 20 : info.set_source_ip(sip->to_string());
1228 20 : const Ip4Address *dip = GetDip();
1229 20 : info.set_dest_ip(dip->to_string());
1230 20 : info.set_tunnel_type(tunnel_type_.ToString());
1231 20 : if (crypt_)
1232 0 : info.set_crypt_traffic("All");
1233 20 : if (crypt_tunnel_available_)
1234 0 : info.set_crypt_tunnel_available("Yes");
1235 20 : if (crypt_interface_)
1236 0 : info.set_crypt_interface(GetCryptInterface()->name());
1237 20 : info.set_rewrite_dmac(rewrite_dmac_.ToString());
1238 20 : OPER_TRACE_ENTRY(NextHop, table, info);
1239 20 : }
1240 :
1241 : /////////////////////////////////////////////////////////////////////////////
1242 : // Labelled Tunnel NH routines
1243 : /////////////////////////////////////////////////////////////////////////////
1244 :
1245 0 : LabelledTunnelNH::LabelledTunnelNH(VrfEntry *vrf, const Ip4Address &sip, const Ip4Address &dip,
1246 : bool policy, TunnelType type, const MacAddress &rewrite_dmac,
1247 0 : uint32_t label) :
1248 0 : TunnelNH(vrf, sip, dip, policy, type, rewrite_dmac), transport_mpls_label_(label) {
1249 0 : }
1250 :
1251 0 : LabelledTunnelNH::~LabelledTunnelNH() {
1252 0 : }
1253 :
1254 0 : NextHop *LabelledTunnelNHKey::AllocEntry() const {
1255 0 : VrfEntry *vrf = static_cast<VrfEntry *>
1256 0 : (Agent::GetInstance()->vrf_table()->Find(&vrf_key_, true));
1257 0 : return new LabelledTunnelNH(vrf, sip_, dip_, policy_, tunnel_type_,
1258 0 : rewrite_dmac_, transport_mpls_label_);
1259 : }
1260 :
1261 0 : LabelledTunnelNH::KeyPtr LabelledTunnelNH::GetDBRequestKey() const {
1262 0 : NextHopKey *key = new LabelledTunnelNHKey(vrf_->GetName(), sip_, dip_,
1263 0 : policy_,tunnel_type_, rewrite_dmac_, transport_mpls_label_);
1264 0 : return DBEntryBase::KeyPtr(key);
1265 : }
1266 :
1267 0 : bool LabelledTunnelNH::TunnelNextHopIsLess(const DBEntry &rhs) const {
1268 0 : const LabelledTunnelNH &a = static_cast<const LabelledTunnelNH &>(rhs);
1269 :
1270 0 : return (transport_mpls_label_ < a.transport_mpls_label_);
1271 : }
1272 :
1273 0 : bool LabelledTunnelNH::ChangeEntry(const DBRequest *req) {
1274 0 : bool ret = false;
1275 0 : ret = TunnelNH::ChangeEntry(req);
1276 : TunnelType::Type transport_tunnel_type =
1277 0 : TunnelType::ComputeType(TunnelType::MplsType());
1278 0 : if (transport_tunnel_type != transport_tunnel_type_) {
1279 0 : transport_tunnel_type_ = transport_tunnel_type;
1280 0 : ret = true;
1281 : }
1282 0 : return ret;
1283 : }
1284 :
1285 0 : void LabelledTunnelNH::SendObjectLog(const NextHopTable *table,
1286 : AgentLogEvent::type event) const {
1287 0 : NextHopObjectLogInfo info;
1288 0 : FillObjectLog(event, info);
1289 :
1290 0 : const VrfEntry *vrf = GetVrf();
1291 0 : if (vrf) {
1292 0 : info.set_vrf(vrf->GetName());
1293 : }
1294 0 : const Ip4Address *sip = GetSip();
1295 0 : info.set_source_ip(sip->to_string());
1296 0 : const Ip4Address *dip = GetDip();
1297 0 : info.set_dest_ip(dip->to_string());
1298 0 : info.set_tunnel_type(tunnel_type_.ToString());
1299 0 : if (crypt_)
1300 0 : info.set_crypt_traffic("All");
1301 0 : if (crypt_tunnel_available_)
1302 0 : info.set_crypt_tunnel_available("Yes");
1303 0 : if (crypt_interface_)
1304 0 : info.set_crypt_interface(GetCryptInterface()->name());
1305 0 : info.set_rewrite_dmac(rewrite_dmac_.ToString());
1306 0 : info.set_transport_mpls_label(transport_mpls_label_);
1307 0 : OPER_TRACE_ENTRY(NextHop, table, info);
1308 0 : }
1309 : /////////////////////////////////////////////////////////////////////////////
1310 : // Mirror NH routines
1311 : /////////////////////////////////////////////////////////////////////////////
1312 0 : MirrorNH::MirrorNH(const VrfKey &vkey, const IpAddress &sip, uint16_t sport,
1313 0 : const IpAddress &dip, uint16_t dport):
1314 0 : NextHop(NextHop::MIRROR, false, false), vrf_name_(vkey.name_),
1315 0 : sip_(sip), sport_(sport), dip_(dip), dport_(dport), arp_rt_(this),
1316 0 : interface_(NULL), dmac_() {
1317 0 : VrfEntry *vrf = static_cast<VrfEntry *>
1318 0 : (Agent::GetInstance()->vrf_table()->Find(&vkey, true));
1319 0 : vrf_ = VrfEntryRef(vrf, this);
1320 0 : }
1321 :
1322 0 : bool MirrorNH::CanAdd() const {
1323 : /* For service-chain based mirroring, vrf will always be empty. In this
1324 : * case we should create MirrorNH even when VRF is NULL */
1325 0 : if (!vrf_name_.empty() && vrf_ == NULL) {
1326 0 : LOG(ERROR, "Invalid VRF in mirror NH");
1327 0 : return false;
1328 : }
1329 :
1330 0 : return true;
1331 : }
1332 :
1333 0 : NextHop *MirrorNHKey::AllocEntry() const {
1334 0 : return new MirrorNH(vrf_key_, sip_, sport_, dip_, dport_);
1335 : }
1336 :
1337 0 : bool MirrorNH::NextHopIsLess(const DBEntry &rhs) const {
1338 0 : const MirrorNH &a = static_cast<const MirrorNH &>(rhs);
1339 :
1340 0 : if ((vrf_.get() != a.vrf_.get())) {
1341 0 : return vrf_.get() < a.vrf_.get();
1342 : }
1343 :
1344 0 : if (dip_ != a.dip_) {
1345 0 : return dip_ < a.dip_;
1346 : }
1347 :
1348 0 : return (dport_ < a.dport_);
1349 : }
1350 :
1351 0 : const uint32_t MirrorNH::vrf_id() const {
1352 0 : return (vrf_ ? vrf_->vrf_id() : (uint32_t)-1);
1353 : }
1354 :
1355 0 : void MirrorNH::SetKey(const DBRequestKey *k) {
1356 0 : const MirrorNHKey *key = static_cast<const MirrorNHKey *>(k);
1357 0 : NextHop::SetKey(k);
1358 0 : vrf_ = NextHopTable::GetInstance()->FindVrfEntry(key->vrf_key_);
1359 0 : sip_ = key->sip_;
1360 0 : sport_ = key->sport_;
1361 0 : dip_ = key->dip_;
1362 0 : dport_ = key->dport_;
1363 0 : }
1364 :
1365 0 : MirrorNH::KeyPtr MirrorNH::GetDBRequestKey() const {
1366 0 : NextHopKey *key = new MirrorNHKey((vrf_ ? vrf_->GetName() : ""),
1367 0 : sip_, sport_, dip_, dport_);
1368 0 : return DBEntryBase::KeyPtr(key);
1369 : }
1370 :
1371 0 : InetUnicastAgentRouteTable *MirrorNH::GetRouteTable() {
1372 0 : InetUnicastAgentRouteTable *rt_table = NULL;
1373 0 : if (dip_.is_v4()) {
1374 0 : rt_table = GetVrf()->GetInet4UnicastRouteTable();
1375 : } else {
1376 0 : rt_table = GetVrf()->GetInet6UnicastRouteTable();
1377 : }
1378 0 : return rt_table;
1379 : }
1380 :
1381 0 : bool MirrorNH::ChangeEntry(const DBRequest *req) {
1382 0 : bool ret = false;
1383 0 : bool valid = false;
1384 :
1385 0 : if (GetVrf() == NULL) {
1386 0 : valid_ = true;
1387 0 : return true;
1388 : }
1389 0 : InetUnicastAgentRouteTable *rt_table = GetRouteTable();
1390 0 : InetUnicastRouteEntry *rt = rt_table->FindLPM(dip_);
1391 : const NextHop *anh;
1392 0 : if (!rt) {
1393 : //No route to reach destination, add to unresolved list
1394 0 : valid = false;
1395 0 : rt_table->AddUnresolvedNH(this);
1396 0 : } else if ((anh = rt->GetActiveNextHop()) == NULL) {
1397 0 : valid = false;
1398 0 : rt_table->AddUnresolvedNH(this);
1399 0 : } else if ((anh->GetType() == NextHop::RESOLVE) &&
1400 0 : (GetVrf()->GetName() == Agent::GetInstance()->fabric_vrf_name())) {
1401 : //Trigger ARP resolution
1402 0 : valid = false;
1403 0 : rt_table->AddUnresolvedNH(this);
1404 :
1405 0 : const ResolveNH *nh = static_cast<const ResolveNH *>(anh);
1406 0 : std::string nexthop_vrf = nh->get_interface()->vrf()->GetName();
1407 0 : if (nh->get_interface()->vrf()->forwarding_vrf()) {
1408 0 : nexthop_vrf = nh->get_interface()->vrf()->forwarding_vrf()->GetName();
1409 : }
1410 :
1411 0 : InetUnicastAgentRouteTable::AddArpReq(GetVrf()->GetName(), dip_.to_v4(),
1412 : nexthop_vrf,
1413 : nh->get_interface(),
1414 0 : nh->PolicyEnabled(),
1415 : rt->GetActivePath()->dest_vn_list(),
1416 : rt->GetActivePath()->sg_list(),
1417 : rt->GetActivePath()->tag_list());
1418 0 : rt = NULL;
1419 0 : } else {
1420 0 : valid = anh->IsValid();
1421 : }
1422 :
1423 0 : if (valid != valid_) {
1424 0 : valid_ = valid;
1425 0 : ret = true;
1426 : }
1427 :
1428 0 : if (dip_.is_v4() && (arp_rt_.get() != rt)) {
1429 0 : arp_rt_.reset(rt);
1430 0 : ret = true;
1431 : }
1432 :
1433 : //If route is present, check if the interface or mac
1434 : //address changed for the dependent route
1435 0 : if (valid_ && rt) {
1436 : //Check if the interface or mac
1437 : //of the dependent route has changed
1438 : //only then notify the route
1439 0 : const NextHop *active_nh = rt->GetActiveNextHop();
1440 0 : const Interface *intf = NULL;
1441 0 : MacAddress dmac;
1442 0 : if (active_nh->GetType() == NextHop::ARP) {
1443 0 : const ArpNH *arp_nh = static_cast<const ArpNH *>(active_nh);
1444 0 : dmac = arp_nh->GetMac();
1445 0 : intf = arp_nh->GetInterface();
1446 0 : } else if (active_nh->GetType() == NextHop::NDP) {
1447 0 : const NdpNH *ndp_nh = static_cast<const NdpNH *>(active_nh);
1448 0 : dmac = ndp_nh->GetMac();
1449 0 : intf = ndp_nh->GetInterface();
1450 0 : } else if (active_nh->GetType() == NextHop::INTERFACE) {
1451 0 : const InterfaceNH *intf_nh =
1452 : static_cast<const InterfaceNH *>(active_nh);
1453 0 : intf = intf_nh->GetInterface();
1454 0 : dmac_.Zero();
1455 : }
1456 :
1457 0 : if (dmac_ != dmac) {
1458 0 : dmac_ = dmac;
1459 0 : ret = true;
1460 : }
1461 :
1462 0 : if (interface_ != intf) {
1463 0 : interface_ = intf;
1464 0 : ret = true;
1465 : }
1466 : }
1467 :
1468 0 : return ret;
1469 : }
1470 :
1471 0 : void MirrorNH::Delete(const DBRequest *req) {
1472 0 : if (!GetVrf()) {
1473 0 : return;
1474 : }
1475 0 : InetUnicastAgentRouteTable *rt_table = GetRouteTable();
1476 0 : rt_table->RemoveUnresolvedNH(this);
1477 : }
1478 :
1479 0 : void MirrorNH::SendObjectLog(const NextHopTable *table,
1480 : AgentLogEvent::type event) const {
1481 0 : NextHopObjectLogInfo info;
1482 :
1483 0 : FillObjectLog(event, info);
1484 :
1485 0 : const VrfEntry *vrf = GetVrf();
1486 0 : if (vrf) {
1487 0 : info.set_vrf(vrf->GetName());
1488 : }
1489 0 : const IpAddress *sip = GetSip();
1490 0 : info.set_source_ip(sip->to_string());
1491 0 : const IpAddress *dip = GetDip();
1492 0 : info.set_dest_ip(dip->to_string());
1493 0 : info.set_source_port((short int)GetSPort());
1494 0 : info.set_dest_port((short int)GetDPort());
1495 0 : OPER_TRACE_ENTRY(NextHop, table, info);
1496 0 : }
1497 :
1498 : /////////////////////////////////////////////////////////////////////////////
1499 : // ReceiveNH routines
1500 : /////////////////////////////////////////////////////////////////////////////
1501 4 : bool ReceiveNH::CanAdd() const {
1502 4 : if (interface_ == NULL) {
1503 0 : LOG(ERROR, "Invalid Interface in ReceiveNH. Skip Add");
1504 0 : return false;
1505 : }
1506 :
1507 4 : return true;
1508 : }
1509 :
1510 45 : NextHop *ReceiveNHKey::AllocEntry() const {
1511 45 : Interface *intf = static_cast<Interface *>
1512 45 : (Agent::GetInstance()->interface_table()->Find(intf_key_.get(), true));
1513 45 : if (intf && intf->IsDeleted() && intf->GetRefCount() == 0) {
1514 : // Ignore interface which are deleted, and there are no reference to it
1515 : // taking reference on deleted interface with refcount 0, would result
1516 : // in DB state set on deleted interface entry
1517 0 : intf = NULL;
1518 : }
1519 45 : return new ReceiveNH(intf, policy_);
1520 : }
1521 :
1522 0 : void ReceiveNH::SetKey(const DBRequestKey *key) {
1523 0 : const ReceiveNHKey *nh_key = static_cast<const ReceiveNHKey *>(key);
1524 0 : NextHop::SetKey(key);
1525 0 : interface_ = NextHopTable::GetInstance()->FindInterface(*nh_key->intf_key_.get());
1526 0 : };
1527 :
1528 : // Create 2 ReceiveNH for every VPort. One with policy another without
1529 : // policy
1530 8 : void ReceiveNH::Create(NextHopTable *table, const Interface *intf,
1531 : bool policy) {
1532 8 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1533 : InterfaceKey *key =
1534 8 : static_cast<InterfaceKey *>(intf->GetDBRequestKey().get())->Clone();
1535 8 : req.key.reset(new ReceiveNHKey(key, policy));
1536 8 : req.data.reset(new ReceiveNHData());
1537 8 : table->Process(req);
1538 :
1539 8 : key = static_cast<InterfaceKey *>(intf->GetDBRequestKey().get())->Clone();
1540 8 : req.key.reset(new ReceiveNHKey(key, true));
1541 8 : table->Process(req);
1542 8 : }
1543 :
1544 0 : void ReceiveNH::Delete(NextHopTable *table, const Interface *intf,
1545 : bool policy) {
1546 0 : DBRequest req(DBRequest::DB_ENTRY_DELETE);
1547 : InterfaceKey *key =
1548 0 : static_cast<InterfaceKey *>(intf->GetDBRequestKey().get())->Clone();
1549 0 : req.key.reset(new ReceiveNHKey(key, policy));
1550 0 : req.data.reset(NULL);
1551 0 : table->Process(req);
1552 :
1553 0 : key = static_cast<InterfaceKey *>(intf->GetDBRequestKey().get())->Clone();
1554 0 : req.key.reset(new ReceiveNHKey(key, true));
1555 0 : table->Process(req);
1556 0 : }
1557 :
1558 20 : void ReceiveNH::SendObjectLog(const NextHopTable *table,
1559 : AgentLogEvent::type event) const {
1560 20 : NextHopObjectLogInfo info;
1561 :
1562 20 : FillObjectLog(event, info);
1563 :
1564 20 : const Interface *intf = GetInterface();
1565 20 : FillObjectLogIntf(intf, info);
1566 :
1567 20 : OPER_TRACE_ENTRY(NextHop, table, info);
1568 20 : }
1569 :
1570 : /////////////////////////////////////////////////////////////////////////////
1571 : // ResolveNH routines
1572 : /////////////////////////////////////////////////////////////////////////////
1573 8 : NextHop *ResolveNHKey::AllocEntry() const {
1574 8 : Interface *intf = static_cast<Interface *>
1575 8 : (Agent::GetInstance()->interface_table()->Find(intf_key_.get(), true));
1576 8 : return new ResolveNH(intf, policy_);
1577 : }
1578 :
1579 2 : bool ResolveNH::CanAdd() const {
1580 2 : return true;
1581 : }
1582 :
1583 0 : void ResolveNH::Create(const InterfaceKey *intf, bool policy) {
1584 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1585 0 : req.key.reset(new ResolveNHKey(intf, policy));
1586 0 : req.data.reset(new ResolveNHData());
1587 0 : NextHopTable::GetInstance()->Process(req);
1588 0 : }
1589 :
1590 2 : void ResolveNH::CreateReq(const InterfaceKey *intf, bool policy) {
1591 2 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1592 2 : req.key.reset(new ResolveNHKey(intf, policy));
1593 2 : req.data.reset(new ResolveNHData());
1594 2 : NextHopTable::GetInstance()->Enqueue(&req);
1595 2 : }
1596 :
1597 : /////////////////////////////////////////////////////////////////////////////
1598 : // DiscardNH routines
1599 : /////////////////////////////////////////////////////////////////////////////
1600 22 : NextHop *DiscardNHKey::AllocEntry() const {
1601 22 : return new DiscardNH();
1602 : }
1603 :
1604 2 : bool DiscardNH::CanAdd() const {
1605 2 : return true;
1606 : }
1607 :
1608 2 : void DiscardNH::Create( ) {
1609 2 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1610 2 : req.key.reset(new DiscardNHKey());
1611 2 : req.data.reset(new DiscardNHData());
1612 2 : NextHopTable::GetInstance()->Process(req);
1613 2 : }
1614 :
1615 : /////////////////////////////////////////////////////////////////////////////
1616 : // L2ReceiveNH routines
1617 : /////////////////////////////////////////////////////////////////////////////
1618 10 : NextHop *L2ReceiveNHKey::AllocEntry() const {
1619 10 : return new L2ReceiveNH();
1620 : }
1621 :
1622 2 : bool L2ReceiveNH::CanAdd() const {
1623 2 : return true;
1624 : }
1625 :
1626 2 : void L2ReceiveNH::Create( ) {
1627 2 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1628 2 : req.key.reset(new L2ReceiveNHKey());
1629 2 : req.data.reset(new L2ReceiveNHData());
1630 2 : NextHopTable::GetInstance()->Process(req);
1631 2 : }
1632 :
1633 : /////////////////////////////////////////////////////////////////////////////
1634 : // VLAN NH routines
1635 : /////////////////////////////////////////////////////////////////////////////
1636 0 : bool VlanNH::CanAdd() const {
1637 0 : if (interface_ == NULL) {
1638 0 : LOG(ERROR, "Invalid Interface in VlanNH. Skip Add");
1639 0 : return false;
1640 : }
1641 :
1642 0 : return true;
1643 : }
1644 :
1645 0 : NextHop *VlanNHKey::AllocEntry() const {
1646 0 : Interface *intf = static_cast<Interface *>
1647 0 : (Agent::GetInstance()->interface_table()->Find(intf_key_.get(), true));
1648 0 : return new VlanNH(intf, vlan_tag_);
1649 : }
1650 :
1651 0 : bool VlanNH::NextHopIsLess(const DBEntry &rhs) const {
1652 0 : const VlanNH &a = static_cast<const VlanNH &>(rhs);
1653 :
1654 0 : if (interface_.get() != a.interface_.get()) {
1655 0 : return interface_.get() < a.interface_.get();
1656 : }
1657 :
1658 0 : return vlan_tag_ < a.vlan_tag_;
1659 : }
1660 :
1661 0 : VlanNH::KeyPtr VlanNH::GetDBRequestKey() const {
1662 0 : VlanNHKey *key = new VlanNHKey(interface_->GetUuid(), vlan_tag_);
1663 0 : return DBEntryBase::KeyPtr(key);
1664 : }
1665 :
1666 0 : void VlanNH::SetKey(const DBRequestKey *k) {
1667 0 : const VlanNHKey *key = static_cast<const VlanNHKey *>(k);
1668 :
1669 0 : NextHop::SetKey(k);
1670 0 : interface_ = NextHopTable::GetInstance()->FindInterface(*key->intf_key_.get());
1671 0 : vlan_tag_ = key->vlan_tag_;
1672 0 : }
1673 :
1674 0 : bool VlanNH::ChangeEntry(const DBRequest *req) {
1675 0 : const VlanNHData *data = static_cast<const VlanNHData *>(req->data.get());
1676 0 : bool ret = false;
1677 :
1678 0 : VrfEntry *vrf = static_cast<VrfEntry *>
1679 0 : (Agent::GetInstance()->vrf_table()->FindActiveEntry(&data->vrf_key_));
1680 0 : if (vrf_.get() != vrf) {
1681 0 : vrf_ = vrf;
1682 0 : ret = true;
1683 : }
1684 :
1685 0 : if (smac_.CompareTo(data->smac_) != 0) {
1686 0 : smac_ = data->smac_;
1687 0 : ret = true;
1688 : }
1689 :
1690 0 : if (dmac_.CompareTo(data->dmac_) != 0) {
1691 0 : dmac_ = data->dmac_;
1692 0 : ret = true;
1693 : }
1694 :
1695 0 : return ret;
1696 : }
1697 :
1698 0 : const boost::uuids::uuid &VlanNH::GetIfUuid() const {
1699 0 : return interface_->GetUuid();
1700 : }
1701 :
1702 : // Create VlanNH for a VPort
1703 0 : void VlanNH::Create(const boost::uuids::uuid &intf_uuid, uint16_t vlan_tag,
1704 : const string &vrf_name, const MacAddress &smac,
1705 : const MacAddress &dmac) {
1706 0 : DBRequest req;
1707 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
1708 :
1709 0 : NextHopKey *key = new VlanNHKey(intf_uuid, vlan_tag);
1710 0 : req.key.reset(key);
1711 :
1712 0 : VlanNHData *data = new VlanNHData(vrf_name, smac, dmac);
1713 0 : req.data.reset(data);
1714 0 : NextHopTable::GetInstance()->Process(req);
1715 0 : }
1716 :
1717 0 : void VlanNH::Delete(const boost::uuids::uuid &intf_uuid, uint16_t vlan_tag) {
1718 0 : DBRequest req;
1719 0 : req.oper = DBRequest::DB_ENTRY_DELETE;
1720 :
1721 0 : NextHopKey *key = new VlanNHKey(intf_uuid, vlan_tag);
1722 0 : req.key.reset(key);
1723 :
1724 0 : req.data.reset(NULL);
1725 0 : NextHopTable::GetInstance()->Process(req);
1726 0 : }
1727 :
1728 : // Create VlanNH for a VPort
1729 0 : void VlanNH::CreateReq(const boost::uuids::uuid &intf_uuid, uint16_t vlan_tag,
1730 : const string &vrf_name, const MacAddress &smac,
1731 : const MacAddress &dmac) {
1732 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
1733 0 : req.key.reset(new VlanNHKey(intf_uuid, vlan_tag));
1734 0 : req.data.reset(new VlanNHData(vrf_name, smac, dmac));
1735 0 : NextHopTable::GetInstance()->Enqueue(&req);
1736 0 : }
1737 :
1738 0 : void VlanNH::DeleteReq(const boost::uuids::uuid &intf_uuid, uint16_t vlan_tag) {
1739 0 : DBRequest req;
1740 0 : req.oper = DBRequest::DB_ENTRY_DELETE;
1741 :
1742 0 : NextHopKey *key = new VlanNHKey(intf_uuid, vlan_tag);
1743 0 : req.key.reset(key);
1744 :
1745 0 : req.data.reset(NULL);
1746 0 : NextHopTable::GetInstance()->Enqueue(&req);
1747 0 : }
1748 :
1749 :
1750 0 : VlanNH *VlanNH::Find(const boost::uuids::uuid &intf_uuid, uint16_t vlan_tag) {
1751 0 : VlanNHKey key(intf_uuid, vlan_tag);
1752 0 : return static_cast<VlanNH *>(NextHopTable::GetInstance()->FindActiveEntry(&key));
1753 0 : }
1754 :
1755 0 : void VlanNH::SendObjectLog(const NextHopTable *table,
1756 : AgentLogEvent::type event) const {
1757 0 : NextHopObjectLogInfo info;
1758 :
1759 0 : FillObjectLog(event, info);
1760 :
1761 0 : const Interface *intf = GetInterface();
1762 0 : FillObjectLogIntf(intf, info);
1763 :
1764 0 : const unsigned char *m = GetDMac().GetData();
1765 0 : FillObjectLogMac(m, info);
1766 :
1767 0 : info.set_vlan_tag((short int)GetVlanTag());
1768 0 : OPER_TRACE_ENTRY(NextHop, table, info);
1769 0 : }
1770 :
1771 : /////////////////////////////////////////////////////////////////////////////
1772 : // CompositeNH routines
1773 : /////////////////////////////////////////////////////////////////////////////
1774 0 : void CompositeNHKey::ReplaceLocalNexthop(const ComponentNHKeyList &lnh) {
1775 : //Clear all local nexthop
1776 0 : for (uint32_t i = 0; i < component_nh_key_list_.size();) {
1777 0 : ComponentNHKeyPtr cnh = component_nh_key_list_[i];
1778 0 : if ((cnh.get() != NULL) &&
1779 0 : (cnh->nh_key()->GetType() == NextHop::INTERFACE)) {
1780 0 : component_nh_key_list_.erase(component_nh_key_list_.begin() + i);
1781 : } else {
1782 0 : i++;
1783 : }
1784 0 : }
1785 :
1786 0 : component_nh_key_list_.insert(component_nh_key_list_.begin(), lnh.begin(),
1787 : lnh.end());
1788 0 : }
1789 :
1790 43 : bool CompositeNH::CanAdd() const {
1791 43 : if (vrf_ == NULL || vrf_->IsDeleted()) {
1792 0 : LOG(ERROR, "Invalid VRF in composite NH. Skip Add");
1793 0 : return false;
1794 : }
1795 43 : return true;
1796 : }
1797 :
1798 5 : const NextHop* CompositeNH::GetLocalNextHop() const {
1799 : ComponentNHList::const_iterator comp_nh_it =
1800 5 : component_nh_list_.begin();
1801 15 : for(;comp_nh_it != component_nh_list_.end(); comp_nh_it++) {
1802 10 : if ((*comp_nh_it) == NULL) {
1803 0 : continue;
1804 : }
1805 :
1806 10 : if ((*comp_nh_it)->nh()->GetType() != NextHop::TUNNEL) {
1807 0 : return (*comp_nh_it)->nh();
1808 : }
1809 : }
1810 5 : return NULL;
1811 : }
1812 :
1813 0 : bool CompositeNH::HasVmInterface(const VmInterface *vmi) const {
1814 : ComponentNHList::const_iterator comp_nh_it =
1815 0 : component_nh_list_.begin();
1816 0 : for(;comp_nh_it != component_nh_list_.end(); comp_nh_it++) {
1817 0 : if ((*comp_nh_it) == NULL) {
1818 0 : continue;
1819 : }
1820 :
1821 0 : if ((*comp_nh_it)->nh()->GetType() == NextHop::INTERFACE) {
1822 0 : const InterfaceNH *intf_nh = dynamic_cast<const InterfaceNH *>
1823 0 : ((*comp_nh_it)->nh());
1824 0 : if (intf_nh->GetInterface() == vmi)
1825 0 : return true;
1826 : }
1827 0 : if ((*comp_nh_it)->nh()->GetType() == NextHop::VLAN) {
1828 0 : const VlanNH *vlan_nh = dynamic_cast<const VlanNH *>
1829 0 : ((*comp_nh_it)->nh());
1830 0 : if (vlan_nh->GetInterface() == vmi)
1831 0 : return true;
1832 : }
1833 : }
1834 0 : return false;
1835 : }
1836 :
1837 0 : const Interface *CompositeNH::GetFirstLocalEcmpMemberInterface() const {
1838 0 : if (composite_nh_type_ != Composite::LOCAL_ECMP) {
1839 0 : return NULL;
1840 : }
1841 : ComponentNHList::const_iterator comp_nh_it =
1842 0 : component_nh_list_.begin();
1843 0 : for(;comp_nh_it != component_nh_list_.end(); comp_nh_it++) {
1844 0 : if (*comp_nh_it == NULL) {
1845 0 : continue;
1846 : }
1847 0 : if ((*comp_nh_it)->nh()->GetType() == NextHop::INTERFACE) {
1848 0 : const InterfaceNH *intf_nh = dynamic_cast<const InterfaceNH *>
1849 0 : ((*comp_nh_it)->nh());
1850 0 : return (intf_nh->GetInterface());
1851 : }
1852 0 : if ((*comp_nh_it)->nh()->GetType() == NextHop::VLAN) {
1853 0 : const VlanNH *vlan_nh = dynamic_cast<const VlanNH *>
1854 0 : ((*comp_nh_it)->nh());
1855 0 : return (vlan_nh->GetInterface());
1856 : }
1857 : }
1858 0 : return NULL;
1859 : }
1860 :
1861 0 : uint32_t CompositeNH::PickMember(uint32_t seed, uint32_t affinity_index,
1862 : bool ingress) const {
1863 0 : uint32_t idx = kInvalidComponentNHIdx;
1864 0 : size_t size = component_nh_list_.size();
1865 0 : if (size == 0) {
1866 0 : return idx;
1867 : }
1868 :
1869 0 : if (affinity_index != kInvalidComponentNHIdx) {
1870 0 : const NextHop *nh = GetNH(affinity_index);
1871 0 : if (nh != NULL && nh->IsActive()) {
1872 0 : return affinity_index;
1873 : }
1874 : }
1875 :
1876 0 : idx = seed % size;
1877 0 : if (component_nh_list_[idx].get() == NULL ||
1878 0 : component_nh_list_[idx]->nh() == NULL ||
1879 0 : component_nh_list_[idx]->nh()->IsActive() == false ||
1880 0 : (ingress == false &&
1881 0 : component_nh_list_[idx]->nh()->GetType() == NextHop::TUNNEL)) {
1882 :
1883 0 : std::vector<uint32_t> active_list;
1884 0 : for (uint32_t i = 0; i < size; i++) {
1885 0 : if (i == idx)
1886 0 : continue;
1887 0 : if (component_nh_list_[i].get() != NULL &&
1888 0 : component_nh_list_[i]->nh() != NULL &&
1889 0 : component_nh_list_[i]->nh()->IsActive()) {
1890 0 : if (ingress == false) {
1891 0 : if (component_nh_list_[i]->nh()->GetType() != NextHop::TUNNEL) {
1892 0 : active_list.push_back(i);
1893 : }
1894 : } else {
1895 0 : active_list.push_back(i);
1896 : }
1897 : }
1898 : }
1899 0 : idx = (active_list.size()) ?
1900 0 : active_list.at(seed % active_list.size()) :
1901 : kInvalidComponentNHIdx;
1902 0 : }
1903 :
1904 0 : return idx;
1905 : }
1906 :
1907 335 : NextHop *CompositeNHKey::AllocEntry() const {
1908 335 : VrfEntry *vrf = static_cast<VrfEntry *>
1909 335 : (Agent::GetInstance()->vrf_table()->Find(&vrf_key_, true));
1910 335 : return new CompositeNH(composite_nh_type_, validate_mcast_src_, policy_,
1911 335 : component_nh_key_list_, vrf);
1912 : }
1913 :
1914 0 : void CompositeNHKey::ChangeTunnelType(TunnelType::Type tunnel_type) {
1915 0 : ComponentNHKeyList::iterator it = component_nh_key_list_.begin();
1916 0 : for (;it != component_nh_key_list_.end(); it++) {
1917 0 : if ((*it) == NULL) {
1918 0 : continue;
1919 : }
1920 0 : if ((*it)->nh_key()->GetType() == NextHop::TUNNEL) {
1921 : TunnelNHKey *tunnel_nh_key =
1922 0 : static_cast<TunnelNHKey *>((*it)->nh_key()->Clone());
1923 0 : tunnel_nh_key->set_tunnel_type(tunnel_type);
1924 0 : std::unique_ptr<const NextHopKey> nh_key(tunnel_nh_key);
1925 0 : ComponentNHKeyPtr new_tunnel_nh(new ComponentNHKey((*it)->label(),
1926 0 : std::move(nh_key)));
1927 0 : (*it) = new_tunnel_nh;
1928 0 : }
1929 : }
1930 0 : }
1931 :
1932 88 : bool CompositeNH::ChangeEntry(const DBRequest* req) {
1933 88 : bool changed = false;
1934 88 : CompositeNHData *data = static_cast<CompositeNHData *>(req->data.get());
1935 88 : NextHopKey *key = static_cast <NextHopKey *>(req->key.get());
1936 88 : ComponentNHKeyList tmp_component_nh_key_list_;
1937 88 : if (data && data->pbb_nh_ != pbb_nh_) {
1938 0 : pbb_nh_ = data->pbb_nh_;
1939 0 : changed = true;
1940 : }
1941 :
1942 88 : if (data && data->learning_enabled_ != learning_enabled_) {
1943 0 : learning_enabled_ = data->learning_enabled_;
1944 0 : changed = true;
1945 : }
1946 :
1947 88 : if (data && layer2_control_word_ != data->layer2_control_word_) {
1948 6 : layer2_control_word_ = data->layer2_control_word_;
1949 6 : changed = true;
1950 : }
1951 :
1952 0 : if (key->sub_op_ == AgentKey::RESYNC &&
1953 88 : (data && data->component_nh_key_list_.empty() == false) &&
1954 0 : composite_nh_type_ == Composite::LOCAL_ECMP ) {
1955 0 : tmp_component_nh_key_list_ = data->component_nh_key_list_;
1956 0 : changed = true;
1957 : } else {
1958 88 : tmp_component_nh_key_list_ = component_nh_key_list_;
1959 : }
1960 :
1961 88 : ComponentNHList component_nh_list;
1962 88 : ComponentNHKeyList::const_iterator it = tmp_component_nh_key_list_.begin();
1963 213 : for (;it != tmp_component_nh_key_list_.end(); it++) {
1964 125 : if ((*it) == NULL) {
1965 0 : ComponentNHPtr nh_key;
1966 0 : nh_key.reset();
1967 0 : component_nh_list.push_back(nh_key);
1968 0 : continue;
1969 0 : }
1970 :
1971 125 : const NextHop *nh = static_cast<const NextHop *>
1972 125 : (NextHopTable::GetInstance()->FindActiveEntry((*it)->nh_key()));
1973 125 : if (nh) {
1974 125 : ComponentNHPtr nh_key(new ComponentNH((*it)->label(), nh));
1975 125 : component_nh_list.push_back(nh_key);
1976 125 : } else {
1977 : //Nexthop not active
1978 : //Insert a empty entry
1979 0 : ComponentNHPtr nh_key;
1980 0 : nh_key.reset();
1981 0 : component_nh_list.push_back(nh_key);
1982 0 : }
1983 : }
1984 :
1985 : //Check if new list and old list are same
1986 : ComponentNHList::const_iterator new_comp_nh_it =
1987 88 : component_nh_list.begin();
1988 : ComponentNHList::const_iterator old_comp_nh_it =
1989 88 : component_nh_list_.begin();
1990 260 : for(;new_comp_nh_it != component_nh_list.end() &&
1991 260 : old_comp_nh_it != component_nh_list_.end();
1992 66 : new_comp_nh_it++, old_comp_nh_it++) {
1993 : //Check if both component NH are NULL
1994 66 : if ((*old_comp_nh_it) == NULL &&
1995 0 : (*new_comp_nh_it) == NULL) {
1996 0 : continue;
1997 : }
1998 :
1999 : //check if one of the component NH is NULL
2000 66 : if ((*old_comp_nh_it) == NULL || (*new_comp_nh_it) == NULL) {
2001 0 : changed = true;
2002 0 : break;
2003 : }
2004 :
2005 : //Check if component NH are same
2006 66 : if ((**old_comp_nh_it) == (**new_comp_nh_it)) {
2007 66 : continue;
2008 : }
2009 :
2010 0 : changed = true;
2011 0 : break;
2012 : }
2013 :
2014 136 : if (new_comp_nh_it == component_nh_list.end() &&
2015 136 : old_comp_nh_it == component_nh_list_.end()) {
2016 : //No Change
2017 : } else {
2018 40 : changed = true;
2019 : }
2020 :
2021 88 : if (comp_ecmp_hash_fields_.IsFieldsInUseChanged()) {
2022 38 : comp_ecmp_hash_fields_.SetHashFieldstoUse();
2023 38 : changed = true;
2024 : }
2025 88 : component_nh_list_ = component_nh_list;
2026 :
2027 0 : if (key->sub_op_ == AgentKey::RESYNC &&
2028 88 : (data && data->component_nh_key_list_.empty() == false) &&
2029 0 : composite_nh_type_ == Composite::LOCAL_ECMP ) {
2030 : /* First remove entry from tree */
2031 0 : Agent::GetInstance()->nexthop_table()->RemoveWithoutDelete(static_cast<DBEntry *>(this));
2032 :
2033 : /* Now update the key and add it back to tree */
2034 0 : component_nh_key_list_ = tmp_component_nh_key_list_;
2035 0 : Agent::GetInstance()->nexthop_table()->AddWithoutAlloc(static_cast<DBEntry *>(this));
2036 : }
2037 :
2038 88 : return changed;
2039 88 : }
2040 :
2041 131 : void CompositeNH::SendObjectLog(const NextHopTable *table,
2042 : AgentLogEvent::type event) const {
2043 131 : NextHopObjectLogInfo info;
2044 131 : FillObjectLog(event, info);
2045 :
2046 131 : const VrfEntry *vrf_entry = vrf();
2047 131 : if (vrf_entry) {
2048 131 : info.set_vrf(vrf_entry->GetName());
2049 : }
2050 :
2051 131 : std::vector<ComponentNHLogInfo> comp_nh_log_list;
2052 131 : ComponentNHList::const_iterator component_nh_it = begin();
2053 256 : for (;component_nh_it != end(); component_nh_it++) {
2054 125 : ComponentNHLogInfo component_nh_info;
2055 125 : const ComponentNH *comp_nh = (*component_nh_it).get();
2056 125 : if (comp_nh == NULL) {
2057 0 : continue;
2058 : }
2059 125 : const NextHop *nh = comp_nh->nh();
2060 125 : component_nh_info.set_component_nh_id(nh->id());
2061 125 : switch(nh->GetType()) {
2062 8 : case TUNNEL: {
2063 8 : const TunnelNH *tun_nh = static_cast<const TunnelNH *>(nh);
2064 8 : component_nh_info.set_type("Tunnel");
2065 8 : component_nh_info.set_label(comp_nh->label());
2066 8 : component_nh_info.set_server_ip(tun_nh->GetDip()->to_string());
2067 8 : break;
2068 : }
2069 :
2070 81 : case INTERFACE: {
2071 81 : const InterfaceNH *intf_nh = static_cast<const InterfaceNH *>(nh);
2072 81 : component_nh_info.set_type("Interface");
2073 81 : component_nh_info.set_label(comp_nh->label());
2074 : const Interface *intf =
2075 81 : static_cast<const Interface *>(intf_nh->GetInterface());
2076 81 : component_nh_info.set_intf_name(intf->name());
2077 81 : break;
2078 : }
2079 :
2080 0 : case VLAN: {
2081 0 : const VlanNH *vlan_nh = static_cast<const VlanNH *>(nh);
2082 0 : component_nh_info.set_type("Vlan");
2083 0 : component_nh_info.set_label(comp_nh->label());
2084 : const Interface *intf =
2085 0 : static_cast<const Interface *>(vlan_nh->GetInterface());
2086 0 : component_nh_info.set_intf_name(intf->name());
2087 0 : break;
2088 : }
2089 :
2090 36 : case COMPOSITE: {
2091 36 : const CompositeNH *cnh = static_cast<const CompositeNH *>(nh);
2092 36 : std::stringstream str;
2093 36 : str << "Composite; Type: " << cnh->composite_nh_type() <<
2094 36 : " comp_nh_count" << cnh->ComponentNHCount();
2095 36 : component_nh_info.set_type(str.str());
2096 36 : break;
2097 36 : }
2098 0 : default:
2099 0 : break;
2100 : }
2101 125 : comp_nh_log_list.push_back(component_nh_info);
2102 125 : }
2103 :
2104 131 : info.set_nh_list(comp_nh_log_list);
2105 131 : OPER_TRACE_ENTRY(NextHop, table, info);
2106 131 : }
2107 :
2108 : //Key for composite NH is list of component NH
2109 : //Some of the component NH may be NULL, in case of ECMP, as deletion of
2110 : //component NH resulting in addition of invalid component NH at that location,
2111 : //so that kernel can trap packet hitting such component NH
2112 0 : void CompositeNH::SetKey(const DBRequestKey *k) {
2113 0 : const CompositeNHKey *key = static_cast<const CompositeNHKey *>(k);
2114 0 : NextHop::SetKey(k);
2115 0 : composite_nh_type_ = key->composite_nh_type_;
2116 0 : component_nh_key_list_ = key->component_nh_key_list_;
2117 0 : }
2118 :
2119 1382 : bool CompositeNH::NextHopIsLess(const DBEntry &rhs_db) const {
2120 1382 : const CompositeNH &rhs = static_cast<const CompositeNH &>(rhs_db);
2121 1382 : if (composite_nh_type_ != rhs.composite_nh_type_) {
2122 424 : return composite_nh_type_ < rhs.composite_nh_type_;
2123 : }
2124 :
2125 958 : if (vrf_ != rhs.vrf_) {
2126 0 : return vrf_ < rhs.vrf_;
2127 : }
2128 :
2129 : //Parse thought indivial key entries and compare if they are same
2130 : ComponentNHKeyList::const_iterator left_component_nh_it =
2131 958 : component_nh_key_list_.begin();
2132 : ComponentNHKeyList::const_iterator right_component_nh_it =
2133 958 : rhs.component_nh_key_list_.begin();
2134 :
2135 3305 : for (;left_component_nh_it != component_nh_key_list_.end() &&
2136 3305 : right_component_nh_it != rhs.component_nh_key_list_.end();
2137 1085 : left_component_nh_it++, right_component_nh_it++) {
2138 : //If both component NH are empty, nothing to compare
2139 1230 : if (*left_component_nh_it == NULL &&
2140 0 : *right_component_nh_it == NULL) {
2141 0 : continue;
2142 : }
2143 : //One of the component NH is NULL
2144 2460 : if ((*left_component_nh_it) == NULL ||
2145 1230 : (*right_component_nh_it) == NULL) {
2146 0 : return (*left_component_nh_it) < (*right_component_nh_it);
2147 : }
2148 :
2149 : //Check if the label is different
2150 2460 : if ((*left_component_nh_it)->label() !=
2151 1230 : (*right_component_nh_it)->label()) {
2152 0 : return (*left_component_nh_it)->label() <
2153 0 : (*right_component_nh_it)->label();
2154 : }
2155 :
2156 : //Check if the nexthop key is different
2157 : //Ideally we could find the nexthop and compare pointer alone
2158 : //it wont work because this is called from Find context itself,
2159 : //and it would result in deadlock
2160 : //Hence compare nexthop key alone
2161 1230 : const NextHopKey *left_nh = (*left_component_nh_it)->nh_key();
2162 1230 : const NextHopKey *right_nh = (*right_component_nh_it)->nh_key();
2163 :
2164 1230 : if (left_nh->IsEqual(*right_nh) == false) {
2165 145 : return left_nh->IsLess(*right_nh);
2166 : }
2167 : }
2168 :
2169 : //Both composite nexthop are same
2170 1594 : if (left_component_nh_it == component_nh_key_list_.end() &&
2171 1594 : right_component_nh_it == rhs.component_nh_key_list_.end()) {
2172 670 : return false;
2173 : }
2174 :
2175 : //Right composite nexthop entry has more entries, hence
2176 : //left composite nexthop is lesser then right composite nh
2177 143 : if (left_component_nh_it == component_nh_key_list_.end()) {
2178 111 : return true;
2179 : }
2180 32 : return false;
2181 : }
2182 :
2183 122 : CompositeNH::KeyPtr CompositeNH::GetDBRequestKey() const {
2184 122 : ComponentNHKeyList component_nh_key_list;
2185 122 : component_nh_key_list = component_nh_key_list_;
2186 122 : NextHopKey *key = new CompositeNHKey(composite_nh_type_,
2187 122 : validate_mcast_src_, policy_,
2188 : component_nh_key_list,
2189 122 : vrf_->GetName());
2190 244 : return DBEntryBase::KeyPtr(key);
2191 122 : }
2192 :
2193 43 : void CompositeNH::Delete(const DBRequest* req) {
2194 43 : component_nh_list_.clear();
2195 43 : }
2196 :
2197 11 : void CompositeNH::CreateComponentNH(Agent *agent,
2198 : TunnelType::Type type) const {
2199 : //Create all component NH
2200 11 : for (ComponentNHList::const_iterator it = component_nh_list_.begin();
2201 27 : it != component_nh_list_.end(); it++) {
2202 16 : if ((*it) == NULL) {
2203 0 : continue;
2204 : }
2205 16 : const NextHop *nh = (*it)->nh();
2206 16 : switch (nh->GetType()) {
2207 6 : case NextHop::TUNNEL: {
2208 6 : if (type == TunnelType::MPLS_OVER_MPLS) {
2209 0 : const LabelledTunnelNH *tnh =
2210 : static_cast<const LabelledTunnelNH *>(nh);
2211 0 : if (tnh->GetTransportTunnelType() !=
2212 0 : TunnelType::ComputeType(TunnelType::MplsType())) {
2213 0 : DBRequest tnh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
2214 0 : tnh_req.key.reset(new LabelledTunnelNHKey(
2215 0 : tnh->GetVrf()->GetName(),
2216 0 : *(tnh->GetSip()),
2217 0 : *(tnh->GetDip()),
2218 0 : tnh->PolicyEnabled(),
2219 : type,
2220 0 : tnh->rewrite_dmac(),
2221 0 : tnh->GetTransportLabel()));
2222 0 : tnh_req.data.reset(new LabelledTunnelNHData());
2223 0 : agent->nexthop_table()->Process(tnh_req);
2224 0 : }
2225 : } else {
2226 6 : const TunnelNH *tnh = static_cast<const TunnelNH *>(nh);
2227 6 : if (type != tnh->GetTunnelType().GetType()) {
2228 0 : DBRequest tnh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
2229 0 : tnh_req.key.reset(new TunnelNHKey(tnh->GetVrf()->GetName(),
2230 0 : *(tnh->GetSip()),
2231 0 : *(tnh->GetDip()),
2232 0 : tnh->PolicyEnabled(),
2233 : type,
2234 0 : tnh->rewrite_dmac()));
2235 0 : tnh_req.data.reset(new TunnelNHData());
2236 0 : agent->nexthop_table()->Process(tnh_req);
2237 0 : }
2238 : }
2239 6 : break;
2240 : }
2241 0 : case NextHop::COMPOSITE: {
2242 0 : const CompositeNH *cnh =
2243 : static_cast<const CompositeNH *>(nh);
2244 : //Create new composite NH
2245 0 : cnh->ChangeTunnelType(agent, type);
2246 0 : break;
2247 : }
2248 10 : default: {
2249 10 : break;
2250 : }
2251 : }
2252 : }
2253 11 : }
2254 :
2255 : //Changes the component NH key list to contain new NH keys as per new
2256 : //tunnel type
2257 11 : void CompositeNH::ChangeComponentNHKeyTunnelType(
2258 : ComponentNHKeyList &component_nh_key_list, TunnelType::Type type) const {
2259 :
2260 11 : ComponentNHKeyList::iterator it = component_nh_key_list.begin();
2261 11 : TunnelType::Type orig_type = type;
2262 27 : for (;it != component_nh_key_list.end(); it++) {
2263 16 : type = orig_type;
2264 16 : if ((*it) == NULL) {
2265 0 : continue;
2266 : }
2267 :
2268 16 : if ((*it)->nh_key()->GetType() == NextHop::COMPOSITE) {
2269 : CompositeNHKey *composite_nh_key =
2270 0 : static_cast<CompositeNHKey *>((*it)->nh_key()->Clone());
2271 0 : if (composite_nh_key->composite_nh_type() == Composite::TOR) {
2272 0 : type = TunnelType::VXLAN;
2273 : }
2274 0 : if (composite_nh_key->composite_nh_type() == Composite::FABRIC ||
2275 0 : composite_nh_key->composite_nh_type() == Composite::L3FABRIC) {
2276 0 : type = TunnelType::ComputeType(TunnelType::MplsType());
2277 : }
2278 0 : ChangeComponentNHKeyTunnelType(
2279 0 : composite_nh_key->component_nh_key_list_, type);
2280 0 : std::unique_ptr<const NextHopKey> nh_key(composite_nh_key);
2281 0 : ComponentNHKeyPtr new_comp_nh(new ComponentNHKey((*it)->label(),
2282 0 : std::move(nh_key)));
2283 0 : (*it) = new_comp_nh;
2284 0 : }
2285 :
2286 16 : if ((*it)->nh_key()->GetType() == NextHop::TUNNEL) {
2287 : TunnelNHKey *tunnel_nh_key =
2288 6 : static_cast<TunnelNHKey *>((*it)->nh_key()->Clone());
2289 6 : tunnel_nh_key->set_tunnel_type(type);
2290 6 : std::unique_ptr<const NextHopKey> nh_key(tunnel_nh_key);
2291 6 : ComponentNHKeyPtr new_tunnel_nh(new ComponentNHKey((*it)->label(),
2292 6 : std::move(nh_key)));
2293 6 : (*it) = new_tunnel_nh;
2294 6 : }
2295 : }
2296 11 : }
2297 :
2298 : //This API recursively goes thru composite NH and creates
2299 : //all the component NH upon tunnel type change
2300 : //CreateComponentNH() API which creates new tunnel NH and composite NH,
2301 : //would call ChangeTunnelType() API which would result in recursion
2302 11 : CompositeNH *CompositeNH::ChangeTunnelType(Agent *agent,
2303 : TunnelType::Type type) const {
2304 11 : if (composite_nh_type_ == Composite::TOR) {
2305 0 : type = TunnelType::VXLAN;
2306 : }
2307 11 : if (composite_nh_type_ == Composite::FABRIC ||
2308 11 : composite_nh_type_ == Composite::L3FABRIC) {
2309 0 : type = TunnelType::ComputeType(TunnelType::MplsType());
2310 : }
2311 : //Create all component NH with new tunnel type
2312 11 : CreateComponentNH(agent, type);
2313 :
2314 : //Change the tunnel type of all component NH key
2315 11 : ComponentNHKeyList new_component_nh_key_list = component_nh_key_list_;
2316 11 : ChangeComponentNHKeyTunnelType(new_component_nh_key_list, type);
2317 : //Create the new nexthop
2318 11 : CompositeNHKey *comp_nh_key = new CompositeNHKey(composite_nh_type_,
2319 11 : validate_mcast_src_,
2320 11 : policy_,
2321 : new_component_nh_key_list,
2322 11 : vrf_->GetName());
2323 11 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
2324 11 : nh_req.key.reset(comp_nh_key);
2325 11 : nh_req.data.reset(new CompositeNHData(pbb_nh_, learning_enabled_,
2326 11 : layer2_control_word_));
2327 11 : agent->nexthop_table()->Process(nh_req);
2328 :
2329 11 : CompositeNH *comp_nh = static_cast<CompositeNH *>(
2330 11 : agent->nexthop_table()->FindActiveEntry(comp_nh_key));
2331 11 : assert(comp_nh);
2332 11 : return comp_nh;
2333 11 : }
2334 :
2335 0 : bool CompositeNH::GetIndex(ComponentNH &component_nh, uint32_t &idx) const {
2336 0 : idx = 0;
2337 0 : BOOST_FOREACH(ComponentNHPtr it, component_nh_list_) {
2338 0 : if (it.get() == NULL) {
2339 0 : idx++;
2340 0 : continue;
2341 : }
2342 :
2343 0 : if (it->nh() && component_nh.nh()) {
2344 0 : if (it->nh()->MatchEgressData(component_nh.nh())) {
2345 0 : return true;
2346 0 : } else if (it->nh() == component_nh.nh()) {
2347 0 : return true;
2348 : }
2349 : }
2350 0 : idx++;
2351 0 : }
2352 0 : return false;
2353 : }
2354 :
2355 9 : void CompositeNH::UpdateEcmpHashFieldsUponRouteDelete(Agent *agent,
2356 : const string &vrf_name) {
2357 9 : if (comp_ecmp_hash_fields_.IsFieldsInUseChanged()) {
2358 0 : DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
2359 0 : DBEntryBase::KeyPtr key = GetDBRequestKey();
2360 0 : NextHopKey *nh_key = static_cast<NextHopKey *>(key.get());
2361 0 : nh_key->sub_op_ = AgentKey::RESYNC;
2362 0 : nh_req.key = std::move(key);
2363 0 : nh_req.data.reset(NULL);
2364 0 : agent->nexthop_table()->Process(nh_req);
2365 0 : }
2366 9 : }
2367 :
2368 1 : void CompositeNHKey::CreateTunnelNH(Agent *agent) {
2369 5 : BOOST_FOREACH(ComponentNHKeyPtr component_nh_key, component_nh_key_list_) {
2370 4 : if (component_nh_key.get() &&
2371 2 : component_nh_key->nh_key()->GetType() == NextHop::TUNNEL) {
2372 2 : DBRequest req;
2373 : // First enqueue request to create Tunnel NH
2374 2 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
2375 2 : req.key.reset(component_nh_key->nh_key()->Clone());
2376 2 : TunnelNHData *data = new TunnelNHData();
2377 2 : req.data.reset(data);
2378 2 : agent->nexthop_table()->Process(req);
2379 2 : }
2380 2 : }
2381 1 : }
2382 :
2383 0 : void CompositeNHKey::CreateTunnelNHReq(Agent *agent) {
2384 0 : BOOST_FOREACH(ComponentNHKeyPtr component_nh_key, component_nh_key_list_) {
2385 0 : if (component_nh_key.get() &&
2386 0 : component_nh_key->nh_key()->GetType() == NextHop::TUNNEL) {
2387 0 : DBRequest req;
2388 : // First enqueue request to create Tunnel NH
2389 0 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
2390 0 : req.key.reset(component_nh_key->nh_key()->Clone());
2391 0 : TunnelNHData *data = new TunnelNHData();
2392 0 : req.data.reset(data);
2393 0 : agent->nexthop_table()->Enqueue(&req);
2394 0 : }
2395 0 : }
2396 0 : }
2397 :
2398 38 : CompositeNHKey* CompositeNHKey::Clone() const {
2399 38 : return new CompositeNHKey(composite_nh_type_, validate_mcast_src_, policy_,
2400 38 : component_nh_key_list_, vrf_key_.name_);
2401 : }
2402 :
2403 1 : bool CompositeNHKey::find(ComponentNHKeyPtr new_component_nh_key) {
2404 5 : BOOST_FOREACH(ComponentNHKeyPtr component_nh_key,
2405 : component_nh_key_list_) {
2406 2 : if (component_nh_key == NULL) {
2407 0 : continue;
2408 : }
2409 2 : if (*component_nh_key == *new_component_nh_key) {
2410 0 : return true;
2411 : }
2412 2 : }
2413 1 : return false;
2414 : }
2415 :
2416 0 : void CompositeNHKey::insert(ComponentNHKeyPtr new_component_nh_key) {
2417 0 : if (new_component_nh_key == NULL) {
2418 0 : component_nh_key_list_.push_back(new_component_nh_key);
2419 0 : return;
2420 : }
2421 :
2422 0 : if (find(new_component_nh_key)) {
2423 0 : return;
2424 : }
2425 :
2426 0 : ComponentNHKeyList::iterator it;
2427 0 : for (it = component_nh_key_list_.begin();
2428 0 : it != component_nh_key_list_.end(); it++) {
2429 : //Insert at empty spot
2430 0 : if ((*it) == NULL) {
2431 0 : *it = new_component_nh_key;
2432 0 : return;
2433 : }
2434 : }
2435 0 : component_nh_key_list_.push_back(new_component_nh_key);
2436 : }
2437 :
2438 0 : void CompositeNHKey::erase(ComponentNHKeyPtr nh_key_ptr) {
2439 0 : if (nh_key_ptr==nullptr){
2440 0 : return;
2441 : }
2442 0 : for (auto &com_key_ptr : component_nh_key_list_)
2443 : {
2444 0 : if (com_key_ptr==nullptr){
2445 0 : continue;
2446 : }
2447 0 : if (*com_key_ptr==*nh_key_ptr ){
2448 0 : com_key_ptr.reset();
2449 0 : return;
2450 : }
2451 : }
2452 : }
2453 :
2454 1 : bool CompositeNH::UpdateComponentNHKey(uint32_t label, NextHopKey *nh_key,
2455 : ComponentNHKeyList &component_nh_key_list, bool &comp_nh_policy) const {
2456 1 : bool ret = false;
2457 1 : comp_nh_policy = false;
2458 5 : BOOST_FOREACH(ComponentNHPtr it, component_nh_list_) {
2459 2 : if (it.get() == NULL) {
2460 0 : ComponentNHKeyPtr dummy_ptr;
2461 0 : dummy_ptr.reset();
2462 0 : component_nh_key_list.push_back(dummy_ptr);
2463 0 : continue;
2464 0 : }
2465 2 : const ComponentNH *component_nh = it.get();
2466 2 : uint32_t new_label = component_nh->label();
2467 2 : DBEntryBase::KeyPtr key = component_nh->nh()->GetDBRequestKey();
2468 2 : NextHopKey *lhs = static_cast<NextHopKey *>(key.release());
2469 :
2470 2 : if (new_label != label && lhs->IsEqual(*nh_key)) {
2471 0 : new_label = label;
2472 0 : ret = true;
2473 : }
2474 2 : std::unique_ptr<const NextHopKey> nh_key_ptr(lhs);
2475 : ComponentNHKeyPtr component_nh_key(
2476 2 : new ComponentNHKey(new_label, std::move(nh_key_ptr)));
2477 2 : component_nh_key_list.push_back(component_nh_key);
2478 2 : if (!comp_nh_policy) {
2479 1 : comp_nh_policy = component_nh->nh()->NexthopToInterfacePolicy();
2480 : }
2481 4 : }
2482 1 : return ret;
2483 : }
2484 :
2485 0 : ComponentNHKeyList CompositeNH::AddComponentNHKey(ComponentNHKeyPtr cnh,
2486 : bool &comp_nh_policy) const {
2487 0 : Agent *agent = static_cast<NextHopTable *>(get_table())->agent();
2488 0 : const NextHop *nh = static_cast<const NextHop *>(agent->nexthop_table()->
2489 0 : FindActiveEntry(cnh->nh_key()));
2490 0 : assert(nh);
2491 :
2492 0 : ComponentNHKeyList component_nh_key_list = component_nh_key_list_;
2493 0 : int index = 0;
2494 :
2495 0 : comp_nh_policy = false;
2496 0 : bool made_cnh_list = false;
2497 0 : BOOST_FOREACH(ComponentNHPtr it, component_nh_list_) {
2498 0 : const ComponentNH *component_nh = it.get();
2499 0 : if (component_nh == NULL) {
2500 0 : index++;
2501 0 : continue;
2502 : }
2503 0 : if (component_nh->nh() == nh) {
2504 0 : if (component_nh->label() == cnh->label()) {
2505 : //Entry already present, return old component nh key list
2506 0 : comp_nh_policy = PolicyEnabled();
2507 0 : return component_nh_key_list;
2508 : } else {
2509 0 : if (nh->GetType() == NextHop::INTERFACE) {
2510 0 : component_nh_key_list[index] = cnh;
2511 0 : made_cnh_list = true;
2512 : }
2513 0 : if (!comp_nh_policy) {
2514 0 : comp_nh_policy = nh->NexthopToInterfacePolicy();
2515 : }
2516 : }
2517 0 : } else if (!comp_nh_policy) {
2518 0 : comp_nh_policy = component_nh->nh()->NexthopToInterfacePolicy();
2519 : }
2520 0 : if (comp_nh_policy && made_cnh_list) {
2521 0 : break;
2522 : }
2523 0 : index++;
2524 0 : }
2525 :
2526 0 : if (made_cnh_list) {
2527 0 : return component_nh_key_list;
2528 : }
2529 :
2530 0 : bool inserted = false;
2531 0 : index = 0;
2532 0 : ComponentNHKeyList::const_iterator key_it = component_nh_key_list.begin();
2533 0 : for (;key_it != component_nh_key_list.end(); key_it++, index++) {
2534 : //If there is a empty slot, in
2535 : //component key list insert the element there.
2536 0 : if ((*key_it) == NULL) {
2537 0 : component_nh_key_list[index] = cnh;
2538 0 : inserted = true;
2539 0 : break;
2540 : }
2541 : }
2542 :
2543 : //No empty slots found, insert entry at last
2544 0 : if (inserted == false) {
2545 0 : component_nh_key_list.push_back(cnh);
2546 : }
2547 0 : comp_nh_policy = PolicyEnabled();
2548 0 : if (!comp_nh_policy && (nh->GetType() == NextHop::INTERFACE)) {
2549 0 : comp_nh_policy = nh->NexthopToInterfacePolicy();
2550 : }
2551 0 : return component_nh_key_list;
2552 0 : }
2553 :
2554 : ComponentNHKeyList
2555 0 : CompositeNH::DeleteComponentNHKey(ComponentNHKeyPtr cnh,
2556 : bool &comp_nh_new_policy) const {
2557 0 : Agent *agent = static_cast<NextHopTable *>(get_table())->agent();
2558 0 : const NextHop *nh = static_cast<const NextHop *>(agent->nexthop_table()->
2559 0 : Find(cnh->nh_key(), true));
2560 0 : assert(nh);
2561 :
2562 0 : ComponentNHKeyList component_nh_key_list = component_nh_key_list_;
2563 0 : ComponentNHKeyPtr component_nh_key;
2564 0 : ComponentNHList::const_iterator it = begin();
2565 0 : comp_nh_new_policy = false;
2566 0 : bool removed = false;
2567 0 : int index = 0;
2568 0 : for (;it != end(); it++, index++) {
2569 0 : ComponentNHKeyPtr dummy_ptr;
2570 0 : dummy_ptr.reset();
2571 0 : if ((*it) && ((*it)->label() == cnh->label() && (*it)->nh() == nh)) {
2572 0 : component_nh_key_list[index] = dummy_ptr;
2573 0 : removed = true;
2574 : } else {
2575 : /* Go through all the component Interface Nexthops of this
2576 : * CompositeNH to figure out the new policy status of this
2577 : * CompositeNH. Ignore the component NH being deleted while
2578 : * iterating. */
2579 0 : if ((*it) && (*it)->nh() && !comp_nh_new_policy) {
2580 : /* If any one of component NH's interface has policy enabled,
2581 : * the policy-status of compositeNH is true. So we need to
2582 : * look only until we find the first Interface which has
2583 : * policy enabled */
2584 0 : comp_nh_new_policy = (*it)->nh()->NexthopToInterfacePolicy();
2585 : }
2586 : }
2587 0 : if (removed && comp_nh_new_policy) {
2588 : /* No need to iterate further if we done with both deleting key and
2589 : * figuring out policy-status */
2590 0 : break;
2591 : }
2592 0 : }
2593 0 : return component_nh_key_list;
2594 0 : }
2595 :
2596 1331 : bool CompositeNHKey::NextHopKeyIsLess(const NextHopKey &rhs) const {
2597 1331 : const CompositeNHKey *comp_rhs = static_cast<const CompositeNHKey *>(&rhs);
2598 1331 : if (vrf_key_.name_ != comp_rhs->vrf_key_.name_) {
2599 0 : return vrf_key_.name_ < comp_rhs->vrf_key_.name_;
2600 : }
2601 :
2602 1331 : if (composite_nh_type_ != comp_rhs->composite_nh_type_) {
2603 0 : return composite_nh_type_ < comp_rhs->composite_nh_type_;
2604 : }
2605 :
2606 1331 : ComponentNHKeyList::const_iterator key_it = begin();
2607 1331 : ComponentNHKeyList::const_iterator rhs_key_it = comp_rhs->begin();
2608 3542 : for (;key_it != end() && rhs_key_it != comp_rhs->end();
2609 2211 : key_it++, rhs_key_it++) {
2610 2370 : const ComponentNHKey *lhs_component_nh_ptr = (*key_it).get();
2611 2370 : const ComponentNHKey *rhs_component_nh_ptr = (*rhs_key_it).get();
2612 2370 : if (lhs_component_nh_ptr == NULL &&
2613 : rhs_component_nh_ptr == NULL) {
2614 0 : continue;
2615 : }
2616 :
2617 2370 : if (lhs_component_nh_ptr == NULL ||
2618 : rhs_component_nh_ptr == NULL) {
2619 0 : return lhs_component_nh_ptr < rhs_component_nh_ptr;
2620 : }
2621 :
2622 4740 : if (lhs_component_nh_ptr->label() !=
2623 2370 : rhs_component_nh_ptr->label()) {
2624 0 : return lhs_component_nh_ptr->label() < rhs_component_nh_ptr->label();
2625 : }
2626 :
2627 2370 : const NextHopKey *left_nh_key = lhs_component_nh_ptr->nh_key();
2628 2370 : const NextHopKey *right_nh_key = rhs_component_nh_ptr->nh_key();
2629 2370 : if (left_nh_key->IsEqual(*right_nh_key) == false) {
2630 160 : if (left_nh_key->GetType() != right_nh_key->GetType()) {
2631 0 : return left_nh_key->GetType() < right_nh_key->GetType();
2632 : }
2633 160 : return left_nh_key->IsLess(*right_nh_key);
2634 : }
2635 : }
2636 :
2637 1172 : if (key_it == end() && rhs_key_it == comp_rhs->end()) {
2638 868 : return false;
2639 : }
2640 :
2641 304 : if (key_it == end()) {
2642 216 : return true;
2643 : }
2644 88 : return false;
2645 : }
2646 :
2647 : // Expand list of local composite members using the MPLS label in
2648 : // local-composite key
2649 : // Note, another alternative could be to use path created for local-composites
2650 : // However, in cases such as service-chain, the MPLS label can point to
2651 : // local composite created from different route (route for service-ip)
2652 1 : bool CompositeNHKey::ExpandLocalCompositeNH(Agent *agent) {
2653 1 : uint32_t label = MplsTable::kInvalidLabel;
2654 : //Find local composite ecmp label
2655 5 : BOOST_FOREACH(ComponentNHKeyPtr component_nh_key,
2656 : component_nh_key_list_) {
2657 4 : if (component_nh_key.get() &&
2658 2 : component_nh_key->nh_key()->GetType() == NextHop::COMPOSITE) {
2659 : const CompositeNHKey *composite_nh_key =
2660 : static_cast<const CompositeNHKey *>(
2661 0 : component_nh_key->nh_key());
2662 0 : if (composite_nh_key->composite_nh_type() ==
2663 : Composite::LOCAL_ECMP) {
2664 0 : label = component_nh_key->label();
2665 : //Erase the entry from list, it will be replaced with
2666 : //individual entries of this local composite NH
2667 0 : erase(component_nh_key);
2668 0 : break;
2669 : }
2670 : }
2671 2 : }
2672 :
2673 : //In case of ECMP in fabric VRF there is no mpls
2674 : //label, hence pick policy flag from corresponding
2675 : //interface NH
2676 2 : if (label == MplsTable::kInvalidLabel &&
2677 2 : vrf_key_.IsEqual(VrfKey(agent->fabric_vrf_name()))) {
2678 0 : BOOST_FOREACH(ComponentNHKeyPtr component_nh_key,
2679 : component_nh_key_list_) {
2680 0 : if (component_nh_key.get() &&
2681 0 : component_nh_key->nh_key()->GetType() == NextHop::INTERFACE) {
2682 : //Interface NH wouldnt have policy hence pick from VMI
2683 0 : const NextHop *nh = static_cast<const NextHop *>(
2684 0 : agent->nexthop_table()->FindActiveEntry(component_nh_key->nh_key()));
2685 0 : if (nh && nh->NexthopToInterfacePolicy()) {
2686 0 : return true;
2687 : }
2688 : }
2689 0 : }
2690 : }
2691 :
2692 : //No Local composite NH found
2693 1 : if (label == MplsTable::kInvalidLabel) {
2694 1 : return false;
2695 : }
2696 :
2697 0 : MplsLabel *mpls = agent->mpls_table()->FindMplsLabel(label);
2698 0 : if (mpls == NULL) {
2699 0 : return false;
2700 : }
2701 :
2702 0 : const NextHop *mpls_nh = mpls->nexthop();
2703 :
2704 : // FIXME: Its possible that the label we have got here is re-cycled one
2705 : // We dont have a good scheme to handle recycled labels. For now ensure
2706 : // that label points to COMPOSITE.
2707 : //
2708 : // If the label is really recyecled, then we will get a route update
2709 : // shortly with new label or route delete
2710 0 : if (mpls_nh->GetType() != NextHop::COMPOSITE) {
2711 0 : component_nh_key_list_.clear();
2712 0 : return false;
2713 : }
2714 :
2715 0 : assert(mpls_nh->GetType() == NextHop::COMPOSITE);
2716 0 : const CompositeNH *cnh = static_cast<const CompositeNH *>(mpls_nh);
2717 :
2718 0 : bool comp_nh_new_policy = false;
2719 0 : BOOST_FOREACH(ComponentNHPtr it, cnh->component_nh_list()) {
2720 0 : if (it.get() == NULL) {
2721 0 : ComponentNHKeyPtr dummy_ptr;
2722 0 : dummy_ptr.reset();
2723 0 : insert(dummy_ptr);
2724 0 : continue;
2725 0 : }
2726 0 : const ComponentNH *component_nh = it.get();
2727 0 : DBEntryBase::KeyPtr key = component_nh->nh()->GetDBRequestKey();
2728 0 : NextHopKey *nh_key = static_cast<NextHopKey *>(key.release());
2729 0 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
2730 : ComponentNHKeyPtr component_nh_key(
2731 0 : new ComponentNHKey(component_nh->label(), std::move(nh_key_ptr)));
2732 0 : insert(component_nh_key);
2733 0 : if (!comp_nh_new_policy) {
2734 0 : comp_nh_new_policy = component_nh->nh()->NexthopToInterfacePolicy();
2735 : }
2736 0 : }
2737 0 : return comp_nh_new_policy;
2738 : }
2739 :
2740 1 : bool CompositeNHKey::Reorder(Agent *agent,
2741 : uint32_t label, const NextHop *nh) {
2742 : //Enqueue request to create Tunnel NH
2743 1 : CreateTunnelNH(agent);
2744 : //First expand local composite NH, if any
2745 1 : bool policy = ExpandLocalCompositeNH(agent);
2746 : //Order the component NH entries, so that previous position of
2747 : //component NH are maintained.
2748 : //For example, if previous composite NH consisted of A, B and C
2749 : //as component NH, and the new array of component NH is B, A and C
2750 : //or any combination of the three entries, the result should be A, B and C
2751 : //only, so that previous position are mainatined.
2752 : //If the new key list is C and A, then the end result would be A <NULL> C,
2753 : //so that A and C component NH position are maintained
2754 : //
2755 : //Example 2
2756 : //Let old component NH member be A, B, C
2757 : //And new component NH member be D, A, B, C in any of 24 combination
2758 : //Then new composite NH has to be A, B, C, D in that order, such that
2759 : //A, B, C nexthop retain there position
2760 1 : if (!nh) {
2761 0 : return policy;
2762 : }
2763 :
2764 1 : if (nh->GetType() != NextHop::COMPOSITE) {
2765 1 : DBEntryBase::KeyPtr key = nh->GetDBRequestKey();
2766 1 : NextHopKey *nh_key = static_cast<NextHopKey *>(key.release());
2767 1 : nh_key->SetPolicy(false);
2768 1 : std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
2769 : //Insert exisiting nexthop at first slot
2770 : //This ensures that old flows are not disturbed
2771 : ComponentNHKeyPtr component_nh_key(new ComponentNHKey(label,
2772 1 : std::move(nh_key_ptr)));
2773 1 : if (find(component_nh_key)) {
2774 : //Swap first entry and previous nexthop which
2775 : //route would have been pointing to
2776 0 : ComponentNHKeyPtr first_entry = component_nh_key_list_[0];
2777 0 : erase(first_entry);
2778 0 : erase(component_nh_key);
2779 0 : insert(component_nh_key);
2780 0 : insert(first_entry);
2781 0 : }
2782 1 : return policy;
2783 1 : }
2784 :
2785 : CompositeNHKey *composite_nh_key;
2786 0 : DBEntryBase::KeyPtr key = nh->GetDBRequestKey();
2787 0 : composite_nh_key = static_cast<CompositeNHKey *>(key.get());
2788 : // Delete entries not present in the new composite NH key
2789 0 : BOOST_FOREACH(ComponentNHKeyPtr component_nh_key,
2790 : composite_nh_key->component_nh_key_list()) {
2791 0 : if (component_nh_key != NULL &&
2792 0 : find(component_nh_key) == false) {
2793 0 : composite_nh_key->erase(component_nh_key);
2794 : }
2795 0 : }
2796 :
2797 : // Add new entries
2798 0 : BOOST_FOREACH(ComponentNHKeyPtr component_nh_key,
2799 : component_nh_key_list()) {
2800 0 : if (component_nh_key != NULL) {
2801 0 : composite_nh_key->insert(component_nh_key);
2802 : }
2803 0 : }
2804 : // Copy over the list
2805 0 : component_nh_key_list_ = composite_nh_key->component_nh_key_list();
2806 0 : return policy;
2807 0 : }
2808 :
2809 0 : ComponentNHKey::ComponentNHKey(int label, Composite::Type type, bool policy,
2810 0 : const ComponentNHKeyList &component_nh_list, const std::string &vrf_name):
2811 0 : label_(label), nh_key_(new CompositeNHKey(type, policy, component_nh_list,
2812 0 : vrf_name)) {
2813 0 : }
2814 :
2815 0 : PBBNH::PBBNH(VrfEntry *vrf, const MacAddress &dest_bmac, uint32_t isid):
2816 0 : NextHop(NextHop::PBB, true, false), vrf_(vrf, this), dest_bmac_(dest_bmac),
2817 0 : isid_(isid), label_(MplsTable::kInvalidLabel), child_nh_(NULL){
2818 0 : }
2819 :
2820 0 : PBBNH::~PBBNH() {
2821 0 : }
2822 :
2823 0 : bool PBBNH::CanAdd() const {
2824 0 : if (vrf_ == NULL) {
2825 0 : LOG(ERROR, "Invalid VRF in PBBNH. Skip Add");
2826 0 : return false;
2827 : }
2828 :
2829 0 : if (dest_bmac_ == MacAddress::ZeroMac()) {
2830 0 : LOG(ERROR, "Invalid tunnel-destination in PBBNH");
2831 : }
2832 :
2833 0 : return true;
2834 : }
2835 :
2836 0 : NextHop *PBBNHKey::AllocEntry() const {
2837 0 : VrfEntry *vrf = static_cast<VrfEntry *>
2838 0 : (Agent::GetInstance()->vrf_table()->Find(&vrf_key_, true));
2839 0 : return new PBBNH(vrf, dest_bmac_, isid_);
2840 : }
2841 :
2842 0 : bool PBBNH::NextHopIsLess(const DBEntry &rhs) const {
2843 0 : const PBBNH &a = static_cast<const PBBNH &>(rhs);
2844 :
2845 0 : if (vrf_.get() != a.vrf_.get()) {
2846 0 : return vrf_.get() < a.vrf_.get();
2847 : }
2848 :
2849 0 : if (dest_bmac_ != a.dest_bmac_) {
2850 0 : return dest_bmac_ < a.dest_bmac_;
2851 : }
2852 :
2853 0 : return isid_ < a.isid_;
2854 : }
2855 :
2856 0 : void PBBNH::SetKey(const DBRequestKey *k) {
2857 0 : const PBBNHKey *key = static_cast<const PBBNHKey *>(k);
2858 0 : NextHop::SetKey(k);
2859 0 : vrf_ = NextHopTable::GetInstance()->FindVrfEntry(key->vrf_key_);
2860 0 : dest_bmac_ = key->dest_bmac_;
2861 0 : policy_ = key->policy_;
2862 0 : isid_ = key->isid_;
2863 0 : }
2864 :
2865 0 : PBBNH::KeyPtr PBBNH::GetDBRequestKey() const {
2866 0 : NextHopKey *key = new PBBNHKey(vrf_->GetName(), dest_bmac_, isid_);
2867 0 : return DBEntryBase::KeyPtr(key);
2868 : }
2869 :
2870 0 : const uint32_t PBBNH::vrf_id() const {
2871 0 : return vrf_->vrf_id();
2872 : }
2873 :
2874 0 : bool PBBNH::ChangeEntry(const DBRequest *req) {
2875 0 : bool ret = false;
2876 0 : Agent *agent = Agent::GetInstance();
2877 : BridgeAgentRouteTable *rt_table =
2878 0 : static_cast<BridgeAgentRouteTable *>(vrf_->GetBridgeRouteTable());
2879 0 : BridgeRouteEntry *rt = rt_table->FindRouteNoLock(dest_bmac_);
2880 :
2881 0 : uint32_t label = MplsTable::kInvalidLabel;
2882 0 : const NextHop *nh = NULL;
2883 :
2884 0 : if (!rt) {
2885 0 : DiscardNHKey key;
2886 0 : nh = static_cast<NextHop *>
2887 0 : (agent->nexthop_table()->FindActiveEntry(&key));
2888 0 : } else {
2889 0 : nh = rt->GetActiveNextHop();
2890 0 : label = rt->GetActiveLabel();
2891 : }
2892 :
2893 0 : if (nh != child_nh_.get()) {
2894 0 : child_nh_ = nh;
2895 0 : ret = true;
2896 : }
2897 :
2898 0 : if (label_ != label) {
2899 0 : label_ = label;
2900 0 : ret = true;
2901 : }
2902 : const AgentPath *path;
2903 0 : if (rt && (path = rt->GetActivePath()) != NULL) {
2904 0 : if (etree_leaf_ != path->etree_leaf()) {
2905 0 : etree_leaf_ = path->etree_leaf();
2906 0 : ret = true;
2907 : }
2908 : }
2909 :
2910 0 : return ret;
2911 : }
2912 :
2913 0 : void PBBNH::Delete(const DBRequest *req) {
2914 0 : child_nh_.reset(NULL);
2915 0 : }
2916 :
2917 0 : void PBBNH::SendObjectLog(const NextHopTable *table,
2918 : AgentLogEvent::type event) const {
2919 0 : NextHopObjectLogInfo info;
2920 0 : FillObjectLog(event, info);
2921 :
2922 0 : if (vrf_) {
2923 0 : info.set_vrf(vrf_->GetName());
2924 : }
2925 0 : info.set_mac(dest_bmac_.ToString());
2926 0 : OPER_TRACE_ENTRY(NextHop, table, info);
2927 0 : }
2928 :
2929 : /////////////////////////////////////////////////////////////////////////////
2930 : // NextHop Sandesh routines
2931 : /////////////////////////////////////////////////////////////////////////////
2932 0 : static void FillComponentNextHop(const CompositeNH *comp_nh,
2933 : std::vector<McastData> &list)
2934 : {
2935 0 : for (ComponentNHList::const_iterator it = comp_nh->begin();
2936 0 : it != comp_nh->end(); it++) {
2937 0 : const ComponentNH *component_nh = (*it).get();
2938 0 : McastData sdata;
2939 0 : if (component_nh == NULL) {
2940 0 : sdata.set_type("NULL");
2941 0 : list.push_back(sdata);
2942 0 : continue;
2943 : }
2944 0 : switch (component_nh->nh()->GetType()) {
2945 0 : case NextHop::INTERFACE: {
2946 0 : sdata.set_type("Interface");
2947 : const InterfaceNH *sub_nh =
2948 0 : static_cast<const InterfaceNH *>(component_nh->nh());
2949 0 : if (sub_nh && sub_nh->GetInterface())
2950 0 : sdata.set_label(component_nh->label());
2951 0 : sdata.set_itf(sub_nh->GetInterface()->name());
2952 0 : list.push_back(sdata);
2953 0 : break;
2954 : }
2955 0 : case NextHop::TUNNEL: {
2956 0 : sdata.set_type("Tunnel");
2957 : const TunnelNH *tnh =
2958 0 : static_cast<const TunnelNH *>(component_nh->nh());
2959 0 : sdata.set_dip(tnh->GetDip()->to_string());
2960 0 : sdata.set_sip(tnh->GetSip()->to_string());
2961 0 : sdata.set_label(component_nh->label());
2962 0 : list.push_back(sdata);
2963 0 : break;
2964 : }
2965 0 : case NextHop::VLAN: {
2966 0 : sdata.set_type("Vlan");
2967 : const VlanNH *vlan_nh =
2968 0 : static_cast<const VlanNH *>(component_nh->nh());
2969 0 : sdata.set_itf(vlan_nh->GetInterface()->name());
2970 0 : sdata.set_vlan_tag(vlan_nh->GetVlanTag());
2971 0 : list.push_back(sdata);
2972 0 : break;
2973 : }
2974 0 : case NextHop::COMPOSITE: {
2975 0 : sdata.set_type("Composite");
2976 : const CompositeNH *child_component_nh =
2977 0 : static_cast<const CompositeNH *>(component_nh->nh());
2978 0 : std::vector<McastData> comp_list;
2979 0 : FillComponentNextHop(child_component_nh, comp_list);
2980 0 : list.insert(list.begin(), comp_list.begin(), comp_list.end());
2981 0 : break;
2982 0 : }
2983 0 : default:
2984 0 : std::stringstream s;
2985 0 : s << "UNKNOWN<" << component_nh->nh()->GetType()
2986 0 : << ">";
2987 0 : sdata.set_type(s.str());
2988 0 : list.push_back(sdata);
2989 0 : break;
2990 : }
2991 0 : }
2992 0 : }
2993 :
2994 0 : static void FillL2CompositeNextHop(const CompositeNH *comp_nh,
2995 : L2CompositeData &data)
2996 : {
2997 0 : std::stringstream str;
2998 0 : str << "L2 Composite, subnh count : "
2999 0 : << comp_nh->ComponentNHCount();
3000 0 : data.set_type(str.str());
3001 0 : if (comp_nh->ComponentNHCount() == 0)
3002 0 : return;
3003 0 : std::vector<McastData> data_list;
3004 0 : FillComponentNextHop(comp_nh, data_list);
3005 0 : data.set_mc_list(data_list);
3006 0 : }
3007 :
3008 0 : static void FillL3CompositeNextHop(const CompositeNH *comp_nh,
3009 : L3CompositeData &data)
3010 : {
3011 0 : std::stringstream str;
3012 0 : str << "L3 Composite, subnh count : "
3013 0 : << comp_nh->ComponentNHCount();
3014 0 : data.set_type(str.str());
3015 0 : if (comp_nh->ComponentNHCount() == 0)
3016 0 : return;
3017 0 : std::vector<McastData> data_list;
3018 0 : FillComponentNextHop(comp_nh, data_list);
3019 0 : data.set_mc_list(data_list);
3020 0 : }
3021 :
3022 0 : static void FillMultiProtoCompositeNextHop(const CompositeNH *comp_nh,
3023 : NhSandeshData &data)
3024 : {
3025 0 : std::stringstream str;
3026 0 : str << "Multi Proto Composite, subnh count : "
3027 0 : << comp_nh->ComponentNHCount();
3028 0 : data.set_type(str.str());
3029 0 : if (comp_nh->ComponentNHCount() == 0)
3030 0 : return;
3031 0 : for (ComponentNHList::const_iterator it = comp_nh->begin();
3032 0 : it != comp_nh->end(); it++) {
3033 0 : const ComponentNH *component_nh = (*it).get();
3034 0 : if (component_nh == NULL) {
3035 0 : continue;
3036 : }
3037 : const CompositeNH *sub_cnh =
3038 0 : static_cast<const CompositeNH *>(component_nh->nh());
3039 0 : if (sub_cnh->composite_nh_type() == Composite::L2COMP) {
3040 0 : L2CompositeData l2_data;
3041 0 : FillL2CompositeNextHop(sub_cnh, l2_data);
3042 0 : data.set_l2_comp(l2_data);
3043 0 : }
3044 0 : if (sub_cnh->composite_nh_type() == Composite::L3COMP) {
3045 0 : L3CompositeData l3_data;
3046 0 : FillL3CompositeNextHop(sub_cnh, l3_data);
3047 0 : data.set_l3_comp(l3_data);
3048 0 : }
3049 : }
3050 0 : }
3051 :
3052 0 : static void ExpandCompositeNextHop(const CompositeNH *comp_nh,
3053 : NhSandeshData &data)
3054 : {
3055 0 : stringstream comp_str;
3056 0 : switch (comp_nh->composite_nh_type()) {
3057 0 : case Composite::EVPN: {
3058 0 : comp_str << "evpn Composite" << " sub nh count: "
3059 0 : << comp_nh->ComponentNHCount();
3060 0 : data.set_type(comp_str.str());
3061 0 : if (comp_nh->ComponentNHCount() == 0)
3062 0 : break;
3063 0 : std::vector<McastData> data_list;
3064 0 : FillComponentNextHop(comp_nh, data_list);
3065 0 : data.set_mc_list(data_list);
3066 0 : break;
3067 0 : }
3068 0 : case Composite::TOR: {
3069 0 : comp_str << "TOR Composite" << " sub nh count: "
3070 0 : << comp_nh->ComponentNHCount();
3071 0 : data.set_type(comp_str.str());
3072 0 : if (comp_nh->ComponentNHCount() == 0)
3073 0 : break;
3074 0 : std::vector<McastData> data_list;
3075 0 : FillComponentNextHop(comp_nh, data_list);
3076 0 : data.set_mc_list(data_list);
3077 0 : break;
3078 0 : }
3079 0 : case Composite::FABRIC: {
3080 0 : comp_str << "fabric Composite" << " sub nh count: "
3081 0 : << comp_nh->ComponentNHCount();
3082 0 : data.set_type(comp_str.str());
3083 0 : if (comp_nh->ComponentNHCount() == 0)
3084 0 : break;
3085 0 : std::vector<McastData> data_list;
3086 0 : FillComponentNextHop(comp_nh, data_list);
3087 0 : data.set_mc_list(data_list);
3088 0 : break;
3089 0 : }
3090 0 : case Composite::L3FABRIC: {
3091 0 : comp_str << "L3 Fabric Composite" << " sub nh count: "
3092 0 : << comp_nh->ComponentNHCount();
3093 0 : data.set_type(comp_str.str());
3094 0 : if (comp_nh->ComponentNHCount() == 0)
3095 0 : break;
3096 0 : std::vector<McastData> data_list;
3097 0 : FillComponentNextHop(comp_nh, data_list);
3098 0 : data.set_mc_list(data_list);
3099 0 : break;
3100 0 : }
3101 0 : case Composite::L3COMP: {
3102 0 : comp_str << "L3 Composite" << " sub nh count: "
3103 0 : << comp_nh->ComponentNHCount();
3104 0 : data.set_type(comp_str.str());
3105 0 : if (comp_nh->ComponentNHCount() == 0)
3106 0 : break;
3107 0 : std::vector<McastData> data_list;
3108 0 : FillComponentNextHop(comp_nh, data_list);
3109 0 : data.set_mc_list(data_list);
3110 0 : break;
3111 0 : }
3112 0 : case Composite::L2COMP: {
3113 0 : comp_str << "L2 Composite" << " sub nh count: "
3114 0 : << comp_nh->ComponentNHCount();
3115 0 : data.set_type(comp_str.str());
3116 0 : if (comp_nh->ComponentNHCount() == 0)
3117 0 : break;
3118 0 : std::vector<McastData> data_list;
3119 0 : FillComponentNextHop(comp_nh, data_list);
3120 0 : data.set_mc_list(data_list);
3121 0 : break;
3122 0 : }
3123 0 : case Composite::L2INTERFACE: {
3124 0 : comp_str << "L2 interface Composite" << " sub nh count: "
3125 0 : << comp_nh->ComponentNHCount();
3126 0 : data.set_type(comp_str.str());
3127 0 : if (comp_nh->ComponentNHCount() == 0)
3128 0 : break;
3129 0 : std::vector<McastData> data_list;
3130 0 : FillComponentNextHop(comp_nh, data_list);
3131 0 : data.set_mc_list(data_list);
3132 0 : break;
3133 0 : }
3134 0 : case Composite::L3INTERFACE: {
3135 0 : comp_str << "L3 interface Composite" << " sub nh count: "
3136 0 : << comp_nh->ComponentNHCount();
3137 0 : data.set_type(comp_str.str());
3138 0 : if (comp_nh->ComponentNHCount() == 0)
3139 0 : break;
3140 0 : std::vector<McastData> data_list;
3141 0 : FillComponentNextHop(comp_nh, data_list);
3142 0 : data.set_mc_list(data_list);
3143 0 : break;
3144 0 : }
3145 0 : case Composite::MULTIPROTO: {
3146 0 : comp_str << "Multiproto Composite" << " sub nh count: "
3147 0 : << comp_nh->ComponentNHCount();
3148 0 : data.set_type(comp_str.str());
3149 0 : FillMultiProtoCompositeNextHop(comp_nh, data);
3150 0 : break;
3151 : }
3152 0 : case Composite::ECMP:
3153 : case Composite::LOCAL_ECMP:
3154 : case Composite::LU_ECMP: {
3155 0 : comp_str << "ECMP Composite" << " sub nh count: "
3156 0 : << comp_nh->ComponentNHCount();
3157 0 : data.set_type(comp_str.str());
3158 0 : std::vector<McastData> data_list;
3159 0 : FillComponentNextHop(comp_nh, data_list);
3160 0 : data.set_mc_list(data_list);
3161 0 : break;
3162 0 : }
3163 0 : default: {
3164 0 : comp_str << "UNKNOWN<" << comp_nh->composite_nh_type()
3165 0 : << ">";
3166 0 : data.set_type(comp_str.str());
3167 0 : break;
3168 : }
3169 : }
3170 0 : }
3171 :
3172 0 : void NextHop::SetNHSandeshData(NhSandeshData &data) const {
3173 0 : data.set_nh_index(id());
3174 0 : data.set_vxlan_flag(false);
3175 0 : data.set_intf_flags(0);
3176 0 : switch (type_) {
3177 0 : case DISCARD:
3178 0 : data.set_type("discard");
3179 0 : break;
3180 0 : case L2_RECEIVE:
3181 0 : data.set_type("l2-receive");
3182 0 : break;
3183 0 : case RECEIVE: {
3184 0 : data.set_type("receive");
3185 0 : const ReceiveNH *nh = static_cast<const ReceiveNH *>(this);
3186 0 : if (nh->GetInterface()) {
3187 0 : data.set_itf(nh->GetInterface()->name());
3188 : } else {
3189 0 : data.set_itf("<NULL>");
3190 : }
3191 0 : break;
3192 : }
3193 0 : case RESOLVE:
3194 0 : data.set_type("resolve");
3195 0 : break;
3196 0 : case ARP: {
3197 0 : data.set_type("arp");
3198 0 : const ArpNH *arp = static_cast<const ArpNH *>(this);
3199 0 : data.set_sip(arp->GetIp()->to_string());
3200 0 : data.set_vrf(arp->GetVrf()->GetName());
3201 0 : if (valid_ == false) {
3202 0 : break;
3203 : }
3204 0 : data.set_itf(arp->GetInterface()->name());
3205 0 : const unsigned char *m = arp->GetMac().GetData();
3206 : char mstr[32];
3207 0 : snprintf(mstr, 32, "%x:%x:%x:%x:%x:%x",
3208 0 : m[0], m[1], m[2], m[3], m[4], m[5]);
3209 0 : std::string mac(mstr);
3210 0 : data.set_mac(std::vector<std::string>(1, mac));
3211 0 : break;
3212 0 : }
3213 0 : case NDP: {
3214 0 : data.set_type("ndp");
3215 0 : const NdpNH *ndp = static_cast<const NdpNH *>(this);
3216 0 : data.set_sip(ndp->GetIp()->to_string());
3217 0 : data.set_vrf(ndp->GetVrf()->GetName());
3218 0 : if (valid_ == false) {
3219 0 : break;
3220 : }
3221 0 : data.set_itf(ndp->GetInterface()->name());
3222 0 : const unsigned char *m = ndp->GetMac().GetData();
3223 : char mstr[32];
3224 0 : snprintf(mstr, 32, "%x:%x:%x:%x:%x:%x",
3225 0 : m[0], m[1], m[2], m[3], m[4], m[5]);
3226 0 : std::string mac(mstr);
3227 0 : data.set_mac(std::vector<std::string>(1, mac));
3228 0 : break;
3229 0 : }
3230 0 : case VRF: {
3231 0 : data.set_type("vrf");
3232 0 : const VrfNH *vrf = static_cast<const VrfNH *>(this);
3233 0 : data.set_vrf(vrf->GetVrf()->GetName());
3234 0 : data.set_vxlan_flag(vrf->bridge_nh());
3235 0 : data.set_flood_unknown_unicast(vrf->flood_unknown_unicast());
3236 0 : data.set_layer2_control_word(vrf->layer2_control_word());
3237 0 : break;
3238 : }
3239 0 : case INTERFACE: {
3240 0 : data.set_type("interface");
3241 0 : const InterfaceNH *itf = static_cast<const InterfaceNH *>(this);
3242 0 : data.set_itf(itf->GetInterface()->name());
3243 0 : const unsigned char *m = itf->GetDMac().GetData();
3244 : char mstr[32];
3245 0 : snprintf(mstr, 32, "%x:%x:%x:%x:%x:%x",
3246 0 : m[0], m[1], m[2], m[3], m[4], m[5]);
3247 0 : std::string mac(mstr);
3248 0 : data.set_mac(std::vector<std::string>(1, mac));
3249 0 : if (itf->is_multicastNH())
3250 0 : data.set_mcast("enabled");
3251 : else
3252 0 : data.set_mcast("disabled");
3253 0 : data.set_layer2_control_word(itf->layer2_control_word());
3254 0 : data.set_vxlan_flag(itf->IsVxlanRouting());
3255 0 : data.set_intf_flags(itf->GetFlags());
3256 0 : break;
3257 0 : }
3258 0 : case TUNNEL: {
3259 0 : data.set_type("tunnel");
3260 0 : const TunnelNH *tun = static_cast<const TunnelNH *>(this);
3261 0 : data.set_sip(tun->GetSip()->to_string());
3262 0 : data.set_dip(tun->GetDip()->to_string());
3263 0 : data.set_vrf(tun->GetVrf()->GetName());
3264 0 : data.set_tunnel_type(tun->GetTunnelType().ToString());
3265 0 : if (valid_) {
3266 0 : const NextHop *anh = tun->GetRt()->GetActiveNextHop();
3267 0 : if (anh != NULL) {
3268 0 : const NextHop *nh = static_cast<const NextHop *>(anh);
3269 0 : if (nh->GetType() == NextHop::ARP) {
3270 0 : const ArpNH *arp_nh = static_cast<const ArpNH *>(nh);
3271 0 : const unsigned char *m = arp_nh->GetMac().GetData();
3272 : char mstr[32];
3273 0 : snprintf(mstr, 32, "%x:%x:%x:%x:%x:%x",
3274 0 : m[0], m[1], m[2], m[3], m[4], m[5]);
3275 0 : std::string mac(mstr);
3276 0 : data.set_mac(std::vector<std::string>(1, mac));
3277 0 : } else if (nh->GetType() == NextHop::NDP) {
3278 0 : const NdpNH *ndp_nh = static_cast<const NdpNH *>(nh);
3279 0 : const unsigned char *m = ndp_nh->GetMac().GetData();
3280 : char mstr[32];
3281 0 : snprintf(mstr, 32, "%x:%x:%x:%x:%x:%x",
3282 0 : m[0], m[1], m[2], m[3], m[4], m[5]);
3283 0 : std::string mac(mstr);
3284 0 : data.set_mac(std::vector<std::string>(1, mac));
3285 0 : } else if (nh->GetType() == NextHop::COMPOSITE) {
3286 0 : const CompositeNH *cnh = dynamic_cast<const CompositeNH*>(nh);
3287 : ComponentNHList::const_iterator component_nh_it =
3288 0 : cnh->begin();
3289 0 : std::vector<std::string> mac_list;
3290 0 : while (component_nh_it != cnh->end()) {
3291 0 : const NextHop *component_nh = NULL;
3292 0 : if (*component_nh_it) {
3293 0 : component_nh = (*component_nh_it)->nh();
3294 0 : if (component_nh->GetType() == NextHop::ARP) {
3295 0 : const ArpNH *arp_nh = dynamic_cast<const ArpNH*>(component_nh);
3296 0 : const unsigned char *m = arp_nh->GetMac().GetData();
3297 : char mstr[32];
3298 0 : snprintf(mstr, 32, "%x:%x:%x:%x:%x:%x",
3299 0 : m[0], m[1], m[2], m[3], m[4], m[5]);
3300 0 : std::string mac(mstr);
3301 0 : mac_list.push_back(mac);
3302 0 : }
3303 : }
3304 0 : component_nh_it++;
3305 : }
3306 0 : data.set_mac(mac_list);
3307 0 : }
3308 : }
3309 : }
3310 0 : data.set_crypt_all_traffic(tun->GetCrypt());
3311 0 : if (tun->GetCryptTunnelAvailable()) {
3312 0 : data.set_crypt_path_available(tun->GetCryptTunnelAvailable());
3313 0 : data.set_crypt_interface(tun->GetCryptInterface()->name());
3314 : }
3315 0 : if (tun->rewrite_dmac().IsZero() == false) {
3316 0 : data.set_vxlan_flag(true);
3317 0 : data.set_pbb_bmac(tun->rewrite_dmac().ToString());
3318 : }
3319 0 : break;
3320 : }
3321 0 : case MIRROR: {
3322 0 : data.set_type("Mirror");
3323 0 : const MirrorNH *mir_nh = static_cast<const MirrorNH *>(this);
3324 0 : data.set_sip(mir_nh->GetSip()->to_string());
3325 0 : data.set_dip(mir_nh->GetDip()->to_string());
3326 0 : data.set_vrf(mir_nh->GetVrf() ? mir_nh->GetVrf()->GetName() : "");
3327 0 : data.set_sport(mir_nh->GetSPort());
3328 0 : data.set_dport(mir_nh->GetDPort());
3329 0 : if (valid_ && mir_nh->GetVrf()) {
3330 0 : const NextHop *mnh = mir_nh->GetRt()->GetActiveNextHop();
3331 0 : if (mnh != NULL) {
3332 0 : const NextHop *nh = static_cast<const NextHop *>(mnh);
3333 0 : if (nh->GetType() == NextHop::ARP) {
3334 0 : const ArpNH *arp_nh = static_cast<const ArpNH *>(nh);
3335 0 : (mir_nh->GetRt()->GetActiveNextHop());
3336 0 : const unsigned char *m = arp_nh->GetMac().GetData();
3337 : char mstr[32];
3338 0 : snprintf(mstr, 32, "%x:%x:%x:%x:%x:%x",
3339 0 : m[0], m[1], m[2], m[3], m[4], m[5]);
3340 0 : std::string mac(mstr);
3341 0 : data.set_mac(std::vector<std::string>(1, mac));
3342 0 : } else if (nh->GetType() == NextHop::NDP) {
3343 0 : const NdpNH *ndp_nh = static_cast<const NdpNH *>(nh);
3344 0 : (mir_nh->GetRt()->GetActiveNextHop());
3345 0 : const unsigned char *m = ndp_nh->GetMac().GetData();
3346 : char mstr[32];
3347 0 : snprintf(mstr, 32, "%x:%x:%x:%x:%x:%x",
3348 0 : m[0], m[1], m[2], m[3], m[4], m[5]);
3349 0 : std::string mac(mstr);
3350 0 : data.set_mac(std::vector<std::string>(1, mac));
3351 0 : } else if (nh->GetType() == NextHop::RECEIVE) {
3352 0 : const ReceiveNH *rcv_nh = static_cast<const ReceiveNH*>(nh);
3353 0 : data.set_itf(rcv_nh->GetInterface()->name());
3354 0 : } else if (nh->GetType() == NextHop::COMPOSITE) {
3355 0 : const CompositeNH *cnh = dynamic_cast<const CompositeNH*>(nh);
3356 : ComponentNHList::const_iterator component_nh_it =
3357 0 : cnh->begin();
3358 0 : std::vector<std::string> mac_list;
3359 0 : while (component_nh_it != cnh->end()) {
3360 0 : const NextHop *component_nh = NULL;
3361 0 : if (*component_nh_it) {
3362 0 : component_nh = (*component_nh_it)->nh();
3363 0 : if (component_nh->GetType() == NextHop::ARP) {
3364 0 : const ArpNH *arp_nh = dynamic_cast<const ArpNH*>(component_nh);
3365 0 : const unsigned char *m = arp_nh->GetMac().GetData();
3366 : char mstr[32];
3367 0 : snprintf(mstr, 32, "%x:%x:%x:%x:%x:%x",
3368 0 : m[0], m[1], m[2], m[3], m[4], m[5]);
3369 0 : std::string mac(mstr);
3370 0 : mac_list.push_back(mac);
3371 0 : }
3372 : }
3373 0 : component_nh_it++;
3374 : }
3375 0 : data.set_mac(mac_list);
3376 :
3377 0 : }
3378 : }
3379 : }
3380 0 : break;
3381 : }
3382 0 : case COMPOSITE: {
3383 0 : const CompositeNH *comp_nh = static_cast<const CompositeNH *>(this);
3384 0 : ExpandCompositeNextHop(comp_nh, data);
3385 0 : data.set_layer2_control_word(comp_nh->layer2_control_word());
3386 0 : break;
3387 : }
3388 :
3389 0 : case PBB: {
3390 0 : data.set_type("PBB Tunnel");
3391 0 : const PBBNH *pbb_nh = static_cast<const PBBNH *>(this);
3392 0 : data.set_pbb_bmac(pbb_nh->dest_bmac().ToString());
3393 0 : data.set_vrf(pbb_nh->vrf()->GetName());
3394 0 : data.set_isid(pbb_nh->isid());
3395 0 : std::vector<McastData> data_list;
3396 : const TunnelNH *tnh =
3397 0 : dynamic_cast<const TunnelNH *>(pbb_nh->child_nh());
3398 0 : if (tnh) {
3399 0 : McastData sdata;
3400 0 : sdata.set_type("Tunnel");
3401 0 : sdata.set_dip(tnh->GetDip()->to_string());
3402 0 : sdata.set_sip(tnh->GetSip()->to_string());
3403 0 : sdata.set_label(pbb_nh->label());
3404 0 : data_list.push_back(sdata);
3405 0 : }
3406 0 : data.set_mc_list(data_list);
3407 0 : break;
3408 0 : }
3409 :
3410 0 : case VLAN: {
3411 0 : data.set_type("vlan");
3412 0 : const VlanNH *itf = static_cast<const VlanNH *>(this);
3413 0 : data.set_itf(itf->GetInterface()->name());
3414 0 : data.set_vlan_tag(itf->GetVlanTag());
3415 0 : const unsigned char *m = itf->GetDMac().GetData();
3416 : char mstr[32];
3417 0 : snprintf(mstr, 32, "%x:%x:%x:%x:%x:%x",
3418 0 : m[0], m[1], m[2], m[3], m[4], m[5]);
3419 0 : std::string mac(mstr);
3420 0 : data.set_mac(std::vector<std::string>(1, mac));
3421 0 : break;
3422 0 : }
3423 :
3424 0 : case INVALID:
3425 : default:
3426 0 : data.set_type("invalid");
3427 0 : break;
3428 : }
3429 0 : if (valid_) {
3430 0 : data.set_valid("true");
3431 : } else {
3432 0 : data.set_valid("false");
3433 : }
3434 :
3435 0 : data.set_learning_enabled(learning_enabled_);
3436 0 : data.set_etree_leaf(etree_leaf_);
3437 :
3438 0 : if (policy_) {
3439 0 : data.set_policy("enabled");
3440 : } else {
3441 0 : data.set_policy("disabled");
3442 : }
3443 :
3444 0 : data.set_ref_count(GetRefCount());
3445 0 : }
3446 :
3447 25 : NextHop *NextHopTable::FindNextHop(size_t index) {
3448 25 : NextHop *nh = index_table_.At(index);
3449 25 : if (nh && nh->IsDeleted() != true) {
3450 25 : return nh;
3451 : }
3452 0 : return NULL;
3453 : }
3454 :
3455 0 : bool NextHop::DBEntrySandesh(Sandesh *sresp, std::string &name) const {
3456 0 : NhListResp *resp = static_cast<NhListResp *>(sresp);
3457 :
3458 0 : NhSandeshData data;
3459 0 : SetNHSandeshData(data);
3460 : std::vector<NhSandeshData> &list =
3461 0 : const_cast<std::vector<NhSandeshData>&>(resp->get_nh_list());
3462 0 : list.push_back(data);
3463 :
3464 0 : return true;
3465 0 : }
3466 :
3467 0 : void NhListReq::HandleRequest() const {
3468 0 : AgentSandeshPtr sand(new AgentNhSandesh(context(), get_type(),
3469 0 : get_nh_index(), get_policy_enabled()));
3470 0 : sand->DoSandesh(sand);
3471 0 : }
3472 :
3473 0 : AgentSandeshPtr NextHopTable::GetAgentSandesh(const AgentSandeshArguments *args,
3474 : const std::string &context) {
3475 : return AgentSandeshPtr(new AgentNhSandesh(context,
3476 0 : args->GetString("type"), args->GetString("nh_index"),
3477 0 : args->GetString("policy_enabled")));
3478 : }
|