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