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: 652 1320 49.4 %
Date: 2026-11-09 02:10:49 Functions: 57 83 68.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14