LCOV - code coverage report
Current view: top level - vnsw/agent/oper - agent_path.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 433 1320 32.8 %
Date: 2026-06-18 01:51:13 Functions: 37 83 44.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <boost/uuid/uuid_io.hpp>
       6             : #include <boost/lexical_cast.hpp>
       7             : #include <boost/foreach.hpp>
       8             : #include <cmn/agent_cmn.h>
       9             : #include <route/route.h>
      10             : #include <init/agent_param.h>
      11             : 
      12             : #include <vnc_cfg_types.h>
      13             : #include <agent_types.h>
      14             : 
      15             : #include <filter/acl.h>
      16             : 
      17             : #include <oper/peer.h>
      18             : #include <oper/vrf.h>
      19             : #include <oper/interface_common.h>
      20             : #include <oper/nexthop.h>
      21             : #include <oper/tunnel_nh.h>
      22             : #include <oper/vn.h>
      23             : #include <oper/mirror_table.h>
      24             : #include <oper/vxlan.h>
      25             : #include <oper/mpls.h>
      26             : #include <oper/route_common.h>
      27             : #include <oper/ecmp_load_balance.h>
      28             : #include <oper/agent_sandesh.h>
      29             : #include <oper/tsn_elector.h>
      30             : 
      31             : using namespace std;
      32             : using namespace boost::asio;
      33             : 
      34             : //Helpers
      35           0 : bool RebakeLabel(MplsTable *table, uint32_t label, NextHop *nh) {
      36           0 :     bool ret = false;
      37           0 :     if (label != MplsTable::kInvalidLabel) {
      38           0 :         MplsLabelKey key(label);
      39           0 :         MplsLabel *mpls = static_cast<MplsLabel *>(table->
      40           0 :                                                    FindActiveEntry(&key));
      41           0 :         if (mpls && mpls->ChangeNH(nh)) {
      42           0 :             ret = true;
      43             :             //Send notify of change
      44           0 :             mpls->get_table_partition()->Notify(mpls);
      45             :         }
      46           0 :     }
      47           0 :     return ret;
      48             : }
      49             : 
      50             : //AgentPath
      51          19 : AgentPath::AgentPath(const Peer *peer, AgentRoute *rt):
      52          19 :     Path(), peer_(peer), nh_(NULL), label_(MplsTable::kInvalidLabel),
      53          19 :     vxlan_id_(VxLanTable::kInvalidvxlan_id), dest_vn_list_(),
      54          19 :     origin_vn_(""), sync_(false), force_policy_(false), sg_list_(),
      55          19 :     tunnel_dest_(0), tunnel_bmap_(TunnelType::AllType()),
      56          19 :     tunnel_type_(TunnelType::ComputeType(TunnelType::AllType())),
      57          19 :     vrf_name_(""), gw_ip_(), unresolved_(true),
      58          19 :     is_subnet_discard_(false), dependant_rt_(rt), path_preference_(),
      59          19 :     local_ecmp_mpls_label_(rt), composite_nh_key_(NULL), subnet_service_ip_(),
      60          19 :     arp_mac_(), arp_interface_(NULL), arp_valid_(false),
      61          38 :     ecmp_suppressed_(false), is_local_(false), is_health_check_service_(false),
      62          19 :     peer_sequence_number_(0), etree_leaf_(false), layer2_control_word_(false),
      63          57 :     inactive_(false), copy_local_path_(false), parent_rt_(rt), dependent_table_(NULL) {
      64          19 : }
      65             : 
      66          35 : AgentPath::~AgentPath() {
      67          19 :     clear_sg_list();
      68          35 : }
      69             : 
      70           0 : uint32_t AgentPath::GetTunnelBmap() const {
      71           0 :     TunnelType::Type type = TunnelType::ComputeType(tunnel_bmap_);
      72           0 :     if ((type == (1 << TunnelType::VXLAN)) && (vxlan_id_ != 0)) {
      73           0 :         return (1 << TunnelType::VXLAN);
      74             :     } else {
      75           0 :         return tunnel_bmap_;
      76             :     }
      77             : }
      78             : 
      79          51 : uint32_t AgentPath::GetActiveLabel() const {
      80          51 :     if (tunnel_type_ == TunnelType::VXLAN) {
      81           0 :         return vxlan_id_;
      82             :     } else {
      83          51 :         return label_;
      84             :     }
      85             : }
      86             : 
      87         253 : NextHop* AgentPath::nexthop() const {
      88         253 :     return nh_.get();
      89             : }
      90             : 
      91         376 : const NextHop* AgentPath::ComputeNextHop(Agent *agent) const {
      92         376 :     if (nh_) {
      93         304 :         return nh_.get();
      94             :     }
      95             : 
      96          72 :     if (unresolved_ == true) {
      97          45 :         DiscardNH key;
      98          45 :         return static_cast<NextHop *>
      99          45 :             (agent->nexthop_table()->FindActiveEntry(&key));
     100          45 :     }
     101             : 
     102             :     // Send back discard NH if dependant_rt_ is not set
     103          27 :     if (dependant_rt_.get() == NULL) {
     104           0 :         DiscardNH key;
     105           0 :         return static_cast<NextHop *>
     106           0 :             (agent->nexthop_table()->FindActiveEntry(&key));
     107           0 :     }
     108             : 
     109             :     //Indirect route's path, get direct route's NH
     110          27 :     const NextHop *nh = dependant_rt_.get()->GetActiveNextHop();
     111          27 :     if (nh == NULL) {
     112           0 :         DiscardNH key;
     113           0 :         return static_cast<NextHop *>
     114           0 :             (agent->nexthop_table()->FindActiveEntry(&key));
     115           0 :     }
     116          27 :     return nh;
     117             : }
     118             : 
     119          21 : bool AgentPath::ChangeNH(Agent *agent, NextHop *nh) {
     120             :     // If NH is not found, point route to discard NH
     121          21 :     bool ret = false;
     122          21 :     if (nh == NULL) {
     123           0 :         nh = agent->nexthop_table()->discard_nh();
     124             :     }
     125             : 
     126          21 :     if (nh_ != nh) {
     127          15 :         nh_ = nh;
     128          15 :         if (nh && nh->GetType() == NextHop::TUNNEL) {
     129           0 :             TunnelNH *tunnel_nh = static_cast<TunnelNH *>(nh);
     130           0 :             tunnel_dest_ = *tunnel_nh->GetDip();
     131             :         }
     132          15 :         ret = true;
     133             :     }
     134             : 
     135          21 :     if (peer_ && (peer_->GetType() == Peer::ECMP_PEER) &&
     136           0 :         (label_ != MplsTable::kInvalidLabel)) {
     137           0 :         if (RebakeLabel(agent->mpls_table(), label_, nh))
     138           0 :             ret = true;
     139             :     }
     140             : 
     141          21 :     if (PostChangeNH(agent, nh)) {
     142           0 :         ret = true;
     143             :     }
     144          21 :     return ret;
     145             : }
     146             : 
     147          21 : bool AgentPath::PostChangeNH(Agent *agent, NextHop *nh) {
     148          21 :     return false;
     149             : }
     150             : 
     151           0 : bool AgentPath::RebakeAllTunnelNHinCompositeNH(const AgentRoute *sync_route) {
     152           0 :     if (nh_->GetType() != NextHop::COMPOSITE){
     153           0 :         return false;
     154             :     }
     155             : 
     156             :     Agent *agent =
     157           0 :         static_cast<AgentRouteTable *>(sync_route->get_table())->agent();
     158           0 :     CompositeNH *cnh = static_cast<CompositeNH *>(nh_.get());
     159             : 
     160             :     //Compute new tunnel type
     161             :     TunnelType::Type new_tunnel_type;
     162             :     //Only MPLS types are supported for multicast
     163           0 :     if ((sync_route->is_multicast()) && (peer_->GetType() ==
     164             :                                          Peer::MULTICAST_FABRIC_TREE_BUILDER)) {
     165           0 :         new_tunnel_type = TunnelType::ComputeType(TunnelType::MplsType());
     166           0 :         if (new_tunnel_type == TunnelType::VXLAN) {
     167           0 :             new_tunnel_type = TunnelType::MPLS_GRE;
     168             :         }
     169             :     } else {
     170           0 :         new_tunnel_type = TunnelType::ComputeType(tunnel_bmap_);
     171             :     }
     172             : 
     173           0 :     CompositeNH *new_composite_nh = NULL;
     174           0 :     new_composite_nh = cnh->ChangeTunnelType(agent, new_tunnel_type);
     175           0 :     if (ChangeNH(agent, new_composite_nh)) {
     176             :         //Update composite NH key list to reflect new type
     177           0 :         if (composite_nh_key_)
     178           0 :             composite_nh_key_->ChangeTunnelType(new_tunnel_type);
     179           0 :         return true;
     180             :     }
     181           0 :     return false;
     182             : }
     183             : 
     184          46 : bool AgentPath::UpdateNHPolicy(Agent *agent) {
     185          46 :     bool ret = false;
     186          46 :     if (nh_.get() == NULL || nh_->GetType() != NextHop::INTERFACE) {
     187          32 :         return ret;
     188             :     }
     189             : 
     190          14 :     const InterfaceNH *intf_nh = static_cast<const InterfaceNH *>(nh_.get());
     191          14 :     if (intf_nh->GetInterface()->type() != Interface::VM_INTERFACE) {
     192           0 :         return ret;
     193             :     }
     194             : 
     195             :     const VmInterface *vm_port =
     196          14 :         static_cast<const VmInterface *>(intf_nh->GetInterface());
     197             : 
     198          14 :     bool policy = vm_port->policy_enabled();
     199          14 :     if (force_policy_) {
     200           0 :         policy = true;
     201             :     }
     202             : 
     203          14 :     NextHop *nh = NULL;
     204          14 :     if (intf_nh->PolicyEnabled() != policy) {
     205             :         //Make path point to policy enabled interface
     206             :         InterfaceNHKey key(new VmInterfaceKey(AgentKey::ADD_DEL_CHANGE,
     207           0 :                                               vm_port->GetUuid(),
     208           0 :                                               vm_port->name()),
     209           0 :                            policy, intf_nh->GetFlags(),
     210           0 :                            intf_nh->GetDMac());
     211           0 :         nh = static_cast<NextHop *>
     212           0 :             (agent->nexthop_table()->FindActiveEntry(&key));
     213             :         // If NH is not found, point route to discard NH
     214           0 :         if (nh == NULL) {
     215           0 :             LOG(DEBUG, "Interface NH for <"
     216             :                 << boost::lexical_cast<std::string>(vm_port->GetUuid())
     217             :                 << " : policy = " << policy);
     218           0 :             nh = agent->nexthop_table()->discard_nh();
     219             :         }
     220           0 :         if (ChangeNH(agent, nh) == true) {
     221           0 :             ret = true;
     222             :         }
     223           0 :     }
     224             : 
     225          14 :     return ret;
     226             : }
     227             : 
     228          46 : bool AgentPath::UpdateTunnelType(Agent *agent, const AgentRoute *sync_route) {
     229             :     //Return if there is no change in tunnel type for non Composite NH.
     230             :     //For composite NH component needs to be traversed.
     231             :     // if tunnel type is MPLS over MPLS, transport tunnel
     232             :     // type might be changed ( mpls over gre or mpls over udp)
     233             :     // so check nh transport tunnel type and trigger update if there
     234             :     // is any change
     235         138 :     if ((tunnel_type_ != TunnelType::MPLS_OVER_MPLS) &&
     236         125 :             (tunnel_type_ == TunnelType::ComputeType(tunnel_bmap_)) &&
     237          79 :         (nh_.get() && nh_.get()->GetType() != NextHop::COMPOSITE)) {
     238          35 :         return false;
     239             :     }
     240             : 
     241          11 :     tunnel_type_ = TunnelType::ComputeType(tunnel_bmap_);
     242          11 :     if (tunnel_type_ == TunnelType::VXLAN &&
     243           0 :         vxlan_id_ == VxLanTable::kInvalidvxlan_id) {
     244           0 :         tunnel_type_ = TunnelType::ComputeType(TunnelType::MplsType());
     245             :     }
     246          11 :     DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
     247          11 :     const TunnelNH *tunnel_nh = static_cast<const TunnelNH*>(nh_.get());
     248          11 :     if (nh_.get() && nh_->GetType() == NextHop::TUNNEL) {
     249           0 :         if (tunnel_nh->GetTunnelType().GetType() == TunnelType::MPLS_OVER_MPLS) {
     250             :             const LabelledTunnelNH *label_tunnel_nh =
     251           0 :                     static_cast<const LabelledTunnelNH*>(nh_.get());
     252             :             // check if transport tunnel type is changed
     253           0 :             if (label_tunnel_nh->GetTransportTunnelType() ==
     254           0 :                     TunnelType::ComputeType(TunnelType::MplsType())) {
     255           0 :                 return false;
     256             :             }
     257             :             LabelledTunnelNHKey *tnh_key =
     258           0 :                 new LabelledTunnelNHKey(agent->fabric_vrf_name(),
     259           0 :                         *(label_tunnel_nh->GetSip()),
     260           0 :                         *(label_tunnel_nh->GetDip()),
     261             :                         false, tunnel_type_,
     262           0 :                         label_tunnel_nh->rewrite_dmac(),
     263           0 :                         label_tunnel_nh->GetTransportLabel());
     264           0 :             nh_req.key.reset(tnh_key);
     265           0 :             nh_req.data.reset(new TunnelNHData());
     266           0 :             agent->nexthop_table()->Process(nh_req);
     267             : 
     268             :             LabelledTunnelNHKey nh_key(agent->fabric_vrf_name(),
     269           0 :                         *(label_tunnel_nh->GetSip()),
     270           0 :                         tunnel_dest_, false, tunnel_type_,
     271             :                         label_tunnel_nh->rewrite_dmac(),
     272           0 :                         label_tunnel_nh->GetTransportLabel());
     273           0 :             NextHop *nh = static_cast<NextHop *>
     274           0 :                 (agent->nexthop_table()->FindActiveEntry(&nh_key));
     275           0 :             ChangeNH(agent, nh);
     276           0 :         } else {
     277             : 
     278             :             TunnelNHKey *tnh_key =
     279           0 :                 new TunnelNHKey(agent->fabric_vrf_name(), *(tunnel_nh->GetSip()),
     280           0 :                                 tunnel_dest_, false, tunnel_type_);
     281           0 :             nh_req.key.reset(tnh_key);
     282           0 :             nh_req.data.reset(new TunnelNHData());
     283           0 :             agent->nexthop_table()->Process(nh_req);
     284             : 
     285           0 :             TunnelNHKey nh_key(agent->fabric_vrf_name(), *(tunnel_nh->GetSip()),
     286           0 :                             tunnel_dest_, false, tunnel_type_);
     287           0 :             NextHop *nh = static_cast<NextHop *>
     288           0 :                 (agent->nexthop_table()->FindActiveEntry(&nh_key));
     289           0 :             ChangeNH(agent, nh);
     290           0 :         }
     291             :     }
     292             : 
     293          11 :     if (nh_.get() && nh_->GetType() == NextHop::COMPOSITE) {
     294           0 :         RebakeAllTunnelNHinCompositeNH(sync_route);
     295             :     }
     296          11 :     return true;
     297          11 : }
     298             : 
     299           0 : void AgentPath::ImportPrevActiveNH(Agent *agent, NextHop *nh)
     300             : {
     301           0 :     if (nh_ == nh) {
     302           0 :         return;
     303             :     }
     304             :     // change NH ,
     305             :     // assumptions here is that composite nh grid order would be different
     306             :     // but elements would be same , so importing previous active nh
     307             :     // would make sure the holes are already set in proper order
     308             :     // ex: previous nh order A,B, C, new path nh order would be BCA
     309             :     // ex2: previous nh order _,B,C, new path nh order is just B,C
     310           0 :     ChangeNH(agent, nh);
     311             :     // will there be a race condition while removing the active path,
     312             :     // adding new component nh? 
     313             :     // this can be handled by calling reorder composite nh method
     314           0 :     if (composite_nh_key_ == NULL) { 
     315           0 :         return;
     316             :     }
     317             :     boost::scoped_ptr<CompositeNHKey> composite_nh_key(
     318           0 :                                     composite_nh_key_->Clone());
     319           0 :     bool comp_nh_policy = false;
     320             :     //TODO: optimize here , compare compositenh_key from path and nh?
     321           0 :     ReorderCompositeNH(agent, composite_nh_key.get(), comp_nh_policy, NULL);
     322           0 :     composite_nh_key->SetPolicy(comp_nh_policy);
     323           0 :     ChangeCompositeNH(agent, composite_nh_key.get());
     324             : 
     325           0 : }
     326             : 
     327          46 : bool AgentPath::ResolveGwNextHops(Agent *agent, const AgentRoute *sync_route) {
     328             : 
     329          46 :     if (tunnel_type_ != TunnelType::MPLS_OVER_MPLS) {
     330          46 :         return false;
     331             :     }
     332           0 :     if (ecmp_member_list_.size() == 0) {
     333           0 :         return false;
     334             :     }
     335           0 :     NextHop *nh = NULL;
     336           0 :     InetUnicastAgentRouteTable *table = NULL;
     337             :     table = static_cast<InetUnicastAgentRouteTable *>
     338           0 :         (agent->fabric_inet4_mpls_table());
     339           0 :     assert(table != NULL);
     340             :     //if ecmp member list size is one then it is non ecmp route sync
     341           0 :     if (ecmp_member_list_.size() == 1) {
     342           0 :         AgentPathEcmpComponentPtr member = ecmp_member_list_[0];
     343           0 :         InetUnicastRouteEntry *uc_rt = table->FindRoute(member->GetGwIpAddr());
     344             :         const NextHop *anh;
     345           0 :         if (uc_rt == NULL || uc_rt->prefix_length() == 0 || (anh = uc_rt->GetActiveNextHop()) == NULL) {
     346           0 :             set_unresolved(true);
     347           0 :             member->UpdateDependentRoute(NULL);
     348           0 :             member->SetUnresolved(true);
     349             :         } else {
     350           0 :             set_unresolved(false);
     351           0 :             table->RemoveUnresolvedRoute(GetParentRoute());
     352             :             DBEntryBase::KeyPtr key =
     353           0 :                 anh->GetDBRequestKey();
     354             :             const NextHopKey *nh_key =
     355           0 :                 static_cast<const NextHopKey*>(key.get());
     356           0 :             nh = static_cast<NextHop *>(agent->nexthop_table()->
     357           0 :                                 FindActiveEntry(nh_key));
     358           0 :             assert(nh !=NULL);
     359             :             //Reset to new gateway route, no nexthop for indirect route
     360           0 :             member->UpdateDependentRoute(uc_rt);
     361           0 :             member->SetUnresolved(false);
     362           0 :             set_nexthop(NULL);
     363           0 :         }
     364           0 :         if (nh != NULL) {
     365           0 :             ChangeNH(agent, nh);
     366             :         }
     367           0 :     } else {
     368             :         // this flag is set if atleast one member is unresolved
     369           0 :         bool path_unresolved = false;
     370             :         // if this flag is false , then
     371             :         // composite NH is created with one compoenent NH as discard
     372             :         // and avoid reording teh existing composite NH
     373             :         // this flag is set to true if atleast one member is resolved
     374           0 :         bool is_ecmp_member_resolved = false;
     375           0 :         ComponentNHKeyList comp_nh_list;
     376           0 :         bool comp_nh_policy = false;
     377             :         AgentPathEcmpComponentPtrList::const_iterator ecmp_member_it =
     378           0 :                     ecmp_member_list_.begin();
     379           0 :         while (ecmp_member_it != ecmp_member_list_.end()) {
     380             :             InetUnicastRouteEntry *uc_rt =
     381           0 :                 table->FindRoute((*ecmp_member_it)->GetGwIpAddr());
     382             :             const NextHop *anh;
     383           0 :             if (uc_rt == NULL || uc_rt->prefix_length() == 0 || (anh = uc_rt->GetActiveNextHop()) == NULL) {
     384           0 :                 (*ecmp_member_it)->UpdateDependentRoute(NULL);
     385           0 :                 (*ecmp_member_it)->SetUnresolved(true);
     386           0 :                 if (!path_unresolved) {
     387           0 :                     path_unresolved  = true;
     388             :                     DBEntryBase::KeyPtr key =
     389           0 :                         agent->nexthop_table()->discard_nh()->GetDBRequestKey();
     390             :                     NextHopKey *nh_key =
     391           0 :                         static_cast<NextHopKey *>(key.release());
     392           0 :                     std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
     393             :                     ComponentNHKeyPtr component_nh_key(new ComponentNHKey(
     394           0 :                                     (*ecmp_member_it)->GetLabel(),
     395           0 :                                     std::move(nh_key_ptr)));
     396           0 :                     comp_nh_list.push_back(component_nh_key);
     397           0 :                 }
     398             :             } else {
     399           0 :                 is_ecmp_member_resolved = true;
     400             :                 DBEntryBase::KeyPtr key =
     401           0 :                     anh->GetDBRequestKey();
     402           0 :                 NextHopKey *nh_key = static_cast<NextHopKey *>(key.release());
     403           0 :                 if (nh_key->GetType() != NextHop::COMPOSITE) {
     404             :                     //By default all component members of composite NH
     405             :                     //will be policy disabled, except for component NH
     406             :                     //of type composite
     407           0 :                     nh_key->SetPolicy(false);
     408             :                 }
     409           0 :                 std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
     410             :                 ComponentNHKeyPtr component_nh_key(new
     411           0 :                         ComponentNHKey((*ecmp_member_it)->GetLabel(),
     412           0 :                                                    std::move(nh_key_ptr)));
     413           0 :                 comp_nh_list.push_back(component_nh_key);
     414             :                 //Reset to new gateway route, no nexthop for indirect route
     415           0 :                 (*ecmp_member_it)->UpdateDependentRoute(uc_rt);
     416           0 :                 (*ecmp_member_it)->SetUnresolved(false);
     417           0 :             }
     418           0 :             ecmp_member_it++;
     419             :         }
     420           0 :         DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
     421           0 :         nh_req.key.reset(new CompositeNHKey(Composite::ECMP, comp_nh_policy,
     422           0 :                                     comp_nh_list, vrf_name_));
     423           0 :         nh_req.data.reset(new CompositeNHData());
     424             :         CompositeNHKey *comp_key =
     425           0 :             static_cast<CompositeNHKey *>(nh_req.key.get());
     426           0 :         bool new_comp_nh_policy = false;
     427           0 :         if ((is_ecmp_member_resolved == false) ||
     428           0 :                 ReorderCompositeNH(agent, comp_key, new_comp_nh_policy,
     429           0 :                                sync_route->FindLocalVmPortPath())) {
     430           0 :             comp_key->SetPolicy(new_comp_nh_policy);
     431           0 :             ChangeCompositeNH(agent, comp_key);
     432             :         }
     433             : 
     434           0 :         set_unresolved(path_unresolved);
     435           0 :     }
     436             : 
     437             : 
     438           0 :     return true;
     439             : }
     440          46 : bool AgentPath::Sync(AgentRoute *sync_route) {
     441          46 :     bool ret = false;
     442          46 :     bool unresolved = false;
     443             : 
     444             :     Agent *agent = static_cast<AgentRouteTable *>
     445          46 :         (sync_route->get_table())->agent();
     446             : 
     447             :     // Check if there is change in policy on the interface
     448             :     // If yes update the path to point to policy enabled NH
     449          46 :     if (UpdateNHPolicy(agent)) {
     450           0 :         ret = true;
     451             :     }
     452          46 :     if (ResolveGwNextHops(agent, sync_route)) {
     453           0 :         return true;
     454             :     }
     455             :     //Handle tunnel type change
     456          46 :     if (UpdateTunnelType(agent, sync_route)) {
     457          11 :         ret = true;
     458             :     }
     459             : 
     460             :     //Check if there was a change in local ecmp composite nexthop
     461          82 :     if (nh_ && nh_->GetType() == NextHop::COMPOSITE &&
     462          82 :         composite_nh_key_.get() != NULL && (copy_local_path_ ||
     463           0 :         local_ecmp_mpls_label_.get() != NULL)) {
     464           0 :         boost::scoped_ptr<CompositeNHKey> composite_nh_key(composite_nh_key_->Clone());
     465           0 :         bool comp_nh_policy = false;
     466           0 :         if (ReorderCompositeNH(agent, composite_nh_key.get(), comp_nh_policy,
     467           0 :                                sync_route->FindLocalVmPortPath())) {
     468           0 :             composite_nh_key->SetPolicy(comp_nh_policy);
     469           0 :             if (ChangeCompositeNH(agent, composite_nh_key.get())) {
     470           0 :                 ret = true;
     471             :             }
     472             :         }
     473           0 :     }
     474             : 
     475          46 :     if (nh_ && nh_->GetType() == NextHop::ARP) {
     476           2 :         if (CopyArpData()) {
     477           0 :             ret = true;
     478             :         }
     479             :     }
     480             : 
     481          46 :     if (vrf_name_ == Agent::NullString()) {
     482          36 :         return ret;
     483             :     }
     484             : 
     485             :     // check dependant route change
     486             :     // this is needed only for inet routes
     487          10 :     InetUnicastAgentRouteTable *table = NULL;
     488          10 :     table = dynamic_cast<InetUnicastAgentRouteTable *>
     489          10 :                                 (sync_route->get_table());
     490          10 :     if (table == NULL) {
     491           0 :         return ret;
     492             :     }
     493             : 
     494          10 :     InetUnicastRouteEntry *rt = NULL;
     495             : 
     496          10 :     rt = table->FindRoute(gw_ip_);
     497          10 :     if (rt == sync_route) {
     498           3 :         rt = NULL;
     499             :     }
     500             :     const NextHop *anh;
     501          10 :     if (rt == NULL || rt->prefix_length() == 0) {
     502           3 :        if (agent->params()->subnet_hosts_resolvable() == false &&
     503           0 :             agent->fabric_vrf_name() == vrf_name_) {
     504           0 :             unresolved = false;
     505           0 :             assert(gw_ip_.is_v4());
     506           0 :             table->AddArpReq(vrf_name_, gw_ip_.to_v4(), vrf_name_,
     507             :                              agent->vhost_interface(), false,
     508           0 :                              dest_vn_list_, sg_list_, tag_list_);
     509             :         } else {
     510           3 :             unresolved = true;
     511             :         }
     512           7 :     } else if ((anh = rt->GetActiveNextHop()) == NULL) {
     513           0 :        if (agent->params()->subnet_hosts_resolvable() == false &&
     514           0 :             agent->fabric_vrf_name() == vrf_name_) {
     515           0 :             unresolved = false;
     516           0 :             assert(gw_ip_.is_v4());
     517           0 :             table->AddArpReq(vrf_name_, gw_ip_.to_v4(), vrf_name_,
     518             :                              agent->vhost_interface(), false,
     519           0 :                              dest_vn_list_, sg_list_, tag_list_);
     520             :         } else {
     521           0 :             unresolved = true;
     522             :         }
     523           7 :     } else if (anh->GetType() == NextHop::RESOLVE) {
     524           2 :         const ResolveNH *nh =
     525             :             static_cast<const ResolveNH *>(anh);
     526           2 :         std::string nexthop_vrf = nh->get_interface()->vrf()->GetName();
     527           2 :         if (nh->get_interface()->vrf()->forwarding_vrf()) {
     528           2 :             nexthop_vrf = nh->get_interface()->vrf()->forwarding_vrf()->GetName();
     529             :         }
     530             : 
     531           2 :         assert(gw_ip_.is_v4());
     532           2 :         table->AddArpReq(vrf_name_, gw_ip_.to_v4(), nexthop_vrf,
     533           2 :                          nh->get_interface(), nh->PolicyEnabled(), dest_vn_list_,
     534           2 :                          sg_list_, tag_list_);
     535           2 :         unresolved = true;
     536           2 :     } else {
     537           5 :         unresolved = false;
     538             :     }
     539             : 
     540          10 :     if (unresolved_ != unresolved) {
     541           1 :         unresolved_ = unresolved;
     542           1 :         ret = true;
     543             :     }
     544             : 
     545             :     // Reset to new gateway route, no nexthop for indirect route
     546          10 :     if (dependant_rt_.get() != rt) {
     547           3 :         dependant_rt_.reset(rt);
     548           3 :         ret = true;
     549           3 :         if (rt) {
     550             :             TunnelType::TypeBmap dep_bmap =
     551           2 :                 dependant_rt_->GetActivePath()->tunnel_bmap();
     552           2 :             if (tunnel_bmap_ & 1 << TunnelType::NATIVE) {
     553           2 :                 dep_bmap |= (1 << TunnelType::NATIVE);
     554             :             }
     555           2 :             set_tunnel_bmap(dep_bmap);
     556             :         }
     557             :     }
     558          10 :     return ret;
     559             : }
     560             : 
     561           5 : bool AgentPath::IsLess(const AgentPath &r_path) const {
     562           5 :     if (peer()->GetType() == r_path.peer()->GetType()) {
     563           0 :         if (path_preference() != r_path.path_preference()) {
     564             :             //If right path has lesser preference, then
     565             :             //it should be after the current entry
     566             :             //Hence the reverse check
     567           0 :             return (r_path.path_preference() < path_preference());
     568             :         }
     569             :     }
     570             : 
     571           5 :     return peer()->IsLess(r_path.peer());
     572             : }
     573             : 
     574         946 : const AgentPath *AgentPath::UsablePath() const {
     575         946 :     return this;
     576             : }
     577             : 
     578           3 : void AgentPath::set_nexthop(NextHop *nh) {
     579           3 :     nh_ = nh;
     580           3 : }
     581             : 
     582           4 : bool AgentPath::CopyArpData() {
     583           4 :     bool ret = false;
     584           4 :     if (nh_ && nh_->GetType() == NextHop::ARP) {
     585           4 :         const ArpNH *arp_nh = static_cast<const ArpNH *>(nh_.get());
     586           4 :         if (arp_mac() != arp_nh->GetMac()) {
     587           0 :             set_arp_mac(arp_nh->GetMac());
     588           0 :             ret = true;
     589             :         }
     590             : 
     591           4 :         if (arp_interface() != arp_nh->GetInterface()) {
     592           1 :             set_arp_interface(arp_nh->GetInterface());
     593           1 :             ret = true;
     594             :         }
     595             : 
     596           4 :         if (arp_valid() != arp_nh->IsValid()) {
     597           0 :             set_arp_valid(arp_nh->IsValid());
     598           0 :             ret = true;
     599             :         }
     600             :     }
     601           4 :     return ret;
     602             : }
     603             : 
     604           0 : bool AgentPath::CopyNdpData() {
     605           0 :     bool ret = false;
     606           0 :     if (nh_ && nh_->GetType() == NextHop::NDP) {
     607           0 :         const NdpNH *ndp_nh = static_cast<const NdpNH *>(nh_.get());
     608           0 :         if (arp_mac() != ndp_nh->GetMac()) {
     609           0 :             set_arp_mac(ndp_nh->GetMac());
     610           0 :             ret = true;
     611             :         }
     612             : 
     613           0 :         if (arp_interface() != ndp_nh->GetInterface()) {
     614           0 :             set_arp_interface(ndp_nh->GetInterface());
     615           0 :             ret = true;
     616             :         }
     617             : 
     618           0 :         if (arp_valid() != ndp_nh->IsValid()) {
     619           0 :             set_arp_valid(ndp_nh->IsValid());
     620           0 :             ret = true;
     621             :         }
     622             :     }
     623           0 :     return ret;
     624             : }
     625             : 
     626           1 : EvpnDerivedPath::EvpnDerivedPath(const EvpnPeer *evpn_peer,
     627             :                    const IpAddress &ip_addr,
     628             :                    uint32_t ethernet_tag,
     629           1 :                    const std::string &parent) :
     630             :     AgentPath(evpn_peer, NULL),
     631           2 :     ip_addr_(ip_addr), ethernet_tag_(ethernet_tag),
     632           1 :     parent_(parent){
     633           1 : }
     634             : 
     635           1 : bool EvpnDerivedPath::IsLess(const AgentPath &r_path) const {
     636           1 :     const EvpnDerivedPath *r_evpn_path =
     637           1 :         dynamic_cast<const EvpnDerivedPath *>(&r_path);
     638           1 :     if (r_evpn_path != NULL) {
     639           0 :         if (r_evpn_path->ip_addr() != ip_addr_) {
     640           0 :             return (ip_addr_ < r_evpn_path->ip_addr());
     641             :         }
     642             :     }
     643             : 
     644           1 :     return peer()->IsLess(r_path.peer());
     645             : }
     646             : 
     647          17 : const NextHop *EvpnDerivedPath::ComputeNextHop(Agent *agent) const {
     648          17 :     return nexthop();
     649             : }
     650             : 
     651           4 : EvpnDerivedPathData::EvpnDerivedPathData(const EvpnRouteEntry *evpn_rt) :
     652             :     AgentRouteData(AgentRouteData::ADD_DEL_CHANGE,
     653           4 :                    evpn_rt->is_multicast(), 0),
     654           4 :     ethernet_tag_(evpn_rt->ethernet_tag()), ip_addr_(evpn_rt->prefix_address()),
     655           8 :     reference_path_(evpn_rt->GetActivePath()), ecmp_suppressed_(false) {
     656             :     // For debuging add peer of active path in parent as well
     657           4 :     std::stringstream s;
     658           4 :     s << evpn_rt->ToString();
     659           4 :     s << " ";
     660           4 :     if (reference_path_ && reference_path_->peer())
     661           3 :         s << reference_path_->peer()->GetName();
     662           4 :     parent_ = s.str();
     663           4 : }
     664             : 
     665           1 : AgentPath *EvpnDerivedPathData::CreateAgentPath(const Peer *peer,
     666             :                                          AgentRoute *rt) const {
     667           1 :     const EvpnPeer *evpn_peer = dynamic_cast<const EvpnPeer *>(peer);
     668           1 :     assert(evpn_peer != NULL);
     669           1 :     return (new EvpnDerivedPath(evpn_peer, ip_addr_, ethernet_tag_,
     670           1 :                                 parent_));
     671             : }
     672             : 
     673           3 : bool EvpnDerivedPathData::AddChangePathExtended(Agent *agent, AgentPath *path,
     674             :                                                 const AgentRoute *rt) {
     675           3 :     bool ret = false;
     676           3 :     EvpnDerivedPath *evpn_path = dynamic_cast<EvpnDerivedPath *>(path);
     677           3 :     assert(evpn_path != NULL);
     678             : 
     679           3 :     evpn_path->set_tunnel_dest(reference_path_->tunnel_dest());
     680           3 :     uint32_t label = reference_path_->label();
     681           3 :     if (evpn_path->label() != label) {
     682           1 :         evpn_path->set_label(label);
     683           1 :         ret = true;
     684             :     }
     685             : 
     686           3 :     uint32_t vxlan_id = reference_path_->vxlan_id();
     687           3 :     if (evpn_path->vxlan_id() != vxlan_id) {
     688           0 :         evpn_path->set_vxlan_id(vxlan_id);
     689           0 :         ret = true;
     690             :     }
     691             : 
     692           3 :     uint32_t tunnel_bmap = reference_path_->tunnel_bmap();
     693           3 :     if (evpn_path->tunnel_bmap() != tunnel_bmap) {
     694           0 :         evpn_path->set_tunnel_bmap(tunnel_bmap);
     695           0 :         ret = true;
     696             :     }
     697             : 
     698           3 :     TunnelType::Type tunnel_type = reference_path_->tunnel_type();
     699           3 :     if (evpn_path->tunnel_type() != tunnel_type) {
     700           0 :         evpn_path->set_tunnel_type(tunnel_type);
     701           0 :         ret = true;
     702             :     }
     703             : 
     704           3 :     PathPreference pref = reference_path_->path_preference();
     705           3 :     if (evpn_path->path_preference() != pref) {
     706             :         // Take path preference from parent path
     707           0 :         evpn_path->set_path_preference(pref);
     708           0 :         ret = true;
     709             :     }
     710             : 
     711           6 :     if (evpn_path->nexthop() !=
     712           3 :         reference_path_->nexthop()) {
     713           1 :         evpn_path->set_nexthop(reference_path_->nexthop());
     714           1 :         ret = true;
     715             :     }
     716             : 
     717           3 :     const SecurityGroupList &sg_list = reference_path_->sg_list();
     718           3 :     if (evpn_path->sg_list() != sg_list) {
     719           0 :         evpn_path->set_sg_list(sg_list);
     720           0 :         ret = true;
     721             :     }
     722             : 
     723           3 :     const TagList &tag_list = reference_path_->tag_list();
     724           3 :     if (evpn_path->tag_list() != tag_list) {
     725           0 :         evpn_path->set_tag_list(tag_list);
     726           0 :         ret = true;
     727             :     }
     728             : 
     729           3 :     const VnListType &dest_vn_list = reference_path_->dest_vn_list();
     730           3 :     if (evpn_path->dest_vn_list() != dest_vn_list) {
     731           1 :         evpn_path->set_dest_vn_list(dest_vn_list);
     732           1 :         ret = true;
     733             :     }
     734             : 
     735           3 :     if (evpn_path->ecmp_suppressed() != ecmp_suppressed_) {
     736           0 :         evpn_path->set_ecmp_suppressed(ecmp_suppressed_);
     737           0 :         ret = true;
     738             :     }
     739             : 
     740           3 :     if (evpn_path->etree_leaf() != reference_path_->etree_leaf()) {
     741           0 :         evpn_path->set_etree_leaf(reference_path_->etree_leaf());
     742           0 :         ret = true;
     743             :     }
     744             : 
     745           3 :     if (evpn_path->ResyncControlWord(rt)) {
     746           0 :         ret = true;
     747             :     }
     748             : 
     749           3 :     path->set_unresolved(false);
     750             : 
     751           3 :     return ret;
     752           3 : }
     753             : 
     754           1 : bool EvpnDerivedPathData::CanDeletePath(Agent *agent, AgentPath *path,
     755             :                                         const AgentRoute *rt) const {
     756             :     const EvpnDerivedPath *evpn_path =
     757           1 :         dynamic_cast<const EvpnDerivedPath *>(path);
     758           1 :     assert(evpn_path != NULL);
     759             : 
     760           1 :     if (evpn_path->ethernet_tag() != ethernet_tag())
     761           0 :         return false;
     762             : 
     763           1 :     return (evpn_path->ip_addr() == ip_addr());
     764             : }
     765             : 
     766           0 : bool HostRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
     767             :                                       const AgentRoute *rt) {
     768           0 :     bool ret = false;
     769           0 :     NextHop *nh = NULL;
     770             : 
     771           0 :     InterfaceNHKey key(intf_.Clone(), policy_, InterfaceNHFlags::INET4,
     772           0 :                        agent->pkt_interface_mac());
     773           0 :     nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
     774           0 :     VnListType dest_vn_list;
     775           0 :     dest_vn_list.insert(dest_vn_name_);
     776           0 :     if (path->dest_vn_list() != dest_vn_list) {
     777           0 :         path->set_dest_vn_list(dest_vn_list);
     778           0 :         ret = true;
     779             :     }
     780             : 
     781           0 :     path->set_unresolved(false);
     782           0 :     if (path->ChangeNH(agent, nh) == true)
     783           0 :         ret = true;
     784             : 
     785           0 :     return ret;
     786           0 : }
     787             : 
     788           0 : bool HostRoute::UpdateRoute(AgentRoute *rt) {
     789           0 :     InetUnicastRouteEntry *uc_rt =
     790             :         static_cast<InetUnicastRouteEntry *>(rt);
     791           0 :     AgentRouteTable *table = static_cast<AgentRouteTable *>(rt->get_table());
     792           0 :     if ((table->GetTableType() != Agent::INET4_UNICAST) &&
     793           0 :         (table->GetTableType() != Agent::INET6_UNICAST))
     794           0 :         return false;
     795             : 
     796           0 :     return uc_rt->UpdateRouteFlags(false, false, true);
     797             : }
     798             : 
     799           4 : bool L2ReceiveRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
     800             :                                            const AgentRoute *rt) {
     801           4 :     bool ret = false;
     802             : 
     803           4 :     path->set_unresolved(false);
     804             : 
     805           4 :     VnListType dest_vn_list;
     806           4 :     dest_vn_list.insert(dest_vn_name_);
     807           4 :     if (path->dest_vn_list() != dest_vn_list) {
     808           4 :         path->set_dest_vn_list(dest_vn_list);
     809           4 :         ret = true;
     810             :     }
     811             : 
     812           4 :     if (path->label() != mpls_label_) {
     813           4 :         path->set_label(mpls_label_);
     814           4 :         ret = true;
     815             :     }
     816             : 
     817           4 :     if (path->vxlan_id() != vxlan_id_) {
     818           0 :         path->set_vxlan_id(vxlan_id_);
     819           0 :         ret = true;
     820             :     }
     821             : 
     822           4 :     if (path->path_preference().ConfigChanged(path_preference_)) {
     823           0 :         path->set_path_preference(path_preference_);
     824           0 :         ret = true;
     825             :     }
     826             : 
     827           4 :     if (path->peer() && path->peer()->GetType() == Peer::BGP_PEER) {
     828             :         //Copy entire path preference for BGP peer path,
     829             :         //since allowed-address pair config doesn't modify
     830             :         //preference on BGP path
     831           0 :         if (path->path_preference() != path_preference_) {
     832           0 :             path->set_path_preference(path_preference_);
     833           0 :             ret = true;
     834             :         }
     835             :     }
     836             : 
     837           4 :     if (path->ChangeNH(agent, agent->nexthop_table()->l2_receive_nh()) == true)
     838           4 :         ret = true;
     839             : 
     840           4 :     return ret;
     841           4 : }
     842             : 
     843           0 : bool InetInterfaceRoute::UpdateRoute(AgentRoute *rt) {
     844           0 :     AgentRouteTable *table = static_cast<AgentRouteTable *>(rt->get_table());
     845           0 :     if ((table->GetTableType() != Agent::INET4_UNICAST) &&
     846           0 :         (table->GetTableType() != Agent::INET6_UNICAST))
     847           0 :         return false;
     848             : 
     849           0 :     InetUnicastRouteEntry *uc_rt = static_cast<InetUnicastRouteEntry *>(rt);
     850             : 
     851           0 :     return uc_rt->UpdateRouteFlags(false, false, true);
     852             : }
     853             : 
     854           0 : bool InetInterfaceRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
     855             :                                                const AgentRoute *rt) {
     856           0 :     bool ret = false;
     857           0 :     NextHop *nh = NULL;
     858             :     InterfaceNHKey key(intf_.Clone(), false, InterfaceNHFlags::INET4,
     859           0 :                        agent->pkt_interface_mac());
     860           0 :     nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
     861           0 :     if (path->dest_vn_list() != dest_vn_list_) {
     862           0 :         path->set_dest_vn_list(dest_vn_list_);
     863           0 :         ret = true;
     864             :     }
     865             : 
     866           0 :     if (path->label() != label_) {
     867           0 :         path->set_label(label_);
     868           0 :         ret = true;
     869             :     }
     870             : 
     871           0 :     path->set_tunnel_bmap(tunnel_bmap_);
     872           0 :     TunnelType::Type tunnel_type = TunnelType::ComputeType(tunnel_bmap_);
     873           0 :     if (tunnel_type != path->tunnel_type()) {
     874           0 :         path->set_tunnel_type(tunnel_type);
     875           0 :         ret = true;
     876             :     }
     877             : 
     878           0 :     path->set_unresolved(false);
     879           0 :     if (path->ChangeNH(agent, nh) == true)
     880           0 :         ret = true;
     881             : 
     882           0 :     return ret;
     883           0 : }
     884             : 
     885           0 : bool DropRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
     886             :                                       const AgentRoute *rt) {
     887           0 :     bool ret = false;
     888             : 
     889           0 :     VnListType dest_vn_list;
     890           0 :     dest_vn_list.insert(vn_);
     891           0 :     if (path->dest_vn_list() != dest_vn_list) {
     892           0 :         path->set_dest_vn_list(dest_vn_list);
     893           0 :         ret = true;
     894             :     }
     895             : 
     896           0 :     NextHop *nh = agent->nexthop_table()->discard_nh();
     897           0 :     path->set_unresolved(false);
     898           0 :     if (path->ChangeNH(agent, nh) == true) {
     899           0 :         ret = true;
     900             :     }
     901             : 
     902           0 :     return ret;
     903           0 : }
     904             : 
     905           7 : bool LocalVmRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
     906             :                                          const AgentRoute *rt) {
     907           7 :     bool ret = false;
     908           7 :     NextHop *nh = NULL;
     909           7 :     SecurityGroupList path_sg_list;
     910           7 :     TagList path_tag_list;
     911           7 :     CommunityList path_communities;
     912             : 
     913             :     //TODO Based on key table type pick up interface
     914           7 :     VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf_.uuid_, intf_.name_);
     915           7 :     VmInterface *vm_port = static_cast<VmInterface *>
     916           7 :         (agent->interface_table()->FindActiveEntry(&intf_key));
     917             : 
     918           7 :     bool policy = false;
     919           7 :     if (vm_port) {
     920             :         // Use policy based NH if policy enabled on interface
     921           7 :         if (vm_port->policy_enabled()) {
     922           0 :             policy = true;
     923           0 :             ret = true;
     924             :         }
     925             :     }
     926             : 
     927           7 :     if (native_encap_) {
     928           6 :         tunnel_bmap_ |= (1 << TunnelType::NATIVE);
     929             :     }
     930             : 
     931           7 :     if (tunnel_bmap_ != path->tunnel_bmap()) {
     932           3 :         path->set_tunnel_bmap(tunnel_bmap_);
     933           3 :         ret = true;
     934             :     }
     935             : 
     936           7 :     TunnelType::Type new_tunnel_type = TunnelType::ComputeType(tunnel_bmap_);
     937           7 :     if (new_tunnel_type == TunnelType::VXLAN &&
     938           0 :         vxlan_id_ == VxLanTable::kInvalidvxlan_id) {
     939           0 :         new_tunnel_type = TunnelType::ComputeType(TunnelType::MplsType());
     940             :     }
     941             : 
     942           7 :     if (path->tunnel_type() != new_tunnel_type) {
     943           0 :         path->set_tunnel_type(new_tunnel_type);
     944           0 :         ret = true;
     945             :     }
     946             : 
     947             :     // If policy force-enabled in request, enable policy
     948           7 :     path->set_force_policy(force_policy_);
     949           7 :     if (force_policy_) {
     950           0 :         policy = true;
     951             :     }
     952             : 
     953           7 :     MacAddress mac = MacAddress::ZeroMac();
     954           7 :     if (vm_port) {
     955           7 :         mac = vm_port->vm_mac();
     956             :         const InetUnicastRouteEntry *ip_rt =
     957           7 :             dynamic_cast<const InetUnicastRouteEntry *>(rt);
     958           7 :         if (ip_rt) {
     959           6 :             mac = vm_port->GetIpMac(ip_rt->prefix_address(), ip_rt->prefix_length());
     960             :         }
     961             :         const EvpnRouteEntry *evpn_rt =
     962           7 :             dynamic_cast<const EvpnRouteEntry *>(rt);
     963           7 :         if (evpn_rt && vm_port->mac_ip_learning_enable())  {
     964           0 :             mac = evpn_rt->mac();
     965             :         }
     966             :     }
     967           7 :     if (vm_port && vm_port->mac_ip_learning_enable()) {
     968           0 :         MplsLabel *mpls = agent->mpls_table()->FindMplsLabel(mpls_label_);
     969           0 :         if (mpls != NULL) {
     970           0 :             const InterfaceNH *label_nh = dynamic_cast<const InterfaceNH *>(mpls->nexthop());
     971           0 :             if (label_nh) {
     972           0 :                 const MacAddress nh_dmac = label_nh->GetDMac();
     973           0 :                 if (mac == vm_port->vm_mac() && nh_dmac != vm_port->vm_mac()) {
     974           0 :                     mac = nh_dmac;
     975             :                 }
     976             :             }
     977             :         }
     978             :     }
     979           7 :     InterfaceNHKey key(intf_.Clone(), policy, flags_, mac);
     980           7 :     nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
     981             : 
     982           7 :     if (path->label() != mpls_label_) {
     983           4 :         path->set_label(mpls_label_);
     984           4 :         ret = true;
     985             :     }
     986             : 
     987           7 :     if (path->vxlan_id() != vxlan_id_) {
     988           0 :         path->set_vxlan_id(vxlan_id_);
     989           0 :         ret = true;
     990             :     }
     991             : 
     992           7 :     if (path->dest_vn_list() != dest_vn_list_) {
     993           4 :         path->set_dest_vn_list(dest_vn_list_);
     994           4 :         ret = true;
     995             :     }
     996             : 
     997           7 :     path_sg_list = path->sg_list();
     998           7 :     if (path_sg_list != sg_list_) {
     999           0 :         path->set_sg_list(sg_list_);
    1000           0 :         ret = true;
    1001             :     }
    1002             : 
    1003           7 :     path_tag_list = path->tag_list();
    1004           7 :     if (path_tag_list != tag_list_) {
    1005           0 :         path->set_tag_list(tag_list_);
    1006           0 :         ret = true;
    1007             :     }
    1008             : 
    1009           7 :     path_communities = path->communities();
    1010           7 :     if (path_communities != communities_) {
    1011           0 :         path->set_communities(communities_);
    1012           0 :         ret = true;
    1013             :     }
    1014             : 
    1015             :     //Priority and sequence no of path are updated from path
    1016             :     //preference state machine
    1017             :     //Path preference value enqueued here would be copied
    1018             :     //only if
    1019             :     //1> ecmp field is set to true, meaning path would be
    1020             :     //   active-active
    1021             :     //2> static preference is set, meaning external entity
    1022             :     //   would specify the preference of this path(ex LBaaS)
    1023             :     //3> Change in priority when static preference is set
    1024          14 :     if (path->path_preference().ConfigChanged(path_preference_) ||
    1025           7 :         path->peer() == agent->fabric_rt_export_peer()) {
    1026           0 :         path->set_path_preference(path_preference_);
    1027           0 :         ret = true;
    1028             :     }
    1029             : 
    1030           7 :     if (path->peer() && path->peer()->GetType() == Peer::BGP_PEER) {
    1031             :         //Copy entire path preference for BGP peer path,
    1032             :         //since allowed-address pair config doesn't modify
    1033             :         //preference on BGP path
    1034           0 :         if (path->path_preference() != path_preference_) {
    1035           0 :             path->set_path_preference(path_preference_);
    1036           0 :             ret = true;
    1037             :         }
    1038             :     }
    1039             : 
    1040             :     // When BGP path was added, the policy flag in BGP path was based on
    1041             :     // interface config at that instance. If the policy flag changes in
    1042             :     // path for "Local Peer", we should change policy flag on BGP peer
    1043             :     // also. Check if policy has changed and enable SYNC of all path in
    1044             :     // this case
    1045             :     // Ideally his is needed only for LocalPath. But, having code for all
    1046             :     // paths does not have any problem
    1047           7 :     bool old_policy = false;
    1048           7 :     bool new_policy = false;
    1049           7 :     if (path->ComputeNextHop(agent) && path->ComputeNextHop(agent)->PolicyEnabled())
    1050           0 :         old_policy = true;
    1051           7 :     if (nh && nh->PolicyEnabled())
    1052           0 :         new_policy = true;
    1053           7 :     if (old_policy != new_policy) {
    1054           0 :         sync_route_ = true;
    1055             :     }
    1056             : 
    1057           7 :     if (path->subnet_service_ip() != subnet_service_ip_) {
    1058           0 :         path->set_subnet_service_ip(subnet_service_ip_);
    1059           0 :         ret = true;
    1060             :     }
    1061             : 
    1062           7 :     path->set_unresolved(false);
    1063           7 :     path->SyncRoute(sync_route_);
    1064             : 
    1065           7 :     if (ecmp_load_balance_ != path->ecmp_load_balance()) {
    1066           0 :         path->set_ecmp_load_balance(ecmp_load_balance_);
    1067           0 :         ret = true;
    1068             :     }
    1069             : 
    1070           7 :     if (path->ChangeNH(agent, nh) == true)
    1071           4 :         ret = true;
    1072             : 
    1073           7 :     if (is_local_ != path->is_local()) {
    1074           0 :         path->set_is_local(is_local_);
    1075           0 :         ret = true;
    1076             :     }
    1077             : 
    1078           7 :     if (is_health_check_service_ != path->is_health_check_service()) {
    1079           0 :         path->set_is_health_check_service(is_health_check_service_);
    1080           0 :         ret = true;
    1081             :     }
    1082             : 
    1083           7 :     if (etree_leaf_ != path->etree_leaf()) {
    1084           0 :         path->set_etree_leaf(etree_leaf_);
    1085           0 :         ret = true;
    1086             :     }
    1087             : 
    1088           7 :     if (native_vrf_id_ != path->native_vrf_id()) {
    1089           4 :         path->set_native_vrf_id(native_vrf_id_);
    1090           4 :         ret = true;
    1091             :     }
    1092           7 :     path->SetDynamicLearntRouteFlag(is_learnt_route_);
    1093             : 
    1094           7 :     return ret;
    1095           7 : }
    1096             : 
    1097           7 : bool LocalVmRoute::UpdateRoute(AgentRoute *rt) {
    1098           7 :     AgentRouteTable *table = static_cast<AgentRouteTable *>(rt->get_table());
    1099           8 :     if ((table->GetTableType() != Agent::INET4_UNICAST) &&
    1100           1 :         (table->GetTableType() != Agent::INET6_UNICAST)) {
    1101           1 :         return false;
    1102             :     }
    1103             : 
    1104             :     /* Route Reflect will not have the field populated and we do not
    1105             :      * want to override the route type for reflected routes */
    1106           6 :     if (intf_route_type().empty()) {
    1107           5 :        return false;
    1108             :     }
    1109             : 
    1110           1 :     if (intf_route_type().compare(rt->intf_route_type()) != 0) {
    1111           0 :         rt->set_intf_route_type(intf_route_type());
    1112           0 :         return true;
    1113             :     }
    1114             : 
    1115           1 :     return false;
    1116             : }
    1117             : 
    1118             : 
    1119           0 : bool PBBRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
    1120             :                                      const AgentRoute *rt) {
    1121           0 :     bool ret = false;
    1122           0 :     NextHop *nh = NULL;
    1123           0 :     SecurityGroupList path_sg_list;
    1124           0 :     TagList path_tag_list;
    1125           0 :     CommunityList path_communities;
    1126             : 
    1127           0 :     VrfEntry *vrf = static_cast<VrfEntry *>
    1128           0 :         (agent->vrf_table()->FindActiveEntry(&vrf_key_));
    1129             : 
    1130           0 :     if (vrf != NULL) {
    1131             :         //Create PBB NH
    1132           0 :         DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1133           0 :         nh_req.key.reset(new PBBNHKey(vrf_key_.name_, dmac_, isid_));
    1134           0 :         nh_req.data.reset(new PBBNHData());
    1135           0 :         agent->nexthop_table()->Process(nh_req);
    1136             : 
    1137           0 :         PBBNHKey pbb_nh_key(vrf_key_.name_, dmac_, isid_);
    1138           0 :         nh = static_cast<NextHop *>(agent->nexthop_table()->
    1139           0 :                                     FindActiveEntry(&pbb_nh_key));
    1140           0 :     }
    1141             : 
    1142           0 :     if (path->dest_vn_list() != dest_vn_list_) {
    1143           0 :         path->set_dest_vn_list(dest_vn_list_);
    1144           0 :         ret = true;
    1145             :     }
    1146             : 
    1147           0 :     path_sg_list = path->sg_list();
    1148           0 :     if (path_sg_list != sg_list_) {
    1149           0 :         path->set_sg_list(sg_list_);
    1150           0 :         ret = true;
    1151             :     }
    1152             : 
    1153           0 :     path_tag_list = path->tag_list();
    1154           0 :     if (path_tag_list != tag_list_) {
    1155           0 :         path->set_tag_list(tag_list_);
    1156           0 :         ret = true;
    1157             :     }
    1158             : 
    1159             :     //Copy over entire path preference structure, whenever there is a
    1160             : 
    1161           0 :     if (path->ChangeNH(agent, nh) == true) {
    1162           0 :         ret = true;
    1163             :     }
    1164             : 
    1165           0 :     path->set_unresolved(false);
    1166           0 :     return ret;
    1167           0 : }
    1168             : 
    1169           0 : bool VlanNhRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
    1170             :                                         const AgentRoute *rt) {
    1171           0 :     bool ret = false;
    1172           0 :     NextHop *nh = NULL;
    1173           0 :     SecurityGroupList path_sg_list;
    1174           0 :     TagList path_tag_list;
    1175             : 
    1176           0 :     assert(intf_.type_ == Interface::VM_INTERFACE);
    1177           0 :     VlanNHKey key(intf_.uuid_, tag_);
    1178             : 
    1179           0 :     nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
    1180           0 :     if (nh) {
    1181           0 :         assert(nh->GetType() == NextHop::VLAN);
    1182             :     }
    1183             : 
    1184           0 :     if (path->label() != label_) {
    1185           0 :         path->set_label(label_);
    1186           0 :         ret = true;
    1187             :     }
    1188             : 
    1189           0 :     if (path->dest_vn_list() != dest_vn_list_) {
    1190           0 :         path->set_dest_vn_list(dest_vn_list_);
    1191           0 :         ret = true;
    1192             :     }
    1193             : 
    1194           0 :     path_sg_list = path->sg_list();
    1195           0 :     if (path_sg_list != sg_list_) {
    1196           0 :         path->set_sg_list(sg_list_);
    1197           0 :         ret = true;
    1198             :     }
    1199             : 
    1200           0 :     path_tag_list = path->tag_list();
    1201           0 :     if (path_tag_list != tag_list_) {
    1202           0 :         path->set_tag_list(tag_list_);
    1203           0 :         ret = true;
    1204             :     }
    1205             : 
    1206             :     //Copy over entire path preference structure, whenever there is a
    1207             : 
    1208             :     //Copy over entire path preference structure, whenever there is a
    1209             :     //transition from active-active to active-backup struture
    1210           0 :     if (path->path_preference().ConfigChanged(path_preference_)) {
    1211           0 :         path->set_path_preference(path_preference_);
    1212           0 :         ret = true;
    1213             :     }
    1214             : 
    1215           0 :     path->set_tunnel_bmap(tunnel_bmap_);
    1216           0 :     TunnelType::Type tunnel_type = TunnelType::ComputeType(tunnel_bmap_);
    1217           0 :     if (tunnel_type != path->tunnel_type()) {
    1218           0 :         path->set_tunnel_type(tunnel_type);
    1219           0 :         ret = true;
    1220             :     }
    1221             : 
    1222           0 :     path->set_unresolved(false);
    1223           0 :     if (path->ChangeNH(agent, nh) == true) {
    1224           0 :         ret = true;
    1225             :     }
    1226             : 
    1227           0 :     return ret;
    1228           0 : }
    1229             : 
    1230           1 : bool ResolveRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
    1231             :                                          const AgentRoute *rt) {
    1232           1 :     bool ret = false;
    1233           1 :     NextHop *nh = NULL;
    1234           1 :     ResolveNHKey key(intf_key_.get(), policy_);
    1235             : 
    1236           1 :     nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
    1237           1 :     path->set_unresolved(false);
    1238             : 
    1239           1 :     VnListType dest_vn_list;
    1240           1 :     dest_vn_list.insert(dest_vn_name_);
    1241           1 :     if (path->dest_vn_list() != dest_vn_list) {
    1242           1 :         path->set_dest_vn_list(dest_vn_list);
    1243           1 :         ret = true;
    1244             :     }
    1245             : 
    1246           1 :     if (path->label() != label_) {
    1247           0 :         path->set_label(label_);
    1248           0 :         ret = true;
    1249             :     }
    1250             : 
    1251           1 :     if (path->sg_list() != path_sg_list_) {
    1252           0 :         path->set_sg_list(path_sg_list_);
    1253           0 :         ret = true;
    1254             :     }
    1255             : 
    1256             :     //By default resolve route on gateway interface
    1257             :     //is supported with MPLSoGRE or MplsoUdp port
    1258           1 :     path->set_tunnel_bmap(TunnelType::MplsType());
    1259             :     TunnelType::Type new_tunnel_type =
    1260           1 :         TunnelType::ComputeType(TunnelType::MplsType());
    1261           1 :     if (path->tunnel_type() != new_tunnel_type) {
    1262           0 :         path->set_tunnel_type(new_tunnel_type);
    1263             :     }
    1264             : 
    1265           1 :     if (path->ChangeNH(agent, nh) == true)
    1266           1 :         ret = true;
    1267             : 
    1268           1 :     return ret;
    1269           1 : }
    1270             : 
    1271           6 : bool ReceiveRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
    1272             :                                          const AgentRoute *rt) {
    1273           6 :     bool ret = false;
    1274           6 :     NextHop *nh = NULL;
    1275             : 
    1276             :     //TODO check if it needs to know table type
    1277           6 :     ReceiveNHKey key(intf_->Clone(), policy_);
    1278           6 :     nh = static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
    1279           6 :     path->set_unresolved(false);
    1280             : 
    1281           6 :     VnListType dest_vn_list;
    1282           6 :     dest_vn_list.insert(vn_);
    1283           6 :     if (path->dest_vn_list() != dest_vn_list) {
    1284           4 :         path->set_dest_vn_list(dest_vn_list);
    1285           4 :         ret = true;
    1286             :     }
    1287             : 
    1288           6 :     if (path->label() != label_) {
    1289           4 :         path->set_label(label_);
    1290           4 :         ret = true;
    1291             :     }
    1292             : 
    1293           6 :     path->set_tunnel_bmap(tunnel_bmap_);
    1294             : 
    1295           6 :     if (path->ChangeNH(agent, nh) == true)
    1296           4 :         ret = true;
    1297             : 
    1298           6 :     return ret;
    1299           6 : }
    1300             : 
    1301           6 : bool ReceiveRoute::UpdateRoute(AgentRoute *rt) {
    1302           6 :     AgentRouteTable *table = static_cast<AgentRouteTable *>(rt->get_table());
    1303           8 :     if ((table->GetTableType() != Agent::INET4_UNICAST) &&
    1304           2 :         (table->GetTableType() != Agent::INET6_UNICAST))
    1305           1 :         return false;
    1306             : 
    1307           5 :     InetUnicastRouteEntry *uc_rt =
    1308             :         static_cast<InetUnicastRouteEntry *>(rt);
    1309             : 
    1310             :     // Receive route can be a /32 route of multicast-subnet route
    1311             :     // proxy_arp_ is set only for host route. So, set ipam_host_route_ if
    1312             :     // proxy_arp_ enabled
    1313           5 :     return uc_rt->UpdateRouteFlags(false, ipam_host_route_, proxy_arp_);
    1314             : }
    1315             : 
    1316           0 : MulticastRoutePath::MulticastRoutePath(const Peer *peer) :
    1317           0 :     AgentPath(peer, NULL), original_nh_(),
    1318           0 :     evpn_label_(MplsTable::kInvalidLabel),
    1319           0 :     fabric_label_(MplsTable::kInvalidLabel) {
    1320           0 : }
    1321             : 
    1322           0 : bool MulticastRoutePath::PostChangeNH(Agent *agent, NextHop *nh) {
    1323           0 :     bool ret = false;
    1324           0 :     if (!peer())
    1325           0 :         return false;
    1326             : 
    1327           0 :     if (peer()->GetType() != Peer::MULTICAST_PEER)
    1328           0 :         return false;
    1329             : 
    1330             :     //Bake for label in path
    1331           0 :     if (RebakeLabel(agent->mpls_table(), label(), nh))
    1332           0 :         ret = true;
    1333             : 
    1334             :     //If path label is not same as evpn label, then rebake evpn label
    1335           0 :     if ((label() != evpn_label_) &&
    1336           0 :         RebakeLabel(agent->mpls_table(), evpn_label_, nh))
    1337           0 :         ret = true;
    1338             : 
    1339             :     //If path label is not same as fmg label, then rebake fmg label
    1340           0 :     if ((label() != fabric_label_) &&
    1341           0 :         RebakeLabel(agent->mpls_table(), fabric_label_, nh))
    1342           0 :         ret = true;
    1343             : 
    1344           0 :     return ret;
    1345             : }
    1346             : 
    1347           0 : NextHop *MulticastRoutePath::UpdateNH(Agent *agent,
    1348             :                                       CompositeNH *cnh,
    1349             :                                       const TsnElector *te) {
    1350           0 :     ComponentNHKeyList new_component_nh_key_list;
    1351           0 :     for (ComponentNHKeyList::const_iterator it =
    1352           0 :          cnh->component_nh_key_list().begin();
    1353           0 :          it != cnh->component_nh_key_list().end(); it++) {
    1354           0 :         if ((*it) == NULL)
    1355           0 :             continue;
    1356             :         const TunnelNHKey *tunnel_nh_key =
    1357           0 :             static_cast<const TunnelNHKey *>((*it)->nh_key());
    1358           0 :         if (std::find(te->ManagedPhysicalDevices().begin(),
    1359           0 :                       te->ManagedPhysicalDevices().end(),
    1360           0 :                       tunnel_nh_key->dip().to_string()) !=
    1361           0 :             te->ManagedPhysicalDevices().end()) {
    1362           0 :             new_component_nh_key_list.push_back(*it);
    1363             :         }
    1364             :     }
    1365           0 :     set_original_nh(cnh);
    1366           0 :     DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1367           0 :     nh_req.key.reset(new CompositeNHKey(Composite::EVPN, false,
    1368             :                                         new_component_nh_key_list,
    1369           0 :                                         cnh->vrf()->GetName()));
    1370           0 :     nh_req.data.reset(new CompositeNHData(cnh->pbb_nh(),
    1371           0 :                                           cnh->learning_enabled(), false));
    1372           0 :     agent->nexthop_table()->Process(nh_req);
    1373           0 :     NextHop *new_nh = static_cast<NextHop *>(agent->nexthop_table()->
    1374           0 :                       FindActiveEntry(nh_req.key.get()));
    1375           0 :     assert(new_nh);
    1376           0 :     return new_nh;
    1377           0 : }
    1378             : 
    1379           0 : AgentPath *MulticastRoute::CreateAgentPath(const Peer *peer,
    1380             :                                            AgentRoute *rt) const {
    1381           0 :     return (new MulticastRoutePath(peer));
    1382             : }
    1383             : 
    1384           0 : bool MulticastRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
    1385             :                                            const AgentRoute *rt) {
    1386           0 :     bool ret = false;
    1387           0 :     NextHop *nh = NULL;
    1388             : 
    1389           0 :     agent->nexthop_table()->Process(composite_nh_req_);
    1390           0 :     nh = static_cast<NextHop *>(agent->nexthop_table()->
    1391           0 :             FindActiveEntry(composite_nh_req_.key.get()));
    1392           0 :     assert(nh);
    1393             : 
    1394           0 :     if (agent->params()->agent_mode() == AgentParam::TSN_NO_FORWARDING_AGENT) {
    1395             :         MulticastRoutePath *multicast_path =
    1396           0 :             dynamic_cast<MulticastRoutePath *>(path);
    1397           0 :         multicast_path->set_original_nh(nh);
    1398           0 :         const TsnElector *te = agent->oper_db()->tsn_elector();
    1399           0 :         CompositeNH *cnh = dynamic_cast<CompositeNH *>(nh);
    1400           0 :         if (cnh && (cnh->composite_nh_type() == Composite::EVPN)) {
    1401           0 :             if (te->IsMaster() == false)
    1402           0 :                 path->set_inactive(true);
    1403           0 :             nh = multicast_path->UpdateNH(agent, cnh, te);
    1404             :         }
    1405             :     }
    1406           0 :     ret = MulticastRoute::CopyPathParameters(agent,
    1407             :                    path,
    1408           0 :                    vn_name_,
    1409             :                    false,
    1410             :                    vxlan_id_,
    1411           0 :                    ((label_ == MplsTable::kInvalidLabel) ? path->label() : label_),
    1412             :                    tunnel_type_,
    1413           0 :                    nh, rt, ha_stale_);
    1414           0 :     return ret;
    1415             : }
    1416             : 
    1417           0 : bool MulticastRoute::CopyPathParameters(Agent *agent,
    1418             :                                         AgentPath *path,
    1419             :                                         const std::string &vn_name,
    1420             :                                         bool unresolved,
    1421             :                                         uint32_t vxlan_id,
    1422             :                                         uint32_t label,
    1423             :                                         uint32_t tunnel_type,
    1424             :                                         NextHop *nh,
    1425             :                                         const AgentRoute *rt,
    1426             :                                         bool ha_stale) {
    1427           0 :     VnListType dest_vn_list;
    1428           0 :     dest_vn_list.insert(vn_name);
    1429           0 :     path->set_dest_vn_list(dest_vn_list);
    1430           0 :     path->set_unresolved(unresolved);
    1431           0 :     path->set_vxlan_id(vxlan_id);
    1432           0 :     if ((path->peer() != agent->local_vm_peer()) &&
    1433           0 :         (path->peer() != agent->local_peer()))
    1434           0 :         path->set_label(label);
    1435             : 
    1436             :     //Setting of tunnel is only for simulated TOR.
    1437           0 :     path->set_tunnel_bmap(tunnel_type);
    1438             :     TunnelType::Type new_tunnel_type =
    1439           0 :         TunnelType::ComputeType(tunnel_type);
    1440           0 :     if (new_tunnel_type == TunnelType::VXLAN &&
    1441             :         vxlan_id == VxLanTable::kInvalidvxlan_id) {
    1442           0 :         new_tunnel_type = TunnelType::ComputeType(TunnelType::MplsType());
    1443             :     }
    1444             : 
    1445           0 :     if (path->tunnel_type() != new_tunnel_type) {
    1446           0 :         path->set_tunnel_type(new_tunnel_type);
    1447             :     }
    1448             : 
    1449           0 :     uint32_t old_pref = path->path_preference().preference();
    1450           0 :     if (ha_stale) {
    1451           0 :         if (old_pref != PathPreference::HA_STALE) {
    1452           0 :             path->path_preference_non_const().set_preference(PathPreference::HA_STALE);
    1453             :         }
    1454             :     } else {
    1455           0 :         if (old_pref != PathPreference::LOW) {
    1456           0 :             path->path_preference_non_const().set_preference(PathPreference::LOW);
    1457             :         }
    1458             :     }
    1459             : 
    1460           0 :     path->ChangeNH(agent, nh);
    1461             : 
    1462           0 :     path->ResyncControlWord(rt);
    1463             : 
    1464           0 :     return true;
    1465           0 : }
    1466             : 
    1467           0 : bool MulticastRoute::CanDeletePath(Agent *agent, AgentPath *path,
    1468             :                                    const AgentRoute *rt) const {
    1469           0 :     return (vxlan_id() == path->vxlan_id());
    1470             : }
    1471             : 
    1472           0 : bool PathPreferenceData::AddChangePathExtended(Agent *agent, AgentPath *path,
    1473             :                                        const AgentRoute *rt) {
    1474           0 :     bool ret = false;
    1475             :     //ECMP flag will not be changed by path preference module,
    1476             :     //hence retain value in path
    1477           0 :     if (!path) {
    1478           0 :         return ret;
    1479             :     }
    1480             : 
    1481           0 :     path_preference_.set_ecmp(path->path_preference().ecmp());
    1482           0 :     path_preference_.set_dependent_ip(path->path_preference().dependent_ip());
    1483           0 :     path_preference_.set_vrf(path->path_preference().vrf());
    1484           0 :     if (path &&
    1485           0 :         path->path_preference() != path_preference_) {
    1486           0 :         path->set_path_preference(path_preference_);
    1487           0 :         ret = true;
    1488             :     }
    1489           0 :     return ret;
    1490             : }
    1491             : 
    1492             : // Subnet Route route data
    1493           0 : IpamSubnetRoute::IpamSubnetRoute(DBRequest &nh_req,
    1494           0 :                                  const std::string &dest_vn_name) :
    1495             :     AgentRouteData(AgentRouteData::ADD_DEL_CHANGE, false, 0),
    1496           0 :     dest_vn_name_(dest_vn_name) {
    1497           0 :     nh_req_.Swap(&nh_req);
    1498           0 : }
    1499             : 
    1500           0 : bool IpamSubnetRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
    1501             :                                 const AgentRoute *rt) {
    1502           0 :     agent->nexthop_table()->Process(nh_req_);
    1503           0 :     NextHop *nh = static_cast<NextHop *>(agent->nexthop_table()->
    1504           0 :                                     FindActiveEntry(nh_req_.key.get()));
    1505           0 :     assert(nh);
    1506             : 
    1507           0 :     bool ret = false;
    1508             : 
    1509           0 :     if (path->ChangeNH(agent, nh) == true) {
    1510           0 :         ret = true;
    1511             :     }
    1512           0 :     path->set_is_subnet_discard(true);
    1513             : 
    1514           0 :     VnListType dest_vn_list;
    1515           0 :     dest_vn_list.insert(dest_vn_name_);
    1516           0 :     if (path->dest_vn_list() != dest_vn_list) {
    1517           0 :         path->set_dest_vn_list(dest_vn_list);
    1518           0 :         ret = true;
    1519             :     }
    1520             : 
    1521             :     //Resync of subnet route is needed for identifying if arp flood flag
    1522             :     //needs to be enabled for all the smaller subnets present w.r.t. this subnet
    1523             :     //route.
    1524           0 :     AgentRouteTable *table = static_cast<AgentRouteTable *>(rt->get_table());
    1525           0 :     assert((table->GetTableType() == Agent::INET4_UNICAST) ||
    1526             :            (table->GetTableType() == Agent::INET6_UNICAST));
    1527             : 
    1528           0 :     InetUnicastAgentRouteTable *uc_rt_table =
    1529             :         static_cast<InetUnicastAgentRouteTable *>(table);
    1530           0 :     const InetUnicastRouteEntry *uc_rt =
    1531             :         static_cast<const InetUnicastRouteEntry *>(rt);
    1532           0 :     uc_rt_table->ResyncSubnetRoutes(uc_rt, true);
    1533           0 :     return ret;
    1534           0 : }
    1535             : 
    1536           0 : bool IpamSubnetRoute::UpdateRoute(AgentRoute *rt) {
    1537           0 :     InetUnicastRouteEntry *uc_rt = static_cast<InetUnicastRouteEntry *>(rt);
    1538             : 
    1539           0 :     return uc_rt->UpdateRouteFlags(true, false, false);
    1540             : }
    1541             : 
    1542             : ///////////////////////////////////////////////
    1543             : // Sandesh routines below (route_sandesh.cc)
    1544             : //////////////////////////////////////////////
    1545             : //TODO make it generic
    1546           0 : void UnresolvedNH::HandleRequest() const {
    1547             : 
    1548           0 :     VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromId(0);
    1549           0 :     if (!vrf) {
    1550           0 :         ErrorResp *resp = new ErrorResp();
    1551           0 :         resp->set_context(context());
    1552           0 :         resp->Response();
    1553           0 :         return;
    1554             :     }
    1555             : 
    1556           0 :     int count = 0;
    1557           0 :     std::string empty("");
    1558             :     AgentRouteTable *rt_table = static_cast<AgentRouteTable *>
    1559           0 :         (vrf->GetInet4UnicastRouteTable());
    1560           0 :     NhListResp *resp = new NhListResp();
    1561             : 
    1562             :     //TODO - Convert inet4ucroutetable to agentroutetable
    1563           0 :     AgentRouteTable::UnresolvedNHTree::const_iterator it;
    1564           0 :     it = rt_table->unresolved_nh_begin();
    1565           0 :     for (;it != rt_table->unresolved_nh_end(); it++) {
    1566           0 :         count++;
    1567           0 :         const NextHop *nh = *it;
    1568           0 :         nh->DBEntrySandesh(resp, empty);
    1569           0 :         if (count == 1) {
    1570           0 :             resp->set_context(context()+"$");
    1571           0 :             resp->Response();
    1572           0 :             count = 0;
    1573           0 :             resp = new NhListResp();
    1574             :         }
    1575             :     }
    1576             : 
    1577           0 :     resp->set_context(context());
    1578           0 :     resp->Response();
    1579           0 :     return;
    1580           0 : }
    1581             : 
    1582             : //TODO IMplement filltrace in path class
    1583          78 : void AgentRoute::FillTrace(RouteInfo &rt_info, Trace event,
    1584             :                            const AgentPath *path) const {
    1585          78 :     Agent *agent = static_cast<AgentRouteTable *>(get_table())->agent();
    1586          78 :     rt_info.set_ip(ToString());
    1587          78 :     rt_info.set_vrf(vrf()->GetName());
    1588             : 
    1589          78 :     switch(event) {
    1590          15 :     case ADD:{
    1591          15 :         rt_info.set_op("ADD");
    1592          15 :         break;
    1593             :     }
    1594             : 
    1595          15 :     case DEL: {
    1596          15 :         rt_info.set_op("DELETE");
    1597          15 :         break;
    1598             :     }
    1599             : 
    1600          48 :     case ADD_PATH:
    1601             :     case DELETE_PATH:
    1602             :     case STALE_PATH:
    1603             :     case CHANGE_PATH: {
    1604          48 :         if (event == ADD_PATH) {
    1605          19 :             rt_info.set_op("PATH ADD");
    1606          29 :         } else if (event == CHANGE_PATH) {
    1607          10 :             rt_info.set_op("PATH CHANGE");
    1608          19 :         } else if (event == DELETE_PATH) {
    1609          19 :             rt_info.set_op("PATH DELETE");
    1610           0 :         } else if (event == STALE_PATH) {
    1611           0 :             rt_info.set_op("PATH STALE");
    1612             :         }
    1613             : 
    1614          48 :         if (path == NULL) {
    1615           0 :             rt_info.set_nh_type("<NULL>");
    1616           0 :             break;
    1617             :         }
    1618             : 
    1619          48 :         if (path->peer()) {
    1620          48 :             rt_info.set_peer(path->peer()->GetName());
    1621             :         }
    1622          48 :         rt_info.set_ecmp(path->path_preference().ecmp());
    1623          48 :         const NextHop *nh = path->ComputeNextHop(agent);
    1624          48 :         if (nh == NULL) {
    1625           0 :             rt_info.set_nh_type("<NULL>");
    1626           0 :             break;
    1627             :         }
    1628             : 
    1629          48 :         switch (nh->GetType()) {
    1630           0 :         case NextHop::TUNNEL: {
    1631           0 :             const TunnelNH *tun = static_cast<const TunnelNH *>(nh);
    1632           0 :             rt_info.set_nh_type("TUNNEL");
    1633           0 :             rt_info.set_dest_server(tun->GetDip()->to_string());
    1634           0 :             rt_info.set_dest_server_vrf(tun->GetVrf()->GetName());
    1635           0 :             break;
    1636             :         }
    1637             : 
    1638           4 :         case NextHop::ARP:{
    1639           4 :             rt_info.set_nh_type("DIRECT");
    1640           4 :             break;
    1641             :         }
    1642             : 
    1643           0 :         case NextHop::NDP:{
    1644           0 :             rt_info.set_nh_type("DIRECT");
    1645           0 :             break;
    1646             :         }
    1647             : 
    1648          15 :         case NextHop::INTERFACE: {
    1649          15 :             const InterfaceNH *intf_nh = static_cast<const InterfaceNH *>(nh);
    1650          15 :             rt_info.set_nh_type("INTERFACE");
    1651          15 :             rt_info.set_intf(intf_nh->GetInterface()->name());
    1652          15 :             break;
    1653             :         }
    1654             : 
    1655          10 :         case NextHop::RECEIVE: {
    1656          10 :             const ReceiveNH *rcv_nh = static_cast<const ReceiveNH *>(nh);
    1657          10 :             rt_info.set_nh_type("RECEIVE");
    1658          10 :             rt_info.set_intf(rcv_nh->GetInterface()->name());
    1659          10 :             break;
    1660             :         }
    1661             : 
    1662           9 :         case NextHop::DISCARD: {
    1663           9 :             rt_info.set_nh_type("DISCARD");
    1664           9 :             break;
    1665             :         }
    1666             : 
    1667           0 :         case NextHop::VLAN: {
    1668           0 :             rt_info.set_nh_type("VLAN");
    1669           0 :             break;
    1670             :         }
    1671             : 
    1672           2 :         case NextHop::RESOLVE: {
    1673           2 :             rt_info.set_nh_type("RESOLVE");
    1674           2 :             break;
    1675             :         }
    1676             : 
    1677           0 :         case NextHop::COMPOSITE: {
    1678           0 :             rt_info.set_nh_type("COMPOSITE");
    1679           0 :             break;
    1680             :         }
    1681             : 
    1682           8 :         case NextHop::L2_RECEIVE: {
    1683           8 :             rt_info.set_nh_type("L2_RECEIVE");
    1684           8 :             break;
    1685             :         }
    1686             : 
    1687           0 :         case NextHop::PBB: {
    1688           0 :             const PBBNH *pbb_nh = static_cast<const PBBNH *>(nh);
    1689           0 :             rt_info.set_nh_type("PBB");
    1690           0 :             rt_info.set_mac(pbb_nh->dest_bmac().ToString());
    1691           0 :             if (pbb_nh->vrf()) {
    1692           0 :                 rt_info.set_dest_server_vrf(pbb_nh->vrf()->GetName());
    1693             :             }
    1694           0 :             break;
    1695             :         }
    1696             : 
    1697           0 :         case NextHop::VRF: {
    1698           0 :             const VrfNH *vrf_nh = static_cast<const VrfNH *>(nh);
    1699           0 :             rt_info.set_nh_type("VRF");
    1700           0 :             rt_info.set_vrf_nh_name(vrf_nh->GetVrf()->GetName());
    1701           0 :             break;
    1702             :         }
    1703             : 
    1704           0 :         default:
    1705           0 :             assert(0);
    1706             :             break;
    1707             :         }
    1708          48 :        break;
    1709             :     }
    1710             :     }
    1711          78 : }
    1712             : 
    1713          48 : void AgentPath::GetDestinationVnList(std::vector<std::string> *vn_list) const {
    1714          48 :     for (VnListType::const_iterator vnit = dest_vn_list().begin();
    1715          96 :          vnit != dest_vn_list().end(); ++vnit) {
    1716          48 :         vn_list->push_back(*vnit);
    1717             :     }
    1718          48 : }
    1719             : 
    1720           0 : void AgentPath::SetSandeshData(PathSandeshData &pdata) const {
    1721           0 :     const NextHop *nh = nexthop();
    1722           0 :     if (nh != NULL) {
    1723           0 :         nh->SetNHSandeshData(pdata.nh);
    1724             :     }
    1725           0 :     pdata.set_peer(const_cast<Peer *>(peer())->GetName());
    1726           0 :     std::vector<std::string> vn_list;
    1727           0 :     GetDestinationVnList(&vn_list);
    1728           0 :     pdata.set_dest_vn_list(vn_list);
    1729           0 :     pdata.set_origin_vn(origin_vn());
    1730           0 :     pdata.set_unresolved(unresolved() ? "true" : "false");
    1731             : 
    1732           0 :     if (!gw_ip().is_unspecified()) {
    1733           0 :         pdata.set_gw_ip(gw_ip().to_string());
    1734           0 :         pdata.set_vrf(vrf_name());
    1735             :     }
    1736             : 
    1737           0 :     if (ecmp_suppressed()) {
    1738           0 :         pdata.set_ecmp_suppressed(true);
    1739             :     }
    1740             : 
    1741           0 :     pdata.set_sg_list(sg_list());
    1742           0 :     pdata.set_communities(communities());
    1743           0 :     pdata.set_tag_list(tag_list());
    1744           0 :     pdata.set_vxlan_id(vxlan_id());
    1745           0 :     pdata.set_label(label());
    1746           0 :     if (nh != NULL && nh->GetType() == NextHop::PBB) {
    1747           0 :         const PBBNH *pbb_nh = static_cast<const PBBNH *>(nh);
    1748           0 :         if (pbb_nh->child_nh() != NULL) {
    1749           0 :             const TunnelNH *tun_nh = dynamic_cast<const TunnelNH *>(pbb_nh->child_nh());
    1750           0 :             if (tun_nh != NULL) {
    1751           0 :                 pdata.set_active_tunnel_type((tun_nh->GetTunnelType()).ToString());
    1752             :             }
    1753             :         }
    1754             :     } else {
    1755           0 :         pdata.set_active_tunnel_type(
    1756           0 :             TunnelType(tunnel_type()).ToString());
    1757             :     }
    1758           0 :     pdata.set_supported_tunnel_type(
    1759           0 :             TunnelType::GetString(tunnel_bmap()));
    1760           0 :     PathPreferenceSandeshData path_preference_data;
    1761           0 :     path_preference_data.set_sequence(path_preference_.sequence());
    1762           0 :     path_preference_data.set_preference(path_preference_.preference());
    1763           0 :     path_preference_data.set_ecmp(path_preference_.is_ecmp());
    1764           0 :     if ((peer()->GetType() != Peer::BGP_PEER) && (peer()->GetType() != Peer::ECMP_PEER )) {
    1765           0 :         path_preference_data.set_wait_for_traffic(
    1766           0 :              path_preference_.wait_for_traffic());
    1767             :     }
    1768           0 :     if (path_preference_.dependent_ip().is_unspecified() == false) {
    1769           0 :         std::ostringstream str;
    1770           0 :         str << path_preference_.vrf() << " : " <<path_preference_.dependent_ip().to_string();
    1771           0 :         path_preference_data.set_dependent_ip(str.str());
    1772           0 :     }
    1773           0 :     pdata.set_path_preference_data(path_preference_data);
    1774           0 :     pdata.set_active_label(GetActiveLabel());
    1775           0 :     if (peer()->GetType() == Peer::MAC_VM_BINDING_PEER) {
    1776           0 :         const MacVmBindingPath *dhcp_path =
    1777             :             static_cast<const MacVmBindingPath *>(this);
    1778           0 :         pdata.set_flood_dhcp(dhcp_path->flood_dhcp() ? "true" : "false");
    1779           0 :         pdata.set_vm_name(dhcp_path->vm_interface()->ToString());
    1780             :     }
    1781           0 :     std::vector<std::string> string_vector;
    1782           0 :     ecmp_load_balance_.GetStringVector(string_vector);
    1783             :     std::vector<std::string>::iterator string_vector_iter =
    1784           0 :         string_vector.begin();
    1785           0 :     std::stringstream ss;
    1786           0 :     while (string_vector_iter != string_vector.end()) {
    1787           0 :         ss << (*string_vector_iter);
    1788           0 :         ss << ",";
    1789           0 :         string_vector_iter++;
    1790             :     }
    1791           0 :     pdata.set_ecmp_hashing_fields(ss.str());
    1792           0 :     pdata.set_peer_sequence_number(peer_sequence_number());
    1793           0 :     const BgpPeer *bgp_peer = dynamic_cast<const BgpPeer *>(peer());
    1794           0 :     bool is_stale = false;
    1795           0 :     if (bgp_peer) {
    1796           0 :         if (peer_sequence_number() < bgp_peer->ChannelSequenceNumber())
    1797           0 :             is_stale = true;
    1798             :     }
    1799           0 :     pdata.set_stale(is_stale);
    1800           0 :     pdata.set_etree_leaf(etree_leaf());
    1801           0 :     pdata.set_layer2_control_word(layer2_control_word());
    1802           0 :     pdata.set_inactive(inactive());
    1803           0 : }
    1804             : 
    1805           0 : void AgentPath::set_local_ecmp_mpls_label(MplsLabel *mpls) {
    1806           0 :     local_ecmp_mpls_label_.reset(mpls);
    1807           0 : }
    1808             : 
    1809           0 : bool AgentPath::dest_vn_match(const std::string &vn) const {
    1810           0 :     if (dest_vn_list_.find(vn) != dest_vn_list_.end())
    1811           0 :         return true;
    1812           0 :     return false;
    1813             : }
    1814             : 
    1815           0 : const MplsLabel* AgentPath::local_ecmp_mpls_label() const {
    1816           0 :     return local_ecmp_mpls_label_.get();
    1817             : }
    1818             : 
    1819             : //In case of composite NH in fabric VRF, if BGP path has router
    1820             : //id of compute node then copy the ECMP peer or local VM peer path
    1821             : //to composite NH.
    1822             : //In case of overlay mode MPLS label was used to frame local nexthop
    1823             : //list which is not feasible in this fabric VRF
    1824           0 : void AgentPath::CopyLocalPath(CompositeNHKey *composite_nh_key,
    1825             :                               const AgentPath *local_path) {
    1826             : 
    1827           0 :     if (local_path == NULL) {
    1828           0 :         return;
    1829             :     }
    1830             : 
    1831           0 :     DBEntryBase::KeyPtr key_nh = local_path->nexthop()->GetDBRequestKey();
    1832           0 :     NextHopKey *nh_key = static_cast<NextHopKey *>(key_nh.get());
    1833           0 :     nh_key->SetPolicy(false);
    1834           0 :     std::unique_ptr<const NextHopKey> nh_key_p(nh_key->Clone());
    1835             : 
    1836           0 :     ComponentNHKeyList comp_nh_list;
    1837           0 :     if (nh_key_p->GetType() == NextHop::COMPOSITE) {
    1838             :         //Append the list of component NH list from local ecmp peer
    1839           0 :         const CompositeNHKey *comp_nh_key =
    1840             :             static_cast<const CompositeNHKey *>(nh_key);
    1841           0 :         comp_nh_list = comp_nh_key->component_nh_key_list();
    1842             :     } else {
    1843             :         //Append the interface NH to composite NH list
    1844           0 :         ComponentNHKeyPtr new_comp_nh(new ComponentNHKey(0, std::move(nh_key_p)));
    1845           0 :         comp_nh_list.push_back(new_comp_nh);
    1846           0 :     }
    1847             : 
    1848           0 :     composite_nh_key->ReplaceLocalNexthop(comp_nh_list);
    1849           0 : }
    1850             : 
    1851           0 : bool AgentPath::ReorderCompositeNH(Agent *agent,
    1852             :                                    CompositeNHKey *composite_nh_key,
    1853             :                                    bool &comp_nh_policy,
    1854             :                                    const AgentPath *path) {
    1855           0 :     if (copy_local_path_) {
    1856           0 :         CopyLocalPath(composite_nh_key, path);
    1857             :     }
    1858             : 
    1859             :     //Find local composite mpls label, if present
    1860             :     //This has to be done, before expanding component NH
    1861           0 :     BOOST_FOREACH(ComponentNHKeyPtr component_nh_key,
    1862             :                   composite_nh_key->component_nh_key_list()) {
    1863           0 :          if (component_nh_key.get() == NULL ||
    1864           0 :                  component_nh_key->nh_key()->GetType() != NextHop::COMPOSITE) {
    1865           0 :              continue;
    1866             :          }
    1867             :          const CompositeNHKey *composite_key =
    1868           0 :              static_cast<const CompositeNHKey *>(component_nh_key->nh_key());
    1869             :          // composite NH, check composite nh type
    1870             :          // if it is not local ecmp , skip processing
    1871           0 :          if (composite_key->composite_nh_type() !=
    1872             :                         Composite::LOCAL_ECMP) {
    1873           0 :              continue;
    1874             :          }
    1875             :          //Get mpls label allocated for this composite NH
    1876             :          MplsLabel *mpls = agent->mpls_table()->
    1877           0 :              FindMplsLabel(component_nh_key->label());
    1878           0 :          if (!mpls) {
    1879             :              //If a mpls label is deleted,
    1880             :              //wait for bgp to update latest list
    1881           0 :              local_ecmp_mpls_label_.reset(mpls);
    1882           0 :              return false;
    1883             :          }
    1884             : 
    1885           0 :          if (mpls == local_ecmp_mpls_label_.get()) {
    1886           0 :              break;
    1887             :          }
    1888           0 :          local_ecmp_mpls_label_.reset(mpls);
    1889             :          //Check if MPLS is pointing to same NH as mentioned in key list.
    1890             :          //It may so happen that by the time this request is serviced(say in
    1891             :          //case of remote route add from CN), mpls label ahs been re-used for
    1892             :          //some other purpose. If it is so then ignore the request and wait for
    1893             :          //another update.
    1894           0 :          const NextHopKey *nh_key_1 = component_nh_key->nh_key();
    1895           0 :          DBEntryBase::KeyPtr key = mpls->nexthop()->GetDBRequestKey();
    1896           0 :          const NextHopKey *nh_key_2 = static_cast<const NextHopKey*>(key.get());
    1897           0 :          if (nh_key_1->IsEqual(*nh_key_2) == false) {
    1898           0 :              return false;
    1899             :          }
    1900           0 :          break;
    1901           0 :      }
    1902             : 
    1903             :     //Make a copy of composite NH, so that aggregarate mpls
    1904             :     //label allocated for local composite ecmp is maintained
    1905             :     //as data in path
    1906           0 :     CompositeNHKey *comp_key = composite_nh_key->Clone();
    1907             :     //Reorder the keys so that, existing component NH maintain
    1908             :     //there previous position
    1909             :     //For example take a composite NH with members A, B, C
    1910             :     //in that exact order,If B gets deleted,
    1911             :     //the new composite NH created should be A <NULL> C in that order,
    1912             :     //irrespective of the order user passed it in
    1913           0 :     comp_nh_policy = composite_nh_key->Reorder(agent, label_,
    1914           0 :                                                ComputeNextHop(agent));
    1915             :     //Copy the unchanged component NH list to path data
    1916           0 :     set_composite_nh_key(comp_key);
    1917           0 :     return true;
    1918             : }
    1919             : 
    1920           0 : bool AgentPath::ChangeCompositeNH(Agent *agent,
    1921             :                                   CompositeNHKey *composite_nh_key) {
    1922           0 :     DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1923           0 :     nh_req.key.reset(composite_nh_key->Clone());
    1924           0 :     nh_req.data.reset(new CompositeNHData());
    1925             : 
    1926           0 :     NextHop *nh = static_cast<NextHop *>(agent->nexthop_table()->
    1927           0 :             FindActiveEntry(composite_nh_key));
    1928           0 :     if (!nh) {
    1929           0 :         agent->nexthop_table()->Process(nh_req);
    1930           0 :         nh = static_cast<NextHop *>(agent->nexthop_table()->
    1931           0 :             FindActiveEntry(composite_nh_key));
    1932             :     }
    1933             : 
    1934             :     // NH can be NULL in the following scenario
    1935             :     // when VMI is deleted and it is the only member of VRF
    1936             :     // and VMI is part of AAP, then local ecmp route path
    1937             :     // is deleted from route and vrf delete would trigger route deletions
    1938             :     // in the VRF. while deleting the active path, import Nh from prev active
    1939             :     // path function copies the previous active path's NH to current active path
    1940             :     // and recalucalate composite NH based on composite nh key of current
    1941             :     // active path. if component nh key element of composite nh key is
    1942             :     // interface nh key which is already deleted then processing nh req would
    1943             :     // result NULL, in that case return false.
    1944             :     //assert(nh);
    1945           0 :     if (nh == NULL) {
    1946           0 :         return false;
    1947             :     }
    1948             : 
    1949           0 :     if (ChangeNH(agent, nh) == true) {
    1950           0 :         return true;
    1951             :     }
    1952           0 :     return false;
    1953           0 : }
    1954             : 
    1955           0 : const Ip4Address *AgentPath::NexthopIp(Agent *agent) const {
    1956           0 :     if (peer_ == NULL) {
    1957           0 :         return agent->router_ip_ptr();
    1958             :     }
    1959             : 
    1960           0 :     return peer_->NexthopIp(agent, this);
    1961             : }
    1962             : 
    1963           1 : MacVmBindingPath::MacVmBindingPath(const Peer *peer) :
    1964           1 :     AgentPath(peer, NULL), vm_interface_(NULL), flood_dhcp_(false) {
    1965           1 : }
    1966             : 
    1967          10 : bool MacVmBindingPath::IsLess(const AgentPath &r_path) const {
    1968          10 :     return peer()->IsLess(r_path.peer());
    1969             : }
    1970             : 
    1971           2 : const NextHop *MacVmBindingPath::ComputeNextHop(Agent *agent) const {
    1972           2 :     return nexthop();
    1973             : }
    1974             : 
    1975           1 : AgentPath *MacVmBindingPathData::CreateAgentPath(const Peer *peer,
    1976             :                                          AgentRoute *rt) const {
    1977           1 :     const Peer *mac_vm_binding_peer =
    1978             :         dynamic_cast<const Peer *>(peer);
    1979           1 :     assert(mac_vm_binding_peer != NULL);
    1980           1 :     return (new MacVmBindingPath(mac_vm_binding_peer));
    1981             : }
    1982             : 
    1983           1 : bool MacVmBindingPathData::AddChangePathExtended(Agent *agent, AgentPath *path,
    1984             :                                          const AgentRoute *rt) {
    1985           1 :     bool ret = false;
    1986             :     MacVmBindingPath *dhcp_path =
    1987           1 :         dynamic_cast<MacVmBindingPath *>(path);
    1988             : 
    1989           1 :     NextHop *nh = agent->nexthop_table()->discard_nh();
    1990           1 :     if (path->ChangeNH(agent, nh) == true)
    1991           1 :         ret = true;
    1992             : 
    1993           1 :     if (dhcp_path->flood_dhcp() != flood_dhcp_) {
    1994           0 :         dhcp_path->set_flood_dhcp(flood_dhcp_);
    1995           0 :         ret = true;
    1996             :     }
    1997             : 
    1998           1 :     if (dhcp_path->vm_interface() != vm_intf_) {
    1999           1 :         dhcp_path->set_vm_interface(vm_intf_);
    2000           1 :         ret = true;
    2001             :     }
    2002             : 
    2003           1 :     return ret;
    2004             : }
    2005             : 
    2006           0 : void AgentPath::UpdateEcmpHashFields(const Agent *agent,
    2007             :                                      const EcmpLoadBalance &ecmp_load_balance,
    2008             :                                      DBRequest &nh_req) {
    2009             : 
    2010           0 :     NextHop *nh = NULL;
    2011           0 :     nh = static_cast<NextHop *>(agent->nexthop_table()->
    2012           0 :                                 FindActiveEntry(nh_req.key.get()));
    2013           0 :     CompositeNH *cnh = dynamic_cast< CompositeNH *>(nh);
    2014           0 :     if (cnh) {
    2015           0 :         ecmp_hash_fields_.CalculateChangeInEcmpFields(ecmp_load_balance,
    2016             :                                                      cnh->CompEcmpHashFields());
    2017             :     } else {
    2018           0 :         agent->nexthop_table()->Process(nh_req);
    2019           0 :         nh = static_cast<NextHop *>(agent->nexthop_table()->
    2020           0 :                                     FindActiveEntry(nh_req.key.get()));
    2021           0 :         CompositeNH *cnh = static_cast< CompositeNH *>(nh);
    2022           0 :         if (cnh) {
    2023           0 :             ecmp_hash_fields_.CalculateChangeInEcmpFields(ecmp_load_balance,
    2024             :                                                           cnh->CompEcmpHashFields());
    2025             :         }
    2026             :     }
    2027           0 : }
    2028             : 
    2029           0 : void AgentPath::ResetEcmpHashFields() {
    2030           0 :     ecmp_hash_fields_.Reset();
    2031           0 : }
    2032             : 
    2033           3 : bool AgentPath::ResyncControlWord(const AgentRoute *rt) {
    2034             :     const BridgeRouteEntry *bridge_rt =
    2035           3 :         dynamic_cast<const BridgeRouteEntry *>(rt);
    2036           3 :     if (!bridge_rt || rt->vrf() == NULL) {
    2037           0 :         return false;
    2038             :     }
    2039             : 
    2040           3 :     if (layer2_control_word() != bridge_rt->vrf()->layer2_control_word()) {
    2041           0 :         set_layer2_control_word(bridge_rt->vrf()->layer2_control_word());
    2042           0 :         return true;
    2043             :     }
    2044             : 
    2045           3 :     return false;
    2046             : }
    2047             : 
    2048           0 : EvpnRoutingPath::EvpnRoutingPath(const Peer *peer,
    2049             :                                  AgentRoute *rt,
    2050           0 :                                  VrfEntryConstRef routing_vrf) :
    2051           0 :     AgentPath(peer, rt), routing_vrf_(routing_vrf) {
    2052           0 :         l3_vrf_vxlan_id_ = routing_vrf.get()->vxlan_id();
    2053           0 : }
    2054             : 
    2055           0 : EvpnRoutingPath::~EvpnRoutingPath() {
    2056           0 : }
    2057             : 
    2058           0 : const VrfEntry *EvpnRoutingPath::routing_vrf() const {
    2059           0 :     return routing_vrf_.get();
    2060             : }
    2061             : 
    2062           0 : void EvpnRoutingPath::set_routing_vrf(const VrfEntry *vrf) {
    2063           0 :     routing_vrf_.reset(vrf);
    2064           0 : }
    2065             : 
    2066           0 : void EvpnRoutingPath::DeleteEvpnType5Route(Agent *agent,
    2067             :                                            const AgentRoute *rt) const {
    2068           0 :     const VrfEntry *l3_vrf = routing_vrf_.get();
    2069           0 :     if (!l3_vrf)
    2070           0 :         return;
    2071             : 
    2072             :     const InetUnicastRouteEntry *inet_rt =
    2073           0 :         dynamic_cast<const InetUnicastRouteEntry *>(rt);
    2074           0 :     if (!inet_rt) {
    2075           0 :         return;
    2076             :     }
    2077             :     const EvpnAgentRouteTable *evpn_table =
    2078           0 :         static_cast<EvpnAgentRouteTable *>(l3_vrf->GetEvpnRouteTable());
    2079           0 :     evpn_table->Delete(agent->local_vm_export_peer(), l3_vrf->GetName(),
    2080           0 :                        MacAddress(), inet_rt->prefix_address(),
    2081           0 :                        l3_vrf_vxlan_id_);
    2082             : }
    2083             : 
    2084           0 : EvpnRoutingData::EvpnRoutingData(DBRequest &nh_req,
    2085             :                                  const SecurityGroupList &sg_list,
    2086             :                                  const CommunityList &communities,
    2087             :                                  const PathPreference &path_preference,
    2088             :                                  const EcmpLoadBalance &ecmp_load_balance,
    2089             :                                  const TagList &tag_list,
    2090             :                                  VrfEntryConstRef vrf_entry,
    2091             :                                  uint32_t vxlan_id,
    2092             :                                  const VnListType& vn_list,
    2093           0 :                                  const std::string& origin_vn):
    2094             :     AgentRouteData(AgentRouteData::ADD_DEL_CHANGE, false, 0),
    2095           0 :     sg_list_(sg_list),
    2096           0 :     communities_(communities),
    2097           0 :     path_preference_(path_preference),
    2098           0 :     ecmp_load_balance_(ecmp_load_balance),
    2099           0 :     tag_list_(tag_list),
    2100           0 :     routing_vrf_(vrf_entry), vxlan_id_(vxlan_id),
    2101           0 :     dest_vn_list_(vn_list),
    2102           0 :     origin_vn_(origin_vn) {
    2103           0 :         nh_req_.Swap(&nh_req);
    2104           0 : }
    2105             : 
    2106           0 : AgentPath *EvpnRoutingData::CreateAgentPath(const Peer *peer,
    2107             :                                             AgentRoute *rt) const {
    2108           0 :     return (new EvpnRoutingPath(peer, rt, routing_vrf_));
    2109             : }
    2110             : 
    2111           0 : bool EvpnRoutingData::AddChangePathExtended(Agent *agent,
    2112             :                                             AgentPath *path,
    2113             :                                             const AgentRoute *rt) {
    2114           0 :     bool ret = false;
    2115           0 :     EvpnRoutingPath *evpn_path = static_cast<EvpnRoutingPath *>(path);
    2116             : 
    2117             :     //Process nexthop
    2118           0 :     agent->nexthop_table()->Process(nh_req_);
    2119           0 :     NextHop *nh = static_cast<NextHop *>(agent->nexthop_table()->
    2120           0 :                                          FindActiveEntry(nh_req_.key.get()));
    2121             : 
    2122           0 :     InterfaceNH *intf_nh = dynamic_cast<InterfaceNH *>(nh);
    2123           0 :     if (intf_nh) {
    2124           0 :         intf_nh->set_delete_on_zero_refcount(true);
    2125             :     }
    2126           0 :     if (routing_vrf_.get() != evpn_path->routing_vrf()) {
    2127             :         //Remove from old vrf
    2128           0 :         evpn_path->DeleteEvpnType5Route(agent, rt);
    2129           0 :         evpn_path->set_routing_vrf(routing_vrf_.get());
    2130           0 :         ret = true;
    2131             :     }
    2132             : 
    2133           0 :     if (path->ChangeNH(agent, nh) == true) {
    2134           0 :         ret = true;
    2135             :     }
    2136             : 
    2137           0 :     if (sg_list_ != path->sg_list()) {
    2138           0 :         path->set_sg_list(sg_list_);
    2139           0 :         ret = true;
    2140             :     }
    2141             : 
    2142             :     /* Setting the origin_vn in the route path */
    2143           0 :     if (path->origin_vn() != origin_vn_) {
    2144           0 :         path->set_origin_vn(origin_vn_);
    2145           0 :         ret = true;
    2146             :     }
    2147             : 
    2148             :     // Set dest vn
    2149           0 :     path->set_dest_vn_list(dest_vn_list_);
    2150             : 
    2151           0 :     if (communities_ != path->communities()) {
    2152           0 :         path->set_communities(communities_);
    2153           0 :         ret =true;
    2154             :     }
    2155             : 
    2156           0 :     if (path_preference_ != path->path_preference()) {
    2157           0 :         path->set_path_preference(path_preference_);
    2158           0 :         ret = true;
    2159             :     }
    2160             : 
    2161           0 :     if (ecmp_load_balance_ != path->ecmp_load_balance()) {
    2162           0 :         path->set_ecmp_load_balance(ecmp_load_balance_);
    2163           0 :         ret =true;
    2164             :     }
    2165             : 
    2166           0 :     if (tag_list_ != path->tag_list()) {
    2167           0 :         path->set_tag_list(tag_list_);
    2168           0 :         ret =true;
    2169             :     }
    2170             : 
    2171           0 :     path->set_tunnel_type(TunnelType::VXLAN);
    2172           0 :     path->set_tunnel_bmap(TunnelType::VxlanType());
    2173           0 :     path->set_vxlan_id(vxlan_id_);
    2174             : 
    2175           0 :     return ret;
    2176             : }
    2177             : 
    2178           0 : bool EvpnRoutingData::CanDeletePath(Agent *agent, AgentPath *path,
    2179             :                                     const AgentRoute *rt) const {
    2180           0 :     EvpnRoutingPath *evpn_path = dynamic_cast<EvpnRoutingPath *>(path);
    2181           0 :     if (!evpn_path) {
    2182           0 :         return true;
    2183             :     }
    2184           0 :     if (rt->vrf() != evpn_path->routing_vrf()) {
    2185             :         //Remove from old vrf
    2186           0 :         evpn_path->DeleteEvpnType5Route(agent, rt);
    2187             :     }
    2188           0 :     return true;
    2189             : }
    2190           0 : bool EvpnRoutingData::UpdateRoute(AgentRoute *rt) {
    2191             :     InetUnicastRouteEntry *uc_rt =
    2192           0 :         dynamic_cast<InetUnicastRouteEntry *>(rt);
    2193           0 :     if (!uc_rt) {
    2194           0 :         return false;
    2195             :     }
    2196           0 :     return uc_rt->UpdateRouteFlags(false, false, true);
    2197             : }
    2198           0 : AgentPathEcmpComponent::AgentPathEcmpComponent(IpAddress addr, uint32_t label,
    2199           0 :                             AgentRoute *rt):
    2200           0 :            addr_(addr), label_(label), dependent_rt_(rt) {}
    2201             : 

Generated by: LCOV version 1.14