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: 1059 2293 46.2 %
Date: 2026-11-09 02:10:49 Functions: 114 196 58.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14