LCOV - code coverage report
Current view: top level - vnsw/agent/oper - nexthop.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 837 2293 36.5 %
Date: 2026-06-04 02:06:09 Functions: 103 196 52.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14