LCOV - code coverage report
Current view: top level - vnsw/agent/oper - inet_unicast_route.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 574 1064 53.9 %
Date: 2026-08-03 02:19:58 Functions: 67 102 65.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <boost/uuid/uuid_io.hpp>
       6             : 
       7             : #include <base/address_util.h>
       8             : #include <base/task_annotations.h>
       9             : #include <boost/foreach.hpp>
      10             : #include <cmn/agent_cmn.h>
      11             : #include <route/route.h>
      12             : #include <oper/ecmp.h>
      13             : #include <oper/ecmp_load_balance.h>
      14             : #include <oper/route_common.h>
      15             : #include <oper/vrf.h>
      16             : #include <oper/tunnel_nh.h>
      17             : #include <oper/mpls.h>
      18             : #include <oper/vxlan.h>
      19             : #include <oper/mirror_table.h>
      20             : #include <oper/multicast.h>
      21             : #include <controller/controller_export.h>
      22             : #include <controller/controller_peer.h>
      23             : #include <controller/controller_route_path.h>
      24             : #include <oper/agent_sandesh.h>
      25             : 
      26             : using namespace std;
      27             : using namespace boost::asio;
      28             : 
      29             : AgentRoute *
      30         765 : InetUnicastRouteKey::AllocRouteEntry(VrfEntry *vrf, bool is_multicast) const {
      31             :     InetUnicastRouteEntry * entry =
      32         765 :         new InetUnicastRouteEntry(vrf, dip_, plen_, is_multicast);
      33         765 :     return static_cast<AgentRoute *>(entry);
      34             : }
      35             : 
      36           8 : AgentRouteKey *InetUnicastRouteKey::Clone() const {
      37           8 :     return (new InetUnicastRouteKey(peer(), vrf_name_, dip_, plen_));
      38             : }
      39             : 
      40           1 : AgentRouteKey *InetMplsUnicastRouteKey::Clone() const {
      41           1 :     return (new InetMplsUnicastRouteKey(peer(), vrf_name_, dip_, plen_));
      42             : }
      43             : /////////////////////////////////////////////////////////////////////////////
      44             : // InetUnicastAgentRouteTable functions
      45             : /////////////////////////////////////////////////////////////////////////////
      46          36 : InetUnicastAgentRouteTable::InetUnicastAgentRouteTable(DB *db,
      47          36 :                                                        const std::string &name) :
      48          36 :     AgentRouteTable(db, name), walkid_(DBTableWalker::kInvalidWalkerId) {
      49             : 
      50          36 :     if (name.find("uc.route.0") != std::string::npos) {
      51          12 :         type_ = Agent::INET4_UNICAST;
      52          24 :     } else if (name.find("uc.route.3") != std::string::npos) {
      53          12 :         type_ = Agent::INET4_MPLS;
      54          12 :     } else if (name.find("uc.route6.0") != std::string::npos) {
      55          12 :         type_ = Agent::INET6_UNICAST;
      56           0 :     } else if (name.find("evpn.route.0") != std::string::npos) {
      57           0 :         type_ = Agent::EVPN;
      58           0 :     } else if (name.find("l2.route.0") != std::string::npos) {
      59           0 :         type_ = Agent::BRIDGE;
      60           0 :     } else if (name.find("mc.route.0") != std::string::npos) {
      61           0 :         type_ = Agent::INET4_MULTICAST;
      62             :     } else {
      63           0 :         type_ = Agent::INVALID;
      64             :     }
      65          36 : }
      66             : 
      67             : DBTableBase *
      68          36 : InetUnicastAgentRouteTable::CreateTable(DB *db, const std::string &name) {
      69          36 :     AgentRouteTable *table = new InetUnicastAgentRouteTable(db, name);
      70          36 :     table->Init();
      71          36 :     return table;
      72             : }
      73             : 
      74             : InetUnicastRouteEntry *
      75         184 : InetUnicastAgentRouteTable::FindLPM(const IpAddress &ip) {
      76         184 :     uint32_t plen = 128;
      77         184 :     if (ip.is_v4()) {
      78         184 :         plen = 32;
      79             :     }
      80         184 :     InetUnicastRouteEntry key(NULL, ip, plen, false);
      81         368 :     return tree_.LPMFind(&key);
      82         184 : }
      83             : 
      84             : InetUnicastRouteEntry *
      85         270 : InetUnicastAgentRouteTable::FindLPM(const InetUnicastRouteEntry &rt_key) {
      86         270 :     return tree_.LPMFind(&rt_key);
      87             : }
      88             : 
      89             : InetUnicastRouteEntry *
      90          24 : InetUnicastAgentRouteTable::FindResolveRoute(const Ip4Address &ip) {
      91          24 :     uint8_t plen = 32;
      92          24 :     InetUnicastRouteEntry *rt = NULL;
      93             :     do {
      94          42 :         InetUnicastRouteEntry key(NULL, ip, plen, false);
      95          42 :         rt = tree_.LPMFind(&key);
      96          42 :         if (rt) {
      97          39 :             const NextHop *nh = rt->GetActiveNextHop();
      98          39 :             if (nh && nh->GetType() == NextHop::RESOLVE)
      99          21 :                 return rt;
     100             :         }
     101          63 :     } while (rt && --plen);
     102             : 
     103           3 :     return NULL;
     104             : }
     105             : 
     106             : InetUnicastRouteEntry *
     107           0 : InetUnicastAgentRouteTable::FindResolveRoute(const string &vrf_name,
     108             :                                              const Ip4Address &ip) {
     109             :     VrfEntry *vrf =
     110           0 :         Agent::GetInstance()->vrf_table()->FindVrfFromName(vrf_name);
     111             :     InetUnicastAgentRouteTable *rt_table =
     112             :               static_cast<InetUnicastAgentRouteTable *>
     113           0 :               (vrf->GetInet4UnicastRouteTable());
     114           0 :     return rt_table->FindResolveRoute(ip);
     115             : }
     116             : 
     117          52 : static void Inet4UnicastTableEnqueue(Agent *agent, DBRequest *req) {
     118          52 :     AgentRouteTable *table = agent->fabric_inet4_unicast_table();
     119          52 :     if (table) {
     120          52 :         table->Enqueue(req);
     121             :     }
     122          52 : }
     123             : 
     124           3 : static void Inet4MplsUnicastTableEnqueue(Agent *agent, DBRequest *req) {
     125           3 :     AgentRouteTable *table = agent->fabric_inet4_mpls_table();
     126           3 :     if (table) {
     127           3 :         table->Enqueue(req);
     128             :     }
     129           3 : }
     130             : 
     131         126 : static void Inet6UnicastTableEnqueue(Agent *agent, const string &vrf_name,
     132             :                                      DBRequest *req) {
     133         126 :     AgentRouteTable *table = agent->fabric_inet4_unicast_table();
     134         126 :     if (table) {
     135         126 :         table->Enqueue(req);
     136             :     }
     137         126 : }
     138             : 
     139         166 : static void InetUnicastTableEnqueue(Agent *agent, const string &vrf,
     140             :                                     DBRequest *req) {
     141         166 :     InetUnicastRouteKey *key = static_cast<InetUnicastRouteKey *>(req->key.get());
     142         166 :     if (key->addr().is_v4()) {
     143          40 :         Inet4UnicastTableEnqueue(agent, req);
     144         126 :     } else if (key->addr().is_v6()) {
     145         126 :         Inet6UnicastTableEnqueue(agent, vrf, req);
     146             :     }
     147         166 : }
     148             : 
     149         108 : static void Inet4UnicastTableProcess(Agent *agent, const string &vrf_name,
     150             :                                      DBRequest &req) {
     151             :     AgentRouteTable *table =
     152         108 :         agent->vrf_table()->GetInet4UnicastRouteTable(vrf_name);
     153         108 :     if (table) {
     154         108 :         table->Process(req);
     155             :     }
     156         108 : }
     157             : 
     158          31 : static void Inet6UnicastTableProcess(Agent *agent, const string &vrf_name,
     159             :                                      DBRequest &req) {
     160             :     AgentRouteTable *table =
     161          31 :         agent->vrf_table()->GetInet6UnicastRouteTable(vrf_name);
     162          31 :     if (table) {
     163          31 :         table->Process(req);
     164             :     }
     165          31 : }
     166             : 
     167         113 : static void InetUnicastTableProcess(Agent *agent, const string &vrf_name,
     168             :                                     DBRequest &req) {
     169         113 :     InetUnicastRouteKey *key = static_cast<InetUnicastRouteKey *>(req.key.get());
     170         113 :     if (key->addr().is_v4()) {
     171          85 :         Inet4UnicastTableProcess(agent, vrf_name, req);
     172          28 :     } else if (key->addr().is_v6()) {
     173          28 :         Inet6UnicastTableProcess(agent, vrf_name, req);
     174             :     }
     175         113 : }
     176             : 
     177             : /*
     178             :  * Traverse all smaller subnets w.r.t. route sent and mark the arp flood flag
     179             :  * accordingly.
     180             :  */
     181           6 : bool InetUnicastAgentRouteTable::ResyncSubnetRoutes
     182             : (const InetUnicastRouteEntry *rt, bool val) {
     183           6 :     const IpAddress addr = rt->prefix_address();
     184           6 :     uint16_t plen = rt->prefix_length();
     185           6 :     InetUnicastRouteEntry *lpm_rt = GetNextNonConst(rt);
     186             : 
     187           6 :     Ip4Address v4_parent_mask;
     188           6 :     Ip6Address v6_parent_mask;
     189             : 
     190           6 :     if (GetTableType() == Agent::INET4_UNICAST) {
     191          12 :         v4_parent_mask = Address::GetIp4SubnetAddress(addr.to_v4(),
     192           6 :                                                       plen);
     193           0 :     } else if (GetTableType() == Agent::INET6_UNICAST) {
     194           0 :         v6_parent_mask = Address::GetIp6SubnetAddress(addr.to_v6(),
     195           0 :                                                       plen);
     196             :     } else {
     197             :         // skip processing for inet4_mpls table
     198             :         // not expected
     199           0 :         return false;
     200             :     }
     201             : 
     202             : 
     203             :     // Iterate thru all the routes under this subnet and update route flags
     204           6 :     while ((lpm_rt != NULL) && (plen < lpm_rt->prefix_length())) {
     205           0 :         if (GetTableType() == Agent::INET4_UNICAST) {
     206             :             Ip4Address node_mask =
     207           0 :                 Address::GetIp4SubnetAddress(lpm_rt->prefix_address().to_v4(),
     208           0 :                                              plen);
     209           0 :             if (v4_parent_mask != node_mask)
     210           0 :                 break;
     211             : 
     212           0 :         } else if (GetTableType() == Agent::INET6_UNICAST) {
     213             :             Ip6Address node_mask =
     214           0 :                 Address::GetIp6SubnetAddress(lpm_rt->prefix_address().to_v6(),
     215           0 :                                              plen);
     216           0 :             if (v6_parent_mask != node_mask)
     217           0 :                 break;
     218             :         }
     219             : 
     220             :         // Update ipam_host_route_ and proxy_arp_ flags for host-routes
     221           0 :         bool notify = false;
     222           0 :         if (lpm_rt->UpdateIpamHostFlags(val)) {
     223           0 :             notify = true;
     224             :         }
     225             : 
     226           0 :         if (notify) {
     227           0 :             NotifyEntry(lpm_rt);
     228             :         }
     229             : 
     230           0 :         lpm_rt = GetNextNonConst(lpm_rt);
     231             :     }
     232           6 :     return false;
     233             : }
     234             : 
     235             : //Null peer means sync is done on routes.
     236             : //If peer is specified then path belonging to peer will be resync'd
     237             : //Functions in TraverseHostRoutesInSubnet:
     238             : //1) If subnet rt added does not have any supernet then visit all unresolved
     239             : //   routes and resync them.
     240             : //2) If supernet route is present then traverse lpm routes under this newly
     241             : //   added subnet and resync all host routes pointing to supernet route of this
     242             : //   subnet.
     243             : //3) Skip all the host routes present under this subnet belonging to a better
     244             : //   subnet(better subnet is the one which comes under subnet being added).
     245             : //   e.g. 1.1.1.10/24 is a better subnet in 1.1.1.10/16 while supernet can be
     246             : //   1.1.1.0/8
     247             : void
     248          20 : InetUnicastAgentRouteTable::TraverseHostRoutesInSubnet(InetUnicastRouteEntry *rt,
     249             :                                                        const Peer *peer)
     250             : {
     251          20 :     const IpAddress addr = rt->prefix_address();
     252          20 :     uint16_t plen = rt->prefix_length();
     253          20 :     InetUnicastRouteEntry *supernet_rt = GetSuperNetRoute(rt->prefix_address());
     254             : 
     255             :     //If supernet route is NULL, then this is the default route and visit to
     256             :     //unresolved route for resync should suffice.
     257          20 :     if (supernet_rt == NULL) {
     258             :         //Resync all unresolved routes.
     259           0 :         EvaluateUnresolvedRoutes();
     260           0 :         return;
     261             :     }
     262             :     //So suernet route is present and this subnet route is a better route.
     263             :     //Look for all routes which were pointing to supernet route and move them
     264             :     //to this subnet route, if they fall in same subnet.
     265          20 :     IpAddress parent_mask = GetSubnetAddress(addr, plen);
     266          20 :     for (InetUnicastRouteEntry *lpm_rt = GetNextNonConst(rt);
     267          26 :          (lpm_rt != NULL) && (plen < lpm_rt->prefix_length());
     268           6 :          lpm_rt= GetNextNonConst(lpm_rt)) {
     269           6 :         IpAddress node_mask = GetSubnetAddress(lpm_rt->prefix_address(), plen);
     270           6 :         if (parent_mask != node_mask)
     271           0 :             break;
     272             : 
     273             :         //Non host route, lets continue as this route will have its own NH and it
     274             :         //need not be modified.
     275           6 :         if (lpm_rt->IsHostRoute() == false) {
     276           6 :             continue;
     277             :         }
     278             : 
     279             :         //If supernet route of this subnet route is not parent of lpm_rt added,
     280             :         //then skip as its not lpm_rt dependant as well.
     281             :         //There may be some other subnet which is handling it.
     282             :         //e.g. 1.1.0.0/8, 1.1.0.0/16, 1.1.1.0/24, 1.1.1.1, 1.1.0.1
     283             :         //Here parent of 1.1.1.1 will be 1.1.1.0/24 and not 1.1.0.0/16.
     284             :         //So if subnet route getting added is 1.1.0.0/16 in presence of 1.1.1.0/24
     285             :         //then 1.1.1.1 should not be modified.
     286           6 :         if (lpm_rt->GetActivePath()->dependant_rt() != supernet_rt)
     287           6 :             continue;
     288             : 
     289             : 
     290             :         //Proceed only for host route
     291             :         //Resync will ensure that subnet route is added to lpm host route
     292             :         //dependant rt(gw_ip).
     293           0 :         lpm_rt->EnqueueRouteResync();
     294             :     }
     295             : }
     296             : 
     297             : IpAddress
     298          26 : InetUnicastAgentRouteTable::GetSubnetAddress(const IpAddress &addr,
     299             :                                              uint16_t plen) const {
     300          26 :     if (type_ == Agent::INET4_UNICAST) {
     301          23 :         return (Address::GetIp4SubnetAddress(addr.to_v4(), plen));
     302           3 :     } else if (type_ == Agent::INET6_UNICAST) {
     303           3 :         return (Address::GetIp6SubnetAddress(addr.to_v6(), plen));
     304             :     }
     305           0 :     return IpAddress(Ip4Address());
     306             : }
     307             : 
     308             : //Tries searching for subnet route to which this route belongs.
     309             : //Route itself can be a subnet/host. To search for supernet plen is reduced by
     310             : //one and findlpm is issued.
     311             : InetUnicastRouteEntry *
     312         114 : InetUnicastAgentRouteTable::GetSuperNetRoute(const IpAddress &addr) {
     313         114 :     InetUnicastRouteEntry key(NULL, addr, (GetHostPlen(addr) - 1),
     314         114 :                               false);
     315         114 :     InetUnicastRouteEntry *parent_key = FindLPM(key);
     316         114 :     return parent_key;
     317         114 : }
     318             : 
     319             : /////////////////////////////////////////////////////////////////////////////
     320             : // Inet4UnicastAgentRouteEntry functions
     321             : /////////////////////////////////////////////_////////////////////////////////
     322        1261 : InetUnicastRouteEntry::InetUnicastRouteEntry(VrfEntry *vrf,
     323             :                                              const IpAddress &addr,
     324             :                                              uint8_t plen,
     325        1261 :                                              bool is_multicast) :
     326             :     AgentRoute(vrf, is_multicast), AgentRoutePrefix(addr, plen),
     327        1261 :     ipam_subnet_route_(false),
     328        1261 :     ipam_host_route_(false), proxy_arp_(false) {
     329        1261 :         if (addr.is_v4()) {
     330        1037 :         prefix_address_ = Address::GetIp4SubnetAddress(addr.to_v4(), plen);
     331             :     } else {
     332         224 :         prefix_address_ = Address::GetIp6SubnetAddress(addr.to_v6(), plen);
     333             :     }
     334        1261 : }
     335             : 
     336           0 : string InetUnicastRouteKey::ToString() const {
     337           0 :     ostringstream str;
     338           0 :     str << dip_.to_string();
     339           0 :     str << "/";
     340           0 :     str << (int)plen_;
     341           0 :     return str.str();
     342           0 : }
     343             : 
     344         803 : string InetUnicastRouteEntry::ToString() const {
     345         803 :     ostringstream str;
     346         803 :     str << prefix_address_.to_string();
     347         803 :     str << "/";
     348         803 :     str << (int)prefix_length();
     349        1606 :     return str.str();
     350         803 : }
     351             : 
     352             : 
     353         589 : Agent::RouteTableType InetUnicastRouteEntry::GetTableType() const {
     354         589 :     return ((InetUnicastAgentRouteTable *)get_table())->GetTableType();
     355             : }
     356             : 
     357        2618 : int InetUnicastRouteEntry::CompareTo(const Route &rhs) const {
     358        2618 :     const InetUnicastRouteEntry &a =
     359             :         static_cast<const InetUnicastRouteEntry &>(rhs);
     360             : 
     361        2618 :     if (prefix_address_ < a.prefix_address_) {
     362         799 :         return -1;
     363             :     }
     364             : 
     365        1819 :     if (prefix_address_ > a.prefix_address_) {
     366         507 :         return 1;
     367             :     }
     368             : 
     369        1312 :     if (prefix_length() < a.prefix_length()) {
     370           0 :         return -1;
     371             :     }
     372             : 
     373        1312 :     if (prefix_length() > a.prefix_length()) {
     374           0 :         return 1;
     375             :     }
     376             : 
     377        1312 :     return 0;
     378             : }
     379             : 
     380         276 : DBEntryBase::KeyPtr InetUnicastRouteEntry::GetDBRequestKey() const {
     381             :     InetUnicastAgentRouteTable *table =
     382         276 :         (static_cast<InetUnicastAgentRouteTable *>(get_table()));
     383         276 :     Agent *agent = table->agent();
     384         276 :     InetUnicastRouteKey *key = NULL;
     385         276 :     if ((table->GetTableType() == Agent::INET4_MPLS)) {
     386          10 :         key =
     387          10 :         new InetMplsUnicastRouteKey(agent->local_peer(),
     388          10 :                                  vrf()->GetName(), prefix_address_, prefix_length());
     389             :     } else {
     390         266 :         key =
     391         266 :         new InetUnicastRouteKey(agent->local_peer(),
     392         266 :                                  vrf()->GetName(), prefix_address_, prefix_length());
     393             :     }
     394             : 
     395         276 :     return DBEntryBase::KeyPtr(key);
     396             : }
     397             : 
     398           0 : void InetUnicastRouteEntry::SetKey(const DBRequestKey *key) {
     399             :     Agent *agent =
     400           0 :         (static_cast<InetUnicastAgentRouteTable *>(get_table()))->agent();
     401           0 :     const InetUnicastRouteKey *k =
     402             :         static_cast<const InetUnicastRouteKey*>(key);
     403           0 :     SetVrf(agent->vrf_table()->FindVrfFromName(k->vrf_name()));
     404           0 :     IpAddress tmp(k->addr());
     405           0 :     set_addr(tmp);
     406           0 :     set_prefix_length(k->plen());
     407           0 : }
     408             : 
     409         393 : bool InetUnicastRouteEntry::IsHostRoute() const {
     410             :     InetUnicastAgentRouteTable *table =
     411         393 :         static_cast<InetUnicastAgentRouteTable *>(get_table());
     412         393 :     if (table->GetTableType() == Agent::INET4_UNICAST) {
     413         339 :         if (prefix_length() != Address::kMaxV4PrefixLen)
     414          35 :             return false;
     415          54 :     } else if (table->GetTableType() == Agent::INET6_UNICAST) {
     416          48 :         if (prefix_length() != Address::kMaxV6PrefixLen)
     417           6 :             return false;
     418             :     }
     419         352 :     return true;
     420             : }
     421             : 
     422             : /*
     423             :  * This routine finds out if there is supernet for this subnet route and that
     424             :  * is used to inherit flood flag. In case supernet is pointing to resolve i.e.
     425             :  * gateway without having Ipam path, then search continues further
     426             :  */
     427           3 : bool InetUnicastRouteEntry::IpamSubnetRouteAvailable() const {
     428           3 :     return (GetIpamSuperNetRoute() != NULL);
     429             : }
     430             : 
     431             : InetUnicastRouteEntry *
     432           3 : InetUnicastRouteEntry::GetIpamSuperNetRoute() const {
     433           3 :     if (prefix_length() == 0)
     434           1 :         return NULL;
     435             : 
     436             :     //Local path present means that this route itself was programmed
     437             :     //because of IPAM add as well and hence its eligible for flood in
     438             :     //all paths where NH is tunnel.
     439             :     InetUnicastAgentRouteTable *table =
     440           2 :         static_cast<InetUnicastAgentRouteTable *>(get_table());
     441             : 
     442             :     //Search for supernet, if none then dont flood else again search for
     443             :     //local path. If found then mark for flood otherwise check for active path
     444             :     //and retain flood flag from that path.
     445           2 :     uint16_t plen = prefix_length() - 1;
     446           2 :     while (plen != 0) {
     447           2 :         assert(plen < prefix_length());
     448           2 :         InetUnicastRouteEntry key(vrf(), prefix_address_, plen, false);
     449             :         // Find next highest matching route
     450           2 :         InetUnicastRouteEntry *supernet_rt = table->FindRouteUsingKey(key);
     451             : 
     452           2 :         if (supernet_rt == NULL)
     453           1 :             return NULL;
     454             : 
     455           1 :         if (supernet_rt->ipam_subnet_route())
     456           1 :             return supernet_rt;
     457             : 
     458           0 :         plen--;
     459           2 :     }
     460             : 
     461           0 :     return NULL;
     462             : }
     463             : 
     464         169 : bool InetUnicastRouteEntry::ReComputePathAdd(AgentPath *path) {
     465         169 :     bool ret = false;
     466             :     InetUnicastAgentRouteTable *uc_rt_table =
     467         169 :         static_cast<InetUnicastAgentRouteTable *>(get_table());
     468         169 :     if (IsHostRoute() == false)
     469          20 :         uc_rt_table->TraverseHostRoutesInSubnet(this,
     470             :                                                 uc_rt_table->agent()->
     471             :                                                 inet_evpn_peer());
     472             : 
     473         282 :     if (path->nexthop() && path->nexthop()->IsValid() &&
     474         113 :         path->nexthop()->GetType() == NextHop::ARP) {
     475             :         //Add bridge route for IP fabric ARP routes, so that
     476             :         //MAC stitching can be done for VM routes based on corresponding
     477             :         //compute node
     478           0 :         const ArpNH *arp_nh = static_cast<const ArpNH *>(path->nexthop());
     479             :         BridgeAgentRouteTable *table =
     480           0 :             static_cast<BridgeAgentRouteTable *>(vrf()->GetBridgeRouteTable());
     481           0 :         table->AddMacVmBindingRoute(path->peer(), vrf()->GetName(), arp_nh->GetMac(),
     482             :                                     NULL, false);
     483             :     }
     484             : 
     485             :     // ECMP path are managed by route module. Update ECMP path with
     486             :     // addition of new path
     487         169 :     EcmpData ecmp_data(uc_rt_table->agent(), vrf()->GetName(), ToString(),
     488         169 :                        path, false);
     489         169 :     ret |= ecmp_data.Update(this);
     490         169 :     return ret;
     491         169 : }
     492             : 
     493         102 : bool InetUnicastRouteEntry::ReComputePathDeletion(AgentPath *path) {
     494         102 :     if (IsHostRoute() == false) {
     495             :         //TODO merge both evpn inet and subnet routes handling
     496          20 :         UpdateDependantRoutes();
     497             :     }
     498             : 
     499             : 
     500         102 :     if (path->nexthop() && path->nexthop()->GetType() == NextHop::ARP) {
     501             :         const ArpNH *arp_nh =
     502           3 :             static_cast<const ArpNH *>(path->nexthop());
     503             :         BridgeAgentRouteTable *table =
     504           3 :             static_cast<BridgeAgentRouteTable *>(vrf()->GetBridgeRouteTable());
     505           3 :         table->DeleteMacVmBindingRoute(path->peer(), vrf()->GetName(),
     506             :                                        arp_nh->GetMac(), NULL);
     507             :     }
     508             : 
     509             :     InetUnicastAgentRouteTable *uc_rt_table =
     510         102 :         static_cast<InetUnicastAgentRouteTable *>(get_table());
     511             :     //Subnet discard = Ipam subnet route.
     512             :     //Ipam path is getting deleted so all the smaller subnets should be
     513             :     //resynced to remove the arp flood marking.
     514         102 :     if (path->is_subnet_discard()) {
     515             :         // Reset flag on route as ipam is going off.
     516           3 :         UpdateRouteFlags(false, false, false);
     517           3 :         uc_rt_table->ResyncSubnetRoutes(this, false);
     518           3 :         return true;
     519             :     }
     520             :     // ECMP path are managed by route module. Update ECMP path with
     521             :     // deletion of new path
     522          99 :     EcmpData ecmp_data(uc_rt_table->agent(), vrf()->GetName(), ToString(),
     523          99 :                        path, true);
     524          99 :     return ecmp_data.Update(this);
     525          99 : }
     526             : 
     527             : // ipam_host_route_ flag:
     528             : // ipam_host_route_ is set if this is host-route and falls in ipam-subnet range
     529             : //
     530             : // proxy_arp_ flag:
     531             : // For hosts within subnet, we assume ARP must not be proxied and should be
     532             : // flooded instead. If we get EVPN route, in KSYNC the EVPN path processing
     533             : // will take preference and KSYNC will set Proxy flag
     534           3 : bool InetUnicastRouteEntry::UpdateIpamHostFlags(bool ipam_host_route) {
     535             :     // For non-host routes, set proxy always
     536           3 :     if (IsHostRoute() == false) {
     537           1 :         return UpdateRouteFlags(false, false, true);
     538             :     }
     539             : 
     540           2 :     bool proxy_arp = ipam_host_route ? false : true;
     541           2 :     return UpdateRouteFlags(false, ipam_host_route, proxy_arp);
     542             : }
     543             : 
     544          44 : bool InetUnicastRouteEntry::UpdateRouteFlags(bool ipam_subnet_route,
     545             :                                              bool ipam_host_route,
     546             :                                              bool proxy_arp) {
     547          44 :     bool ret = false;
     548          44 :     if (ipam_subnet_route_ != ipam_subnet_route) {
     549           6 :         ipam_subnet_route_ = ipam_subnet_route;
     550           6 :         ret = true;
     551             :     }
     552             : 
     553          44 :     if (ipam_host_route_ != ipam_host_route) {
     554          11 :         ipam_host_route_ = ipam_host_route;
     555          11 :         ret = true;
     556             :     }
     557             : 
     558          44 :     if (proxy_arp_ != proxy_arp) {
     559          24 :         proxy_arp_ = proxy_arp;
     560          24 :         ret = true;
     561             :     }
     562             : 
     563          44 :     return ret;
     564             : }
     565          39 : AgentPath *InetUnicastRouteEntry::FindEvpnPathUsingKeyData
     566             : (const AgentRouteKey *key, const AgentRouteData *data) const {
     567          39 :     const Peer *peer = key->peer();
     568          39 :     const InetEvpnPeer *evpn_peer = dynamic_cast<const InetEvpnPeer*>(peer);
     569          39 :     assert(evpn_peer != NULL);
     570             : 
     571             :     Route::PathList::const_iterator it;
     572         205 :     for (it = GetPathList().begin(); it != GetPathList().end(); it++) {
     573          68 :         const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
     574          68 :         if (path->peer() != key->peer())
     575          43 :             continue;
     576             : 
     577             :         //Handle mac route added via evpn route.
     578             :         const InetEvpnRoutePath *evpn_path =
     579          25 :             dynamic_cast<const InetEvpnRoutePath *>(path);
     580             :         const InetEvpnRouteData *evpn_data =
     581          25 :             dynamic_cast<const InetEvpnRouteData *>(data);
     582          25 :         assert(evpn_path != NULL);
     583          25 :         assert(evpn_data != NULL);
     584          25 :         if (evpn_path->MacAddr() != evpn_data->MacAddr())
     585           1 :             continue;
     586          24 :         return const_cast<AgentPath *>(path);
     587             :     }
     588          15 :     return NULL;
     589             : }
     590         164 : AgentPath *InetUnicastRouteEntry::FindPathUsingKeyData
     591             : (const AgentRouteKey *key, const AgentRouteData *data) const {
     592         164 :     const Peer *peer = key->peer();
     593             :     const InetEvpnPeer *inet_evpn_peer =
     594         164 :         dynamic_cast<const InetEvpnPeer*>(peer);
     595         164 :     if (inet_evpn_peer != NULL)
     596          39 :         return FindEvpnPathUsingKeyData(key, data);
     597             : 
     598         125 :     return FindPath(peer);
     599             : }
     600             : 
     601             : /////////////////////////////////////////////////////////////////////////////
     602             : // AgentRouteData virtual functions
     603             : /////////////////////////////////////////////////////////////////////////////
     604             : 
     605           8 : bool Inet4UnicastArpRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
     606             :                                                  const AgentRoute *rt) {
     607           8 :     bool ret = true;
     608             : 
     609           8 :     ArpNHKey key(vrf_name_, addr_, policy_);
     610             :     NextHop *nh =
     611           8 :         static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
     612           8 :     path->set_unresolved(false);
     613             : 
     614           8 :     if (path->dest_vn_list() != vn_list_) {
     615           3 :         path->set_dest_vn_list(vn_list_);
     616           3 :         ret = true;
     617             :     }
     618             : 
     619           8 :     if (path->sg_list() != sg_list_) {
     620           0 :         path->set_sg_list(sg_list_);
     621           0 :         ret = true;
     622             :     }
     623             : 
     624           8 :     if (path->tag_list() != tag_list_) {
     625           0 :         path->set_tag_list(tag_list_);
     626           0 :         ret = true;
     627             :     }
     628             : 
     629           8 :     if (path->ChangeNH(agent, nh) == true)
     630           3 :         ret = true;
     631             : 
     632           8 :     if (nh) {
     633           8 :         if (path->CopyArpData()) {
     634           4 :             ret = true;
     635             :         }
     636             :     }
     637             : 
     638           8 :     path->set_tunnel_bmap(1 << TunnelType::NATIVE);
     639             : 
     640           8 :     return ret;
     641           8 : }
     642             : 
     643           0 : bool InetUnicastNdpRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
     644             :                                                  const AgentRoute *rt) {
     645           0 :     bool ret = true;
     646             : 
     647           0 :     NdpNHKey key(vrf_name_, addr_, policy_);
     648             :     NextHop *nh =
     649           0 :         static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
     650           0 :     path->set_unresolved(false);
     651             : 
     652           0 :     if (path->dest_vn_list() != vn_list_) {
     653           0 :         path->set_dest_vn_list(vn_list_);
     654           0 :         ret = true;
     655             :     }
     656             : 
     657           0 :     if (path->sg_list() != sg_list_) {
     658           0 :         path->set_sg_list(sg_list_);
     659           0 :         ret = true;
     660             :     }
     661             : 
     662           0 :     if (path->tag_list() != tag_list_) {
     663           0 :         path->set_tag_list(tag_list_);
     664           0 :         ret = true;
     665             :     }
     666             : 
     667           0 :     if (path->ChangeNH(agent, nh) == true)
     668           0 :         ret = true;
     669             : 
     670           0 :     if (nh) {
     671           0 :         if (path->CopyNdpData()) {
     672           0 :             ret = true;
     673             :         }
     674             :     }
     675             : 
     676           0 :     path->set_tunnel_bmap(1 << TunnelType::NATIVE);
     677             : 
     678           0 :     return ret;
     679           0 : }
     680             : 
     681           6 : bool Inet4UnicastGatewayRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
     682             :                                                      const AgentRoute *agent_rt) {
     683           6 :     path->set_vrf_name(vrf_name_);
     684           6 :     NextHop *nh = NULL;
     685           6 :     InetUnicastRouteEntry *rt = NULL;
     686             : 
     687           6 :     if (gw_list_.empty() || gw_list_.size() == 1) { /* SH case */
     688           6 :         InetUnicastAgentRouteTable *table = NULL;
     689             :         table = static_cast<InetUnicastAgentRouteTable *>
     690           6 :             (agent->vrf_table()->GetInet4UnicastRouteTable(vrf_name_));
     691           6 :         IpAddress gw_ip = gw_list_.empty() ? Ip4Address(0) : gw_list_[0];
     692           6 :         rt = table->FindRoute(gw_ip);
     693             :         const NextHop *anh;
     694           6 :         if (rt == NULL || rt->prefix_length() == 0 || (anh = rt->GetActiveNextHop()) == NULL) {
     695           6 :             path->set_unresolved(true);
     696           0 :         } else if (anh->GetType() == NextHop::RESOLVE) {
     697           0 :             const ResolveNH *nh =
     698             :                 static_cast<const ResolveNH *>(anh);
     699           0 :             path->set_unresolved(true);
     700           0 :             std::string nexthop_vrf = nh->get_interface()->vrf()->GetName();
     701           0 :             if (nh->get_interface()->vrf()->forwarding_vrf()) {
     702           0 :                 nexthop_vrf = nh->get_interface()->vrf()->forwarding_vrf()->GetName();
     703             :             }
     704           0 :             InetUnicastAgentRouteTable::AddArpReq(vrf_name_, gw_ip.to_v4(),
     705             :                     nexthop_vrf,
     706           0 :                     nh->get_interface(), nh->PolicyEnabled(),
     707           0 :                     vn_list_, sg_list_, tag_list_);
     708           0 :         } else {
     709           0 :             path->set_unresolved(false);
     710             :         }
     711             :     } else {  /* MH case */
     712             :         CompositeNHKey *comp_key;
     713           0 :         bool comp_nh_policy = false;
     714           0 :         DBRequest nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
     715             : 
     716             :         InetUnicastAgentRouteTable *table = static_cast<InetUnicastAgentRouteTable *>
     717           0 :             (agent->vrf_table()->GetInet4UnicastRouteTable(vrf_name_));
     718             : 
     719           0 :         ComponentNHKeyList comp_nh_list;
     720           0 :         AddressList::const_iterator ptr;
     721           0 :         for (ptr = gw_list_.begin(); ptr < gw_list_.end(); ptr++) {
     722           0 :             InetUnicastRouteEntry *uc_rt = table->FindRoute(*ptr);
     723           0 :             rt = uc_rt;
     724           0 :             if (uc_rt == NULL || uc_rt->prefix_length() == 0) {
     725           0 :                 path->set_unresolved(true);
     726           0 :                 break;
     727           0 :             } else if (uc_rt->GetActiveNextHop()->GetType() == NextHop::RESOLVE) {
     728           0 :                 path->set_unresolved(true);
     729             :                 const ResolveNH *nh =
     730           0 :                     static_cast<const ResolveNH *>(uc_rt->GetActiveNextHop());
     731           0 :                 path->set_unresolved(true);
     732           0 :                 std::string nexthop_vrf = nh->get_interface()->vrf()->GetName();
     733           0 :                 if (nh->get_interface()->vrf()->forwarding_vrf()) {
     734           0 :                     nexthop_vrf = nh->get_interface()->vrf()->forwarding_vrf()->GetName();
     735             :                 }
     736           0 :                 InetUnicastAgentRouteTable::AddArpReq(vrf_name_, *ptr,
     737           0 :                         nexthop_vrf, nh->get_interface(), nh->PolicyEnabled(),
     738           0 :                         vn_list_, sg_list_, tag_list_);
     739           0 :             } else {
     740             :                 DBEntryBase::KeyPtr key =
     741           0 :                     uc_rt->GetActiveNextHop()->GetDBRequestKey();
     742           0 :                 NextHopKey *nh_key = static_cast<NextHopKey *>(key.release());
     743           0 :                 std::unique_ptr<const NextHopKey> nh_key_ptr(nh_key);
     744             :                 ComponentNHKeyPtr component_nh_key(new ComponentNHKey(-1,
     745           0 :                             std::move(nh_key_ptr)));
     746           0 :                 comp_nh_list.push_back(component_nh_key);
     747           0 :             }
     748             :         }
     749             : 
     750           0 :         if (comp_nh_list.size() == gw_list_.size()) {
     751           0 :             path->set_unresolved(false);
     752           0 :             nh_req.key.reset(new CompositeNHKey(Composite::ECMP, comp_nh_policy,
     753           0 :                         comp_nh_list, vrf_name_));
     754           0 :             nh_req.data.reset(new CompositeNHData());
     755             :             comp_key =
     756           0 :                 static_cast<CompositeNHKey *>(nh_req.key.get());
     757           0 :             nh = static_cast<NextHop *>(agent->nexthop_table()->
     758           0 :                     FindActiveEntry(comp_key));
     759           0 :             if (!nh) {
     760           0 :                 agent->nexthop_table()->Process(nh_req);
     761           0 :                 nh = static_cast<NextHop *>(agent->nexthop_table()->
     762           0 :                         FindActiveEntry(comp_key));
     763             :             }
     764             :         }
     765           0 :     }
     766             : 
     767           6 :     if (path->label() != mpls_label_) {
     768           0 :         path->set_label(mpls_label_);
     769             :     }
     770             : 
     771           6 :     if (agent->is_l3mh() == false) {
     772           6 :         path->set_nexthop(nh);
     773             :     }
     774             : 
     775           6 :     SecurityGroupList path_sg_list;
     776           6 :     path_sg_list = path->sg_list();
     777           6 :     if (path_sg_list != sg_list_) {
     778           0 :         path->set_sg_list(sg_list_);
     779             :     }
     780             : 
     781           6 :     TagList path_tag_list;
     782           6 :     path_tag_list = path->tag_list();
     783           6 :     if (path_tag_list != tag_list_) {
     784           0 :         path->set_tag_list(tag_list_);
     785             :     }
     786             : 
     787           6 :     CommunityList path_communities;
     788           6 :     path_communities = path->communities();
     789           6 :     if (path_communities != communities_) {
     790           0 :         path->set_communities(communities_);
     791             :     }
     792             : 
     793             :     //Reset to new gateway route, no nexthop for indirect route
     794           6 :     if (agent->is_l3mh() == false) {
     795           6 :         IpAddress gw_ip = gw_list_.empty() ? Ip4Address(0) : gw_list_[0];
     796           6 :         path->set_gw_ip(gw_ip);
     797           6 :         path->ResetDependantRoute(rt);
     798             :     }
     799             : 
     800           6 :     if (rt) {
     801           6 :         path->set_tunnel_bmap(rt->GetActivePath()->tunnel_bmap());
     802             :     }
     803             : 
     804           6 :     if (native_encap_) {
     805           6 :         path->set_tunnel_bmap(path->tunnel_bmap() | (1 << TunnelType::NATIVE));
     806             :     }
     807             : 
     808           6 :     if (path->dest_vn_list() != vn_list_) {
     809           6 :         path->set_dest_vn_list(vn_list_);
     810             :     }
     811             : 
     812           6 :     if (agent->is_l3mh() && (path->unresolved() == false) &&
     813           0 :             path->ChangeNH(agent, nh) == true) {
     814           0 :         return true;
     815             :     }
     816             : 
     817           6 :     return true;
     818           6 : }
     819             : 
     820          15 : InetEvpnRoutePath::InetEvpnRoutePath(const Peer *peer,
     821             :                                      const MacAddress& mac,
     822             :                                      const std::string& parent,
     823          15 :                                      AgentRoute *rt) :
     824          15 :     AgentPath(peer, rt), mac_(mac), parent_(parent) {
     825          15 : }
     826             : 
     827           9 : const AgentPath *InetEvpnRoutePath::UsablePath() const {
     828             :     //In InetEvpnRoutePath nexthop will always be NULL.
     829             :     //Valid NH is dependant on parent route(subnet).
     830           9 :     if (dependant_rt()) {
     831           0 :         const AgentPath *path = dependant_rt()->GetActivePath();
     832           0 :         if (path != NULL)
     833           0 :             return path;
     834             :     }
     835           9 :     return this;
     836             : }
     837             : 
     838          94 : bool InetEvpnRoutePath::SyncDependantRoute(const AgentRoute *sync_route) {
     839             :     const InetUnicastRouteEntry *dependant_route =
     840          94 :         dynamic_cast<const InetUnicastRouteEntry *>(dependant_rt());
     841             :     InetUnicastAgentRouteTable *table =
     842          94 :         static_cast<InetUnicastAgentRouteTable *>(sync_route->get_table());
     843             :     InetUnicastRouteEntry *parent_subnet_route =
     844          94 :         table->GetSuperNetRoute(dynamic_cast<const InetUnicastRouteEntry *>
     845         188 :                                 (sync_route)->prefix_address());
     846             : 
     847          94 :     if (parent_subnet_route != dependant_route) {
     848          18 :         set_gw_ip(parent_subnet_route ? parent_subnet_route->prefix_address() :
     849             :                   IpAddress());
     850          18 :         if (parent_subnet_route) {
     851          11 :             ResetDependantRoute(parent_subnet_route);
     852          11 :             set_unresolved(false);
     853             :         } else {
     854             :             //Clear old dependant route
     855           7 :             ClearDependantRoute();
     856           7 :             set_unresolved(true);
     857             :         }
     858          18 :         return true;
     859             :     }
     860          76 :     return false;
     861             : }
     862             : 
     863          55 : bool InetEvpnRoutePath::Sync(AgentRoute *sync_route) {
     864          55 :     return SyncDependantRoute(sync_route);
     865             : }
     866             : 
     867          54 : const NextHop* InetEvpnRoutePath::ComputeNextHop(Agent *agent) const {
     868             :     //InetEvpnRoutePath is deleted when parent evpn route is going off.
     869             :     //Now it may happen that supernet route which was used as dependant_rt in
     870             :     //this path has been deleted.
     871          73 :     if ((dependant_rt() == NULL) ||
     872          19 :         (dependant_rt()->GetActiveNextHop() == NULL)) {
     873          35 :         DiscardNH key;
     874          35 :         return static_cast<NextHop *>
     875          35 :             (agent->nexthop_table()->FindActiveEntry(&key));
     876          35 :     }
     877             : 
     878          19 :     return AgentPath::ComputeNextHop(agent);
     879             : }
     880             : 
     881         144 : bool InetEvpnRoutePath::IsLess(const AgentPath &r_path) const {
     882         144 :     const InetEvpnRoutePath *r_evpn_path =
     883         144 :         dynamic_cast<const InetEvpnRoutePath *>(&r_path);
     884         144 :     if (r_evpn_path != NULL) {
     885           8 :         if (r_evpn_path->MacAddr() != mac_) {
     886           8 :             return (mac_ < r_evpn_path->MacAddr());
     887             :         }
     888             :     }
     889             : 
     890         136 :     return peer()->IsLess(r_path.peer());
     891             : }
     892          70 : InetEvpnRouteData::InetEvpnRouteData(const EvpnRouteEntry *evpn_rt):
     893             :     AgentRouteData(AgentRouteData::ADD_DEL_CHANGE,
     894          70 :                  evpn_rt->is_multicast(), 0),
     895          70 :     mac_(evpn_rt->mac()) {
     896          70 :     std::stringstream s;
     897          70 :     s << evpn_rt->ToString();
     898          70 :     s << " ";
     899          70 :     parent_ = s.str();
     900          70 : }
     901             : 
     902          15 : AgentPath *InetEvpnRouteData::CreateAgentPath(const Peer *peer,
     903             :                                               AgentRoute *rt) const {
     904          15 :     return (new InetEvpnRoutePath(peer, mac_, parent_, rt));
     905             : }
     906             : 
     907          39 : bool InetEvpnRouteData::AddChangePathExtended(Agent *agent,
     908             :                                               AgentPath *path,
     909             :                                               const AgentRoute *route) {
     910          39 :     return dynamic_cast<InetEvpnRoutePath *>(path)->SyncDependantRoute(route);
     911             : }
     912             : 
     913          13 : bool InetEvpnRouteData::CanDeletePath(Agent *agent, AgentPath *path,
     914             :                                         const AgentRoute *rt) const {
     915             :     const InetEvpnRoutePath *evpn_path =
     916          13 :         dynamic_cast<const InetEvpnRoutePath *>(path);
     917          13 :     if (evpn_path == NULL) {
     918           0 :         return true;
     919             :     }
     920          13 :     return (evpn_path->MacAddr() == MacAddr());
     921             : }
     922             : 
     923           0 : Inet4UnicastInterfaceRoute::Inet4UnicastInterfaceRoute
     924           0 : (const PhysicalInterface *intrface, const std::string &vn_name) :
     925             :         AgentRouteData(AgentRouteData::ADD_DEL_CHANGE, false, 0),
     926           0 :         interface_key_(new PhysicalInterfaceKey(intrface->name())),
     927           0 :         vn_name_(vn_name) {
     928           0 : }
     929             : 
     930           0 : bool Inet4UnicastInterfaceRoute::AddChangePathExtended(Agent *agent, AgentPath *path,
     931             :                                                        const AgentRoute *rt) {
     932           0 :     bool ret = false;
     933             : 
     934           0 :     path->set_unresolved(false);
     935           0 :     VnListType vn_list;
     936           0 :     vn_list.insert(agent->fabric_vn_name());
     937           0 :     if (path->dest_vn_list() != vn_list) {
     938           0 :         path->set_dest_vn_list(vn_list);
     939           0 :         ret = true;
     940             :     }
     941             : 
     942           0 :     Interface *intf = static_cast<Interface *>(
     943           0 :             agent->interface_table()->FindActiveEntry(interface_key_.get()));
     944           0 :     assert(intf);
     945           0 :     InterfaceNHKey key(interface_key_->Clone(), false,
     946           0 :                        InterfaceNHFlags::INET4, intf->mac());
     947           0 :     NextHop *nh = static_cast<NextHop *>
     948           0 :         (agent->nexthop_table()->FindActiveEntry(&key));
     949           0 :     assert(nh);
     950           0 :     if (path->ChangeNH(agent, nh) == true) {
     951           0 :         ret = true;
     952             :     }
     953             : 
     954           0 :     return ret;
     955           0 : }
     956             : 
     957             : /////////////////////////////////////////////////////////////////////////////
     958             : // Sandesh functions
     959             : /////////////////////////////////////////////////////////////////////////////
     960             : 
     961           0 : bool InetUnicastRouteEntry::DBEntrySandesh(Sandesh *sresp, bool stale) const {
     962             : 
     963           0 :     RouteUcSandeshData data;
     964           0 :     data.set_src_ip(prefix_address_.to_string());
     965           0 :     data.set_src_plen(prefix_length());
     966           0 :     data.set_ipam_subnet_route(ipam_subnet_route_);
     967           0 :     data.set_ipam_host_route(ipam_host_route_);
     968           0 :     data.set_proxy_arp(proxy_arp_);
     969           0 :     data.set_src_vrf(vrf()->GetName());
     970           0 :     data.set_multicast(AgentRoute::is_multicast());
     971           0 :     data.set_intf_route_type(AgentRoute::intf_route_type());
     972           0 :     for (Route::PathList::const_iterator it = GetPathList().begin();
     973           0 :          it != GetPathList().end(); it++) {
     974           0 :         const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
     975           0 :         if (path) {
     976           0 :             PathSandeshData pdata;
     977           0 :             path->SetSandeshData(pdata);
     978           0 :             if (vrf()->GetName() == Agent::GetInstance()->fabric_vrf_name()
     979           0 :                 && (path->tunnel_bmap() & TunnelType::NativeType())) {
     980           0 :                 pdata.set_active_tunnel_type("Native");
     981             :             }
     982           0 :             data.path_list.push_back(pdata);
     983           0 :         }
     984             :     }
     985             : 
     986           0 :     if (prefix_address_.is_v4()) {
     987           0 :         Inet4UcRouteResp *v4_resp = static_cast<Inet4UcRouteResp *>(sresp);
     988             :         std::vector<RouteUcSandeshData> &list =
     989           0 :         const_cast<std::vector<RouteUcSandeshData>&>(v4_resp->get_route_list());
     990           0 :         list.push_back(data);
     991             :     } else {
     992           0 :         Inet6UcRouteResp *v6_resp = static_cast<Inet6UcRouteResp *>(sresp);
     993             :         std::vector<RouteUcSandeshData> &list =
     994           0 :         const_cast<std::vector<RouteUcSandeshData>&>(v6_resp->get_route_list());
     995           0 :         list.push_back(data);
     996             :     }
     997           0 :     return true;
     998           0 : }
     999             : 
    1000           0 : bool InetUnicastRouteEntry::DBEntrySandesh(Sandesh *sresp, IpAddress addr,
    1001             :                                             uint8_t plen, bool stale) const {
    1002           0 :     if (prefix_address_ == addr && prefix_length() == plen) {
    1003           0 :         return DBEntrySandesh(sresp, stale);
    1004             :     }
    1005             : 
    1006           0 :     return false;
    1007             : }
    1008             : 
    1009           0 : void UnresolvedRoute::HandleRequest() const {
    1010           0 :     VrfEntry *vrf = Agent::GetInstance()->vrf_table()->FindVrfFromId(0);
    1011           0 :     if (!vrf) {
    1012           0 :         ErrorResp *resp = new ErrorResp();
    1013           0 :         resp->set_context(context());
    1014           0 :         resp->Response();
    1015           0 :         return;
    1016             :     }
    1017             : 
    1018           0 :     int count = 0;
    1019           0 :     Inet4UcRouteResp *resp = new Inet4UcRouteResp();
    1020             : 
    1021             :     //TODO - Convert inet4ucroutetable to agentroutetable
    1022             :     AgentRouteTable *rt_table = static_cast<AgentRouteTable *>
    1023           0 :         (vrf->GetInet4UnicastRouteTable());
    1024           0 :     InetUnicastAgentRouteTable::UnresolvedRouteTree::const_iterator it;
    1025           0 :     it = rt_table->unresolved_route_begin();
    1026           0 :     for (;it != rt_table->unresolved_route_end(); it++) {
    1027           0 :         count++;
    1028           0 :         const AgentRoute *rt = *it;
    1029           0 :         rt->DBEntrySandesh(resp, false);
    1030           0 :         if (count == 1) {
    1031           0 :             resp->set_context(context()+"$");
    1032           0 :             resp->Response();
    1033           0 :             count = 0;
    1034           0 :             resp = new Inet4UcRouteResp();
    1035             :         }
    1036             :     }
    1037             : 
    1038           0 :     resp->set_context(context());
    1039           0 :     resp->Response();
    1040           0 :     return;
    1041             : }
    1042             : 
    1043           0 : void Inet4UcRouteReq::HandleRequest() const {
    1044             :     VrfEntry *vrf =
    1045           0 :         Agent::GetInstance()->vrf_table()->FindVrfFromId(get_vrf_index());
    1046           0 :     if (!vrf) {
    1047           0 :         ErrorResp *resp = new ErrorResp();
    1048           0 :         resp->set_context(context());
    1049           0 :         resp->Response();
    1050           0 :         return;
    1051             :     }
    1052             : 
    1053           0 :     AgentSandeshPtr sand;
    1054           0 :     if (get_src_ip().empty()) {
    1055           0 :         sand.reset(new AgentInet4UcRtSandesh(vrf, context(), get_stale()));
    1056             :     } else {
    1057           0 :         boost::system::error_code ec;
    1058           0 :         Ip4Address src_ip = Ip4Address::from_string(get_src_ip(), ec);
    1059           0 :         sand.reset(new AgentInet4UcRtSandesh(vrf, context(), src_ip,
    1060           0 :                                              (uint8_t)get_prefix_len(),
    1061           0 :                                              get_stale()));
    1062             :     }
    1063           0 :     sand->DoSandesh(sand);
    1064           0 : }
    1065             : 
    1066           0 : void Inet4MplsUcRouteReq::HandleRequest() const {
    1067             :     VrfEntry *vrf =
    1068           0 :         Agent::GetInstance()->vrf_table()->FindVrfFromId(get_vrf_index());
    1069           0 :     if (!vrf) {
    1070           0 :         ErrorResp *resp = new ErrorResp();
    1071           0 :         resp->set_context(context());
    1072           0 :         resp->Response();
    1073           0 :         return;
    1074             :     }
    1075             : 
    1076           0 :     AgentSandeshPtr sand;
    1077           0 :     if (get_src_ip().empty()) {
    1078           0 :         sand.reset(new AgentInet4MplsUcRtSandesh(vrf, context(), get_stale()));
    1079             :     } else {
    1080           0 :         boost::system::error_code ec;
    1081           0 :         Ip4Address src_ip = Ip4Address::from_string(get_src_ip(), ec);
    1082           0 :         sand.reset(new AgentInet4MplsUcRtSandesh(vrf, context(), src_ip,
    1083           0 :                                              (uint8_t)get_prefix_len(),
    1084           0 :                                              get_stale()));
    1085             :     }
    1086           0 :     sand->DoSandesh(sand);
    1087           0 : }
    1088             : 
    1089           0 : AgentSandeshPtr InetUnicastAgentRouteTable::GetAgentSandesh
    1090             : (const AgentSandeshArguments *args, const std::string &context) {
    1091           0 :     if (type_ == Agent::INET4_UNICAST) {
    1092           0 :         return AgentSandeshPtr(new AgentInet4UcRtSandesh(vrf_entry(), context,
    1093           0 :                                                          false));
    1094           0 :     } else if (type_ == Agent::INET4_MPLS) {
    1095           0 :         return AgentSandeshPtr(new AgentInet4MplsUcRtSandesh(vrf_entry(), context,
    1096           0 :                                                          false));
    1097             :     } else {
    1098           0 :         return AgentSandeshPtr(new AgentInet6UcRtSandesh(vrf_entry(), context,
    1099           0 :                                                          false));
    1100             :     }
    1101             : }
    1102             : 
    1103           0 : void Inet6UcRouteReq::HandleRequest() const {
    1104             :     VrfEntry *vrf =
    1105           0 :         Agent::GetInstance()->vrf_table()->FindVrfFromId(get_vrf_index());
    1106           0 :     if (!vrf) {
    1107           0 :         ErrorResp *resp = new ErrorResp();
    1108           0 :         resp->set_context(context());
    1109           0 :         resp->Response();
    1110           0 :         return;
    1111             :     }
    1112             : 
    1113           0 :     AgentSandeshPtr sand;
    1114           0 :     if (get_src_ip().empty()) {
    1115           0 :         sand.reset(new AgentInet6UcRtSandesh(vrf, context(), get_stale()));
    1116             :     } else {
    1117           0 :         boost::system::error_code ec;
    1118           0 :         Ip6Address src_ip = Ip6Address::from_string(get_src_ip(), ec);
    1119           0 :         sand.reset(new AgentInet6UcRtSandesh(vrf, context(), src_ip,
    1120           0 :                                              (uint8_t)get_prefix_len(),
    1121           0 :                                              get_stale()));
    1122             :     }
    1123           0 :     sand->DoSandesh(sand);
    1124           0 : }
    1125             : 
    1126             : /////////////////////////////////////////////////////////////////////////////
    1127             : // Helper functions to enqueue request or process inline
    1128             : /////////////////////////////////////////////////////////////////////////////
    1129             : 
    1130             : // Request to delete an entry
    1131             : void
    1132         118 : InetUnicastAgentRouteTable::DeleteReq(const Peer *peer, const string &vrf_name,
    1133             :                                       const IpAddress &addr, uint8_t plen,
    1134             :                                       AgentRouteData *data) {
    1135         118 :     DBRequest req(DBRequest::DB_ENTRY_DELETE);
    1136         118 :     req.key.reset(new InetUnicastRouteKey(peer, vrf_name, addr, plen));
    1137         118 :     req.data.reset(data);
    1138         118 :     InetUnicastTableEnqueue(Agent::GetInstance(), vrf_name, &req);
    1139             : 
    1140         118 : }
    1141             : 
    1142             : // Inline delete request
    1143             : void
    1144          84 : InetUnicastAgentRouteTable::Delete(const Peer *peer, const string &vrf_name,
    1145             :                                    const IpAddress &addr, uint8_t plen) {
    1146          84 :     DBRequest req(DBRequest::DB_ENTRY_DELETE);
    1147          84 :     req.key.reset(new InetUnicastRouteKey(peer, vrf_name, addr, plen));
    1148          84 :     req.data.reset(NULL);
    1149          84 :     InetUnicastTableProcess(Agent::GetInstance(), vrf_name, req);
    1150          84 : }
    1151             : 
    1152             : void
    1153           0 : InetUnicastAgentRouteTable::Delete(const Peer *peer, const string &vrf_name,
    1154             :                                    const IpAddress &addr, uint8_t plen,
    1155             :                                    AgentRouteData *data) {
    1156           0 :     DBRequest req(DBRequest::DB_ENTRY_DELETE);
    1157           0 :     req.key.reset(new InetUnicastRouteKey(peer, vrf_name, addr, plen));
    1158           0 :     req.data.reset(data);
    1159           0 :     InetUnicastTableProcess(Agent::GetInstance(), vrf_name, req);
    1160           0 : }
    1161             : 
    1162             : void
    1163           0 : InetUnicastAgentRouteTable::DeleteMplsRouteReq(const Peer *peer, const string &vrf_name,
    1164             :                                       const IpAddress &addr, uint8_t plen,
    1165             :                                       AgentRouteData *data) {
    1166           0 :     DBRequest req(DBRequest::DB_ENTRY_DELETE);
    1167           0 :     req.key.reset(new InetMplsUnicastRouteKey(peer, vrf_name, addr, plen));
    1168           0 :     req.data.reset(data);
    1169           0 :     Inet4MplsUnicastTableEnqueue(Agent::GetInstance(),  &req);
    1170           0 : }
    1171             : 
    1172             : // Utility function to create a route to trap packets to agent.
    1173             : // Assumes that Interface-NH for "HOST Interface" is already present
    1174             : void
    1175          15 : InetUnicastAgentRouteTable::AddHostRoute(const string &vrf_name,
    1176             :                                          const IpAddress &addr,
    1177             :                                          uint8_t plen,
    1178             :                                          const std::string &dest_vn_name,
    1179             :                                          bool policy) {
    1180          15 :     Agent *agent = Agent::GetInstance();
    1181          15 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1182          30 :     req.key.reset(new InetUnicastRouteKey(agent->local_peer(), vrf_name,
    1183          15 :                                            addr, plen));
    1184             : 
    1185           0 :     PacketInterfaceKey intf_key(boost::uuids::nil_uuid(),
    1186          15 :                                 agent->GetHostInterfaceName());
    1187          15 :     HostRoute *data = new HostRoute(intf_key, dest_vn_name);
    1188          15 :     data->set_policy(policy);
    1189          15 :     req.data.reset(data);
    1190             : 
    1191          15 :     InetUnicastTableEnqueue(Agent::GetInstance(), vrf_name, &req);
    1192          15 : }
    1193             : 
    1194             : // Create Route with VLAN NH
    1195             : void
    1196           0 : InetUnicastAgentRouteTable::AddVlanNHRouteReq(const Peer *peer,
    1197             :                                               const string &vm_vrf,
    1198             :                                               const IpAddress &addr,
    1199             :                                               uint8_t plen,
    1200             :                                               VlanNhRoute *data) {
    1201           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1202           0 :     req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen));
    1203           0 :     req.data.reset(data);
    1204           0 :     InetUnicastTableEnqueue(Agent::GetInstance(), vm_vrf, &req);
    1205           0 : }
    1206             : 
    1207             : void
    1208           0 : InetUnicastAgentRouteTable::AddVlanNHRouteReq(const Peer *peer,
    1209             :                                               const string &vm_vrf,
    1210             :                                               const IpAddress &addr,
    1211             :                                               uint8_t plen,
    1212             :                                               const boost::uuids::uuid &intf_uuid,
    1213             :                                               uint16_t tag,
    1214             :                                               uint32_t label,
    1215             :                                               const VnListType &dest_vn_list,
    1216             :                                               const SecurityGroupList &sg_list,
    1217             :                                               const TagList &tag_list,
    1218             :                                               const PathPreference
    1219             :                                               &path_preference) {
    1220           0 :     VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf_uuid, "");
    1221             :     VlanNhRoute *data = new VlanNhRoute(intf_key, tag, label, dest_vn_list,
    1222             :                                         sg_list, tag_list, path_preference,
    1223           0 :                                         peer->sequence_number());
    1224           0 :     AddVlanNHRouteReq(peer, vm_vrf, addr, plen, data);
    1225           0 : }
    1226             : 
    1227             : // Create Route with VLAN NH
    1228             : void
    1229           0 : InetUnicastAgentRouteTable::AddVlanNHRoute(const Peer *peer,
    1230             :                                            const string &vm_vrf,
    1231             :                                            const IpAddress &addr,
    1232             :                                            uint8_t plen,
    1233             :                                            const boost::uuids::uuid &intf_uuid,
    1234             :                                            uint16_t tag,
    1235             :                                            uint32_t label,
    1236             :                                            const VnListType &dest_vn_list,
    1237             :                                            const SecurityGroupList &sg_list,
    1238             :                                            const TagList &tag_list,
    1239             :                                            const PathPreference
    1240             :                                            &path_preference) {
    1241           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1242           0 :     req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen));
    1243             : 
    1244           0 :     VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf_uuid, "");
    1245           0 :     req.data.reset(new VlanNhRoute(intf_key, tag, label, dest_vn_list,
    1246             :                                    sg_list, tag_list, path_preference,
    1247           0 :                                    peer->sequence_number()));
    1248           0 :     InetUnicastTableProcess(Agent::GetInstance(), vm_vrf, req);
    1249           0 : }
    1250             : 
    1251             : void
    1252          24 : InetUnicastAgentRouteTable::AddLocalVmRouteReq(const Peer *peer,
    1253             :                                                const string &vm_vrf,
    1254             :                                                const IpAddress &addr,
    1255             :                                                uint8_t plen,
    1256             :                                                LocalVmRoute *data) {
    1257          24 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1258          24 :     req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen));
    1259             : 
    1260          24 :     req.data.reset(data);
    1261             : 
    1262          24 :     InetUnicastTableEnqueue(Agent::GetInstance(), vm_vrf, &req);
    1263          24 : }
    1264             : 
    1265             : void
    1266          24 : InetUnicastAgentRouteTable::AddLocalVmRouteReq(const Peer *peer,
    1267             :                                                const string &vm_vrf,
    1268             :                                                const IpAddress &addr,
    1269             :                                                uint8_t plen,
    1270             :                                                const boost::uuids::uuid &intf_uuid,
    1271             :                                                const VnListType &vn_list,
    1272             :                                                uint32_t label,
    1273             :                                                const SecurityGroupList &sg_list,
    1274             :                                                const TagList &tag_list,
    1275             :                                                const CommunityList &communities,
    1276             :                                                bool force_policy,
    1277             :                                                const PathPreference
    1278             :                                                &path_preference,
    1279             :                                                const IpAddress &subnet_service_ip,
    1280             :                                                const EcmpLoadBalance &ecmp_load_balance,
    1281             :                                                bool is_local,
    1282             :                                                bool is_health_check_service,
    1283             :                                                bool native_encap,
    1284             :                                                const std::string &intf_name,
    1285             :                                                bool is_learnt_route)
    1286             : {
    1287          24 :     VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf_uuid, intf_name);
    1288             :     LocalVmRoute *data = new LocalVmRoute(intf_key, label,
    1289             :                                     VxLanTable::kInvalidvxlan_id, force_policy,
    1290             :                                     vn_list, InterfaceNHFlags::INET4, sg_list,
    1291             :                                     tag_list, communities, path_preference,
    1292             :                                     subnet_service_ip, ecmp_load_balance,
    1293             :                                     is_local, is_health_check_service,
    1294          24 :                                     peer->sequence_number(),
    1295          24 :                                     false, native_encap);
    1296             : 
    1297          24 :     AddLocalVmRouteReq(peer, vm_vrf, addr, plen, data);
    1298          24 : }
    1299             : 
    1300           5 : void InetUnicastAgentRouteTable::ResyncRoute(const Peer *peer,
    1301             :                                              const string &vrf,
    1302             :                                              const IpAddress &addr,
    1303             :                                              uint8_t plen) {
    1304           5 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1305             : 
    1306           5 :     InetUnicastRouteKey *key = new InetUnicastRouteKey(peer, vrf, addr, plen);
    1307           5 :     key->sub_op_ = AgentKey::RESYNC;
    1308           5 :     req.key.reset(key);
    1309           5 :     req.data.reset(NULL);
    1310           5 :     InetUnicastTableEnqueue(Agent::GetInstance(), vrf, &req);
    1311           5 : }
    1312             : 
    1313             : void
    1314           0 : InetUnicastAgentRouteTable::AddClonedLocalPathReq(const Peer *peer,
    1315             :                                                   const string &vm_vrf,
    1316             :                                                   const IpAddress &addr,
    1317             :                                                   uint8_t plen,
    1318             :                                                   ClonedLocalPath *data) {
    1319           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1320           0 :     req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen));
    1321           0 :     req.data.reset(data);
    1322           0 :     InetUnicastTableEnqueue(Agent::GetInstance(), vm_vrf, &req);
    1323           0 : }
    1324             : 
    1325             : // Create Route for a local VM
    1326             : // Assumes that Interface-NH for "VM Port" is already present
    1327             : void
    1328          29 : InetUnicastAgentRouteTable::AddLocalVmRoute(const Peer *peer,
    1329             :                                             const string &vm_vrf,
    1330             :                                             const IpAddress &addr,
    1331             :                                             uint8_t plen,
    1332             :                                             const boost::uuids::uuid &intf_uuid,
    1333             :                                             const VnListType &vn_list,
    1334             :                                             uint32_t label,
    1335             :                                             const SecurityGroupList &sg_list,
    1336             :                                             const TagList &tag_list,
    1337             :                                             const CommunityList &communities,
    1338             :                                             bool force_policy,
    1339             :                                             const PathPreference
    1340             :                                             &path_preference,
    1341             :                                             const IpAddress &subnet_service_ip,
    1342             :                                             const EcmpLoadBalance &ecmp_load_balance,
    1343             :                                             bool is_local,
    1344             :                                             bool is_health_check_service,
    1345             :                                             const std::string &intf_name,
    1346             :                                             bool native_encap,
    1347             :                                             const std::string &intf_route_type,
    1348             :                                             bool is_learnt_route)
    1349             : {
    1350          29 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1351          29 :     req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen));
    1352             : 
    1353          29 :     VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf_uuid, intf_name);
    1354          29 :     req.data.reset(new LocalVmRoute(intf_key, label, VxLanTable::kInvalidvxlan_id,
    1355             :                                     force_policy, vn_list,
    1356             :                                     InterfaceNHFlags::INET4, sg_list, tag_list,
    1357             :                                     communities, path_preference,
    1358             :                                     subnet_service_ip,
    1359             :                                     ecmp_load_balance, is_local,
    1360             :                                     is_health_check_service,
    1361          29 :                                     peer->sequence_number(), false, native_encap,
    1362             :                                     intf_route_type,
    1363          29 :                                     is_learnt_route));
    1364          29 :     InetUnicastTableProcess(Agent::GetInstance(), vm_vrf, req);
    1365          29 : }
    1366             : 
    1367             : void
    1368           4 : InetUnicastAgentRouteTable::AddRemoteVmRouteReq(const Peer *peer,
    1369             :                                                 const string &vm_vrf,
    1370             :                                                 const IpAddress &vm_addr,
    1371             :                                                 uint8_t plen,
    1372             :                                                 AgentRouteData *data) {
    1373           4 :     if (Agent::GetInstance()->simulate_evpn_tor())
    1374           0 :         return;
    1375           4 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1376           4 :     req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, vm_addr, plen));
    1377           4 :     req.data.reset(data);
    1378           4 :     InetUnicastTableEnqueue(Agent::GetInstance(), vm_vrf, &req);
    1379           4 : }
    1380             : 
    1381             : void
    1382           6 : InetUnicastAgentRouteTable::AddArpReq(const string &route_vrf_name,
    1383             :                                       const Ip4Address &ip,
    1384             :                                       const string &nexthop_vrf_name,
    1385             :                                       const Interface *intf, bool policy,
    1386             :                                       const VnListType &vn_list,
    1387             :                                       const SecurityGroupList &sg_list,
    1388             :                                       const TagList &tag_list) {
    1389           6 :     Agent *agent = Agent::GetInstance();
    1390           6 :     ArpNHKey key(route_vrf_name, ip, policy);
    1391             :     NextHop *nh =
    1392           6 :         static_cast<NextHop *>(agent->nexthop_table()->FindActiveEntry(&key));
    1393           6 :     if (!nh) {
    1394           6 :         DBRequest  nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1395           6 :         nh_req.key.reset(new ArpNHKey(route_vrf_name, ip, policy));
    1396           6 :         nh_req.data.reset(new ArpNHData(
    1397          12 :                     static_cast<InterfaceKey *>(intf->GetDBRequestKey().release())));
    1398           6 :         agent->nexthop_table()->Enqueue(&nh_req);
    1399           6 :     }
    1400           6 :     DBRequest  rt_req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1401          12 :     rt_req.key.reset(new InetUnicastRouteKey(agent->local_peer(),
    1402           6 :                                               route_vrf_name, ip, 32));
    1403           6 :     rt_req.data.reset(new Inet4UnicastArpRoute(nexthop_vrf_name, ip, policy,
    1404           6 :                                                vn_list, sg_list, tag_list));
    1405           6 :     Inet4UnicastTableEnqueue(agent, &rt_req);
    1406           6 : }
    1407             : 
    1408             : void
    1409           3 : InetUnicastAgentRouteTable::ArpRoute(DBRequest::DBOperation op,
    1410             :                                      const string &route_vrf_name,
    1411             :                                      const Ip4Address &ip,
    1412             :                                      const MacAddress &mac,
    1413             :                                      const string &nexthop_vrf_name,
    1414             :                                      const Interface &intf,
    1415             :                                      bool resolved,
    1416             :                                      const uint8_t plen,
    1417             :                                      bool policy,
    1418             :                                      const VnListType &vn_list,
    1419             :                                      const SecurityGroupList &sg,
    1420             :                                      const TagList &tag) {
    1421           3 :     Agent *agent = Agent::GetInstance();
    1422           3 :     DBRequest  nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1423           3 :     ArpNHKey *nh_key = new ArpNHKey(nexthop_vrf_name, ip, policy);
    1424           3 :     if (op == DBRequest::DB_ENTRY_DELETE) {
    1425             :         //In case of delete we want to set the
    1426             :         //nexthop as invalid, hence use resync operation
    1427             :         //We dont want the nexthop to created again
    1428             :         //in case of duplicate delete
    1429           1 :         nh_key->sub_op_ = AgentKey::RESYNC;
    1430             :     }
    1431           3 :     nh_req.key.reset(nh_key);
    1432             :     ArpNHData *arp_data = new ArpNHData(mac,
    1433           3 :                static_cast<InterfaceKey *>(intf.GetDBRequestKey().release()),
    1434           3 :                resolved);
    1435           3 :     nh_req.data.reset(arp_data);
    1436             : 
    1437           3 :     DBRequest  rt_req(op);
    1438             :     InetUnicastRouteKey *rt_key =
    1439           3 :         new InetUnicastRouteKey(agent->local_peer(), route_vrf_name, ip, plen);
    1440           3 :     Inet4UnicastArpRoute *data = NULL;
    1441             : 
    1442           3 :     switch(op) {
    1443           2 :     case DBRequest::DB_ENTRY_ADD_CHANGE:
    1444           2 :         agent->nexthop_table()->Enqueue(&nh_req);
    1445           2 :         data = new Inet4UnicastArpRoute(nexthop_vrf_name, ip, policy,
    1446           2 :                                         vn_list, sg, tag);
    1447           2 :         break;
    1448             : 
    1449           1 :     case DBRequest::DB_ENTRY_DELETE: {
    1450           1 :         VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(route_vrf_name);
    1451             :         InetUnicastRouteEntry *rt =
    1452             :             static_cast<InetUnicastRouteEntry *>(vrf->
    1453           1 :                           GetInet4UnicastRouteTable()->Find(rt_key));
    1454           1 :         assert(resolved==false);
    1455           1 :         agent->nexthop_table()->Enqueue(&nh_req);
    1456             : 
    1457             :         // If no other route is dependent on this, remove the route; else ignore
    1458           1 :         if (rt && rt->IsDependantRouteEmpty() && rt->IsTunnelNHListEmpty()) {
    1459           1 :             data = new Inet4UnicastArpRoute(nexthop_vrf_name, ip, policy,
    1460           1 :                                             vn_list, sg, tag);
    1461             :         } else {
    1462           0 :             rt_key->sub_op_ = AgentKey::RESYNC;
    1463           0 :             rt_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1464             :         }
    1465           1 :         break;
    1466             :     }
    1467             : 
    1468           0 :     default:
    1469           0 :         assert(0);
    1470             :     }
    1471             : 
    1472           3 :     rt_req.key.reset(rt_key);
    1473           3 :     rt_req.data.reset(data);
    1474           3 :     Inet4UnicastTableEnqueue(agent, &rt_req);
    1475           3 : }
    1476             : 
    1477             : void
    1478           0 : InetUnicastAgentRouteTable::NdpRoute(DBRequest::DBOperation op,
    1479             :                                      const string &route_vrf_name,
    1480             :                                      const IpAddress &ip,
    1481             :                                      const MacAddress &mac,
    1482             :                                      const string &nexthop_vrf_name,
    1483             :                                      const Interface &intf,
    1484             :                                      bool resolved,
    1485             :                                      const uint8_t plen,
    1486             :                                      bool policy,
    1487             :                                      const VnListType &vn_list,
    1488             :                                      const SecurityGroupList &sg,
    1489             :                                      const TagList &tag) {
    1490           0 :     Agent *agent = Agent::GetInstance();
    1491           0 :     DBRequest  nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1492           0 :     NdpNHKey *nh_key = new NdpNHKey(nexthop_vrf_name, ip, policy);
    1493           0 :     if (op == DBRequest::DB_ENTRY_DELETE) {
    1494             :         //In case of delete we want to set the
    1495             :         //nexthop as invalid, hence use resync operation
    1496             :         //We dont want the nexthop to created again
    1497             :         //in case of duplicate delete
    1498           0 :         nh_key->sub_op_ = AgentKey::RESYNC;
    1499             :     }
    1500           0 :     nh_req.key.reset(nh_key);
    1501             :     NdpNHData *ndp_data = new NdpNHData(mac,
    1502           0 :                static_cast<InterfaceKey *>(intf.GetDBRequestKey().release()),
    1503           0 :                resolved);
    1504           0 :     nh_req.data.reset(ndp_data);
    1505             : 
    1506           0 :     DBRequest  rt_req(op);
    1507             :     InetUnicastRouteKey *rt_key =
    1508           0 :         new InetUnicastRouteKey(agent->local_peer(), route_vrf_name, ip, plen);
    1509           0 :     InetUnicastNdpRoute *data = NULL;
    1510             : 
    1511           0 :     switch(op) {
    1512           0 :     case DBRequest::DB_ENTRY_ADD_CHANGE:
    1513           0 :         agent->nexthop_table()->Enqueue(&nh_req);
    1514           0 :         data = new InetUnicastNdpRoute(nexthop_vrf_name, ip, policy,
    1515           0 :                                         vn_list, sg, tag);
    1516           0 :         break;
    1517             : 
    1518           0 :     case DBRequest::DB_ENTRY_DELETE: {
    1519           0 :         VrfEntry *vrf = agent->vrf_table()->FindVrfFromName(route_vrf_name);
    1520             :         InetUnicastRouteEntry *rt =
    1521             :             static_cast<InetUnicastRouteEntry *>(vrf->
    1522           0 :                           GetInet6UnicastRouteTable()->Find(rt_key));
    1523           0 :         assert(resolved==false);
    1524           0 :         agent->nexthop_table()->Enqueue(&nh_req);
    1525             : 
    1526             :         // If no other route is dependent on this, remove the route; else ignore
    1527           0 :         if (rt && rt->IsDependantRouteEmpty() && rt->IsTunnelNHListEmpty()) {
    1528           0 :             data = new InetUnicastNdpRoute(nexthop_vrf_name, ip, policy,
    1529           0 :                                             vn_list, sg, tag);
    1530             :         } else {
    1531           0 :             rt_key->sub_op_ = AgentKey::RESYNC;
    1532           0 :             rt_req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1533             :         }
    1534           0 :         break;
    1535             :     }
    1536             : 
    1537           0 :     default:
    1538           0 :         assert(0);
    1539             :     }
    1540             : 
    1541           0 :     rt_req.key.reset(rt_key);
    1542           0 :     rt_req.data.reset(data);
    1543           0 :     Inet6UnicastTableEnqueue(agent, route_vrf_name, &rt_req);
    1544           0 : }
    1545             : 
    1546           0 : bool InetUnicastAgentRouteTable::ShouldAddArp(const Ip4Address &ip) {
    1547           0 :     if (ip == Agent::GetInstance()->router_id() ||
    1548           0 :         !IsIp4SubnetMember(ip, Agent::GetInstance()->router_id(),
    1549           0 :                            Agent::GetInstance()->vhost_prefix_len())) {
    1550             :         // TODO: add Arp request for GW
    1551             :         // Currently, default GW Arp is added during init
    1552           0 :         return false;
    1553             :     }
    1554             : 
    1555           0 :     return true;
    1556             : }
    1557             : 
    1558             : void
    1559           0 : InetUnicastAgentRouteTable::CheckAndAddArpRoute(const string &route_vrf_name,
    1560             :                                                 const Ip4Address &ip,
    1561             :                                                 const MacAddress &mac,
    1562             :                                                 const Interface *intf,
    1563             :                                                 bool resolved,
    1564             :                                                 const VnListType &vn_list,
    1565             :                                                 const SecurityGroupList &sg,
    1566             :                                                 const TagList &tag) {
    1567           0 :     if (!ShouldAddArp(ip)) {
    1568           0 :         return;
    1569             :     }
    1570           0 :     std::string nexthop_vrf = intf->vrf()->GetName();
    1571           0 :     if (intf->vrf()->forwarding_vrf()) {
    1572           0 :         nexthop_vrf = intf->vrf()->forwarding_vrf()->GetName();
    1573             :     }
    1574           0 :     ArpRoute(DBRequest::DB_ENTRY_ADD_CHANGE, route_vrf_name, ip, mac,
    1575             :              nexthop_vrf, *intf, resolved, 32, false, vn_list, sg, tag);
    1576           0 : }
    1577             : 
    1578             : void
    1579           0 : InetUnicastAgentRouteTable::CheckAndAddArpReq(const string &vrf_name,
    1580             :                                               const Ip4Address &ip,
    1581             :                                               const Interface *intf,
    1582             :                                               const VnListType &vn_list,
    1583             :                                               const SecurityGroupList &sg,
    1584             :                                               const TagList &tag) {
    1585             : 
    1586           0 :     if (!ShouldAddArp(ip)) {
    1587           0 :         return;
    1588             :     }
    1589           0 :     std::string nexthop_vrf = intf->vrf()->GetName();
    1590           0 :     if (intf->vrf()->forwarding_vrf()) {
    1591           0 :         nexthop_vrf = intf->vrf()->forwarding_vrf()->GetName();
    1592             :     }
    1593           0 :     AddArpReq(vrf_name, ip, nexthop_vrf, intf, false, vn_list, sg, tag);
    1594           0 : }
    1595             : 
    1596           3 : void InetUnicastAgentRouteTable::AddResolveRoute(const Peer *peer,
    1597             :                                                  const string &vrf_name,
    1598             :                                                  const Ip4Address &ip,
    1599             :                                                  const uint8_t plen,
    1600             :                                                  const InterfaceKey &intf,
    1601             :                                                  const uint32_t label,
    1602             :                                                  bool policy,
    1603             :                                                  const std::string &vn_name,
    1604             :                                                  const SecurityGroupList
    1605             :                                                  &sg_list,
    1606             :                                                  const TagList
    1607             :                                                  &tag_list) {
    1608           3 :     Agent *agent = Agent::GetInstance();
    1609           3 :     ResolveNH::CreateReq(&intf, policy);
    1610           3 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1611           6 :     req.key.reset(new InetUnicastRouteKey(peer, vrf_name, ip,
    1612           3 :                                           plen));
    1613           3 :     req.data.reset(new ResolveRoute(&intf, policy, label, vn_name, sg_list, tag_list));
    1614           3 :     Inet4UnicastTableEnqueue(agent, &req);
    1615           3 : }
    1616             : 
    1617             : // Create Route for a interface NH.
    1618             : // Used to create interface-nh pointing routes to vhost interfaces
    1619           0 : void InetUnicastAgentRouteTable::AddInetInterfaceRouteReq(const Peer *peer,
    1620             :                                                           const string &vm_vrf,
    1621             :                                                           const Ip4Address &addr,
    1622             :                                                           uint8_t plen,
    1623             :                                                           const string &interface,
    1624             :                                                           uint32_t label,
    1625             :                                                           const VnListType &vn_list) {
    1626           0 :     InetInterfaceKey intf_key(interface);
    1627             :     InetInterfaceRoute *data = new InetInterfaceRoute
    1628           0 :         (intf_key, label, TunnelType::MplsType(), vn_list,
    1629           0 :          peer->sequence_number());
    1630             : 
    1631           0 :     AddInetInterfaceRouteReq(peer, vm_vrf, addr, plen, data);
    1632           0 : }
    1633             : 
    1634           0 : void InetUnicastAgentRouteTable::AddInetInterfaceRouteReq(const Peer *peer,
    1635             :                                                           const string &vm_vrf,
    1636             :                                                           const Ip4Address &addr,
    1637             :                                                           uint8_t plen,
    1638             :                                                           InetInterfaceRoute *data) {
    1639           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1640           0 :     req.key.reset(new InetUnicastRouteKey(peer, vm_vrf, addr, plen));
    1641           0 :     req.data.reset(data);
    1642             : 
    1643           0 :     Inet4UnicastTableEnqueue(Agent::GetInstance(), &req);
    1644           0 : }
    1645             : 
    1646          20 : static void AddVHostRecvRouteInternal(DBRequest *req, const Peer *peer,
    1647             :                                       const string &vrf,
    1648             :                                       const InterfaceKey &intf_key,
    1649             :                                       const IpAddress &addr, uint8_t plen,
    1650             :                                       const string &vn_name, bool policy,
    1651             :                                       bool native_encap) {
    1652          20 :     req->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1653          20 :     req->key.reset(new InetUnicastRouteKey(peer, vrf, addr, plen));
    1654             : 
    1655          20 :     int tunnel_bmap = TunnelType::AllType();
    1656          20 :     if (native_encap) {
    1657          20 :         tunnel_bmap |= TunnelType::NativeType();
    1658             :     }
    1659             : 
    1660          20 :     req->data.reset(new ReceiveRoute(intf_key, MplsTable::kInvalidExportLabel,
    1661          20 :                                     tunnel_bmap, policy, vn_name));
    1662          20 : }
    1663             : 
    1664           3 : static void AddVHostMplsRecvRouteInternal(DBRequest *req, const Peer *peer,
    1665             :                                       const string &vrf,
    1666             :                                       const InterfaceKey &intf_key,
    1667             :                                       const IpAddress &addr, uint8_t plen,
    1668             :                                       const string &vn_name, bool policy,
    1669             :                                       bool native_encap) {
    1670           3 :     req->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1671           3 :     req->key.reset(new InetMplsUnicastRouteKey(peer, vrf, addr, plen));
    1672             : 
    1673           3 :     int tunnel_bmap = TunnelType::AllType();
    1674           3 :     if (native_encap) {
    1675           0 :         tunnel_bmap |= TunnelType::NativeType();
    1676             :     }
    1677             : 
    1678           3 :     req->data.reset(new ReceiveRoute(intf_key, MplsTable::kImplicitNullLabel,
    1679           3 :                                     tunnel_bmap, policy, vn_name));
    1680           3 : }
    1681           3 : void InetUnicastAgentRouteTable::AddVHostMplsRecvRouteReq
    1682             :     (const Peer *peer, const string &vrf, const InterfaceKey &intf_key,
    1683             :      const IpAddress &addr, uint8_t plen, const string &vn_name, bool policy,
    1684             :      bool native_encap) {
    1685           3 :     DBRequest req;
    1686           3 :     AddVHostMplsRecvRouteInternal(&req, peer, vrf, intf_key, addr, plen,
    1687             :                               vn_name, policy, native_encap);
    1688           3 :     Inet4MplsUnicastTableEnqueue(Agent::GetInstance(), &req);
    1689           3 : }
    1690          20 : void InetUnicastAgentRouteTable::AddVHostRecvRoute(const Peer *peer,
    1691             :                                                    const string &vrf,
    1692             :                                                    const InterfaceKey &intf_key,
    1693             :                                                    const IpAddress &addr,
    1694             :                                                    uint8_t plen,
    1695             :                                                    const string &vn_name,
    1696             :                                                    bool policy, bool native_encap, bool ipam_host_route) {
    1697          20 :     DBRequest req;
    1698          20 :     AddVHostRecvRouteInternal(&req, peer, vrf, intf_key, addr, plen,
    1699             :                               vn_name, policy, native_encap);
    1700          20 :     static_cast<ReceiveRoute *>(req.data.get())->SetProxyArp(true);
    1701          20 :     static_cast<ReceiveRoute *>(req.data.get())->SetIpamHostRoute(ipam_host_route);
    1702          20 :     if (addr.is_v4()) {
    1703          17 :         Inet4UnicastTableProcess(Agent::GetInstance(), vrf, req);
    1704           3 :     } else if (addr.is_v6()) {
    1705           3 :         Inet6UnicastTableProcess(Agent::GetInstance(), vrf, req);
    1706             :     }
    1707          20 : }
    1708             : 
    1709           0 : void InetUnicastAgentRouteTable::AddVHostRecvRouteReq
    1710             :     (const Peer *peer, const string &vrf, const InterfaceKey &intf_key,
    1711             :      const IpAddress &addr, uint8_t plen, const string &vn_name, bool policy,
    1712             :      bool native_encap) {
    1713           0 :     DBRequest req;
    1714           0 :     AddVHostRecvRouteInternal(&req, peer, vrf, intf_key, addr, plen,
    1715             :                               vn_name, policy, native_encap);
    1716           0 :     static_cast<ReceiveRoute *>(req.data.get())->SetProxyArp(true);
    1717           0 :     static_cast<ReceiveRoute *>(req.data.get())->SetIpamHostRoute(true);
    1718           0 :     if (addr.is_v4()) {
    1719           0 :         Inet4UnicastTableEnqueue(Agent::GetInstance(), &req);
    1720           0 :     } else if (addr.is_v6()) {
    1721           0 :         Inet6UnicastTableEnqueue(Agent::GetInstance(), vrf, &req);
    1722             :     }
    1723           0 : }
    1724             : 
    1725             : void
    1726           0 : InetUnicastAgentRouteTable::AddVHostSubnetRecvRoute(const Peer *peer,
    1727             :                                                     const string &vrf,
    1728             :                                                     const InterfaceKey &intf_key,
    1729             :                                                     const Ip4Address &addr,
    1730             :                                                     uint8_t plen,
    1731             :                                                     const string &vn_name,
    1732             :                                                     bool policy) {
    1733           0 :     DBRequest req;
    1734           0 :     AddVHostRecvRouteInternal(&req, peer, vrf, intf_key, addr, plen,
    1735             :                               vn_name, policy, true);
    1736           0 :     Inet4UnicastTableProcess(Agent::GetInstance(), vrf, req);
    1737           0 : }
    1738             : 
    1739           0 : void InetUnicastAgentRouteTable::AddDropRoute(const string &vm_vrf,
    1740             :                                               const Ip4Address &addr,
    1741             :                                               uint8_t plen,
    1742             :                                               const string &vn_name) {
    1743           0 :     Agent *agent = Agent::GetInstance();
    1744           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1745           0 :     req.key.reset(new InetUnicastRouteKey(agent->local_peer(), vm_vrf,
    1746           0 :                                       Address::GetIp4SubnetAddress(addr, plen),
    1747           0 :                                       plen));
    1748           0 :     req.data.reset(new DropRoute(vn_name));
    1749           0 :     Inet4UnicastTableEnqueue(agent, &req);
    1750           0 : }
    1751             : 
    1752           0 : void InetUnicastAgentRouteTable::DelVHostSubnetRecvRoute(const string &vm_vrf,
    1753             :                                                          const Ip4Address &addr,
    1754             :                                                          uint8_t plen) {
    1755           0 :     DeleteReq(Agent::GetInstance()->local_peer(), vm_vrf,
    1756           0 :               Address::GetIp4SubnetAddress(addr, plen), 32, NULL);
    1757           0 : }
    1758             : 
    1759           6 : static void AddGatewayRouteInternal(const Peer *peer,
    1760             :                                     DBRequest *req, const string &vrf_name,
    1761             :                                     const Ip4Address &dst_addr, uint8_t plen,
    1762             :                                     const AddressList &gw_list,
    1763             :                                     const VnListType &vn_name, uint32_t label,
    1764             :                                     const SecurityGroupList &sg_list,
    1765             :                                     const TagList &tag_list,
    1766             :                                     const CommunityList &communities,
    1767             :                                     bool native_encap) {
    1768           6 :     req->oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1769          12 :     req->key.reset(new InetUnicastRouteKey(peer,
    1770           6 :                                            vrf_name, dst_addr, plen));
    1771           6 :     req->data.reset(new Inet4UnicastGatewayRoute(gw_list, vrf_name,
    1772             :                                                  vn_name, label, sg_list,
    1773             :                                                  tag_list, communities,
    1774           6 :                                                  native_encap));
    1775           6 : }
    1776             : 
    1777           6 : void InetUnicastAgentRouteTable::AddGatewayRoute(const Peer *peer,
    1778             :                                                  const string &vrf_name,
    1779             :                                                  const Ip4Address &dst_addr,
    1780             :                                                  uint8_t plen,
    1781             :                                                  const AddressList &gw_list,
    1782             :                                                  const VnListType &vn_name,
    1783             :                                                  uint32_t label,
    1784             :                                                  const SecurityGroupList
    1785             :                                                  &sg_list,
    1786             :                                                  const TagList
    1787             :                                                  &tag_list,
    1788             :                                                  const CommunityList
    1789             :                                                  &communities,
    1790             :                                                  bool native_encap) {
    1791           6 :     DBRequest req;
    1792           6 :     AddGatewayRouteInternal(peer, &req, vrf_name, dst_addr, plen, gw_list, vn_name,
    1793             :                             label, sg_list, tag_list, communities, native_encap);
    1794           6 :     Inet4UnicastTableProcess(Agent::GetInstance(), vrf_name, req);
    1795           6 : }
    1796             : 
    1797             : void
    1798           0 : InetUnicastAgentRouteTable::AddGatewayRouteReq(const Peer *peer,
    1799             :                                                const string &vrf_name,
    1800             :                                                const Ip4Address &dst_addr,
    1801             :                                                uint8_t plen,
    1802             :                                                const AddressList &gw_list,
    1803             :                                                const VnListType &vn_list,
    1804             :                                                uint32_t label,
    1805             :                                                const SecurityGroupList
    1806             :                                                &sg_list,
    1807             :                                                const TagList
    1808             :                                                &tag_list,
    1809             :                                                const CommunityList
    1810             :                                                &communities,
    1811             :                                                bool native_encap) {
    1812           0 :     DBRequest req;
    1813           0 :     AddGatewayRouteInternal(peer, &req, vrf_name, dst_addr, plen, gw_list,
    1814             :                             vn_list, label, sg_list, tag_list, communities,
    1815             :                             native_encap);
    1816           0 :     Inet4UnicastTableEnqueue(Agent::GetInstance(), &req);
    1817           0 : }
    1818             : 
    1819             : void
    1820           0 : InetUnicastAgentRouteTable::AddMplsRouteReq(const Peer *peer,
    1821             :                                                const string &vrf_name,
    1822             :                                                const IpAddress &dst_addr,
    1823             :                                                uint8_t plen,
    1824             :                                                AgentRouteData *data ) {
    1825           0 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1826           0 :     req.key.reset(new InetMplsUnicastRouteKey(peer, vrf_name, dst_addr, plen));
    1827           0 :     req.data.reset(data);
    1828           0 :     Inet4MplsUnicastTableEnqueue(Agent::GetInstance(), &req);
    1829           0 : }
    1830             : void
    1831           3 : InetUnicastAgentRouteTable::AddIpamSubnetRoute(const string &vrf_name,
    1832             :                                                const IpAddress &dst_addr,
    1833             :                                                uint8_t plen,
    1834             :                                                const string &vn_name) {
    1835           3 :     Agent *agent_ptr = agent();
    1836           3 :     AgentRouteTable *table = NULL;
    1837           3 :     if (dst_addr.is_v4()) {
    1838           3 :         table = agent_ptr->vrf_table()->GetInet4UnicastRouteTable(vrf_name);
    1839           0 :     } else if (dst_addr.is_v6()) {
    1840           0 :         table = agent_ptr->vrf_table()->GetInet6UnicastRouteTable(vrf_name);
    1841             :     }
    1842             : 
    1843             :     //Add local peer path with discard NH
    1844           3 :     DBRequest dscd_nh_req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1845           3 :     dscd_nh_req.key.reset(new DiscardNHKey());
    1846           3 :     dscd_nh_req.data.reset(NULL);
    1847             : 
    1848           3 :     DBRequest req;
    1849           3 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1850           6 :     req.key.reset(new InetUnicastRouteKey(agent_ptr->local_peer(),
    1851           3 :                                           vrf_name, dst_addr, plen));
    1852           3 :     req.data.reset(new IpamSubnetRoute(dscd_nh_req, vn_name));
    1853           3 :     if (table) {
    1854           3 :         table->Process(req);
    1855             :     }
    1856           3 : }
    1857             : 
    1858             : void
    1859           0 : InetUnicastAgentRouteTable::AddVrouterSubnetRoute(const IpAddress &dst_addr,
    1860             :                                                   uint8_t plen) {
    1861             :     /* Only IPv4 is supported */
    1862           0 :     if (!dst_addr.is_v4()) {
    1863           0 :         return;
    1864             :     }
    1865           0 :     const string &vrf_name = agent()->fabric_vrf_name();
    1866           0 :     InetUnicastAgentRouteTable *table = NULL;
    1867           0 :     table = agent()->vrf_table()->GetInet4UnicastRouteTable(vrf_name);
    1868           0 :     const Peer *peer = agent()->fabric_rt_export_peer();
    1869             : 
    1870           0 :     VnListType vn_list;
    1871           0 :     vn_list.insert(agent()->fabric_vn_name());
    1872           0 :     const Ip4Address &gw = agent()->router_id();
    1873           0 :     table->AddGatewayRoute(peer, vrf_name, dst_addr.to_v4(), plen, AddressList(1, gw), vn_list, /* PKC: Make it as a list */
    1874           0 :                            MplsTable::kInvalidExportLabel, SecurityGroupList(),
    1875           0 :                            TagList(), CommunityList(), true);
    1876           0 : }
    1877             : 
    1878             : void
    1879           3 : InetUnicastAgentRouteTable::AddVhostMplsRoute(const IpAddress &vhost_addr,
    1880             :                                                         const Peer *peer) {
    1881             :     /* Only IPv4 is supported */
    1882           3 :     if (!vhost_addr.is_v4()) {
    1883           0 :         return;
    1884             :     }
    1885           3 :     const string &vrf_name = agent()->fabric_vrf_name();
    1886           3 :     InetUnicastAgentRouteTable *table = NULL;
    1887           3 :     table = agent()->vrf_table()->GetInet4MplsUnicastRouteTable(vrf_name);
    1888             : 
    1889           0 :     VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE, boost::uuids::nil_uuid(),
    1890           3 :                                agent()->vhost_interface_name());
    1891           3 :     table->AddVHostMplsRecvRouteReq(peer, vrf_name, vmi_key, vhost_addr,
    1892             :                                 32, agent()->fabric_vn_name(), false, false);
    1893           3 : }
    1894         184 : uint8_t InetUnicastAgentRouteTable::GetHostPlen(const IpAddress &ip_addr) const {
    1895         184 :     if (ip_addr.is_v4()) {
    1896         181 :         return Address::kMaxV4PrefixLen;
    1897             :     } else {
    1898           3 :         return Address::kMaxV6PrefixLen;
    1899             :     }
    1900             : }
    1901             : 
    1902             : void
    1903           0 : InetUnicastAgentRouteTable::AddInterfaceRouteReq(Agent *agent, const Peer *peer,
    1904             :                                                  const string &vrf_name,
    1905             :                                                  const Ip4Address &ip,
    1906             :                                                  uint8_t plen,
    1907             :                                                  const Interface  *intrface,
    1908             :                                                  const string &vn_name) {
    1909             : 
    1910           0 :     assert(intrface->type() == Interface::PHYSICAL);
    1911           0 :     DBRequest  rt_req(DBRequest::DB_ENTRY_ADD_CHANGE);
    1912           0 :     rt_req.key.reset(new InetUnicastRouteKey(agent->local_peer(),
    1913           0 :                                               vrf_name, ip, plen));
    1914           0 :     const PhysicalInterface *phy_intf = static_cast<const PhysicalInterface *>
    1915             :         (intrface);
    1916           0 :     rt_req.data.reset(new Inet4UnicastInterfaceRoute(phy_intf, vn_name));
    1917           0 :     Inet4UnicastTableEnqueue(agent, &rt_req);
    1918           0 : }
    1919             : 
    1920          76 : void InetUnicastAgentRouteTable::AddEvpnRoute(const AgentRoute *route) {
    1921             :     const EvpnRouteEntry *evpn_route =
    1922          76 :         dynamic_cast<const EvpnRouteEntry *>(route);
    1923          76 :     const IpAddress &ip_addr = evpn_route->prefix_address();
    1924             :     //No installation for evpn route with zero Ip prefix.
    1925          76 :     if (ip_addr.is_unspecified())
    1926          37 :         return;
    1927             : 
    1928             :     //label and parent-ip for NH need to be picket from parent route
    1929          39 :     DBRequest req;
    1930          39 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1931          78 :     const uint32_t plen = evpn_route->IsType5() ?
    1932          39 :         evpn_route->prefix_length() : GetHostPlen(ip_addr);
    1933             :     //Set key and data
    1934          78 :     req.key.reset(new InetUnicastRouteKey(agent()->inet_evpn_peer(),
    1935          39 :                                           evpn_route->vrf()->GetName(),
    1936             :                                           ip_addr,
    1937          39 :                                           plen));
    1938          39 :     req.data.reset(new InetEvpnRouteData(evpn_route));
    1939          39 :     Process(req);
    1940          39 : }
    1941             : 
    1942          31 : void InetUnicastAgentRouteTable::DeleteEvpnRoute(const AgentRoute *rt) {
    1943          31 :     const EvpnRouteEntry *evpn_route =
    1944             :         static_cast<const EvpnRouteEntry *>(rt);
    1945          31 :     const IpAddress &ip_addr = evpn_route->prefix_address();
    1946          31 :     DBRequest req(DBRequest::DB_ENTRY_DELETE);
    1947          31 :     const Peer *peer = agent()->inet_evpn_peer();
    1948          31 :     if (evpn_route->IsType5()) {
    1949           0 :         peer = agent()->evpn_routing_peer();
    1950             :     }
    1951          62 :     const uint32_t plen = evpn_route->IsType5() ?
    1952          31 :         evpn_route->prefix_length() : GetHostPlen(ip_addr);
    1953          31 :     req.key.reset(new InetUnicastRouteKey(peer,
    1954          31 :                                           evpn_route->vrf()->GetName(),
    1955             :                                           ip_addr,
    1956          31 :                                           plen));
    1957          31 :     req.data.reset(new InetEvpnRouteData(evpn_route));
    1958          31 :     Process(req);
    1959          31 : }
    1960             : 
    1961           0 : void InetUnicastAgentRouteTable::AddEvpnRoutingRoute(const IpAddress &ip_addr,
    1962             :                                     uint8_t plen,
    1963             :                                     const VrfEntry *vrf,
    1964             :                                     const Peer *peer,
    1965             :                                     const SecurityGroupList &sg_list,
    1966             :                                     const CommunityList &communities,
    1967             :                                     const PathPreference &path_preference,
    1968             :                                     const EcmpLoadBalance &ecmp_load_balance,
    1969             :                                     const TagList &tag_list,
    1970             :                                     DBRequest &nh_req,
    1971             :                                     uint32_t vxlan_id,
    1972             :                                     const VnListType& vn_list,
    1973             :                                     const std::string& origin_vn) {
    1974           0 :     DBRequest req;
    1975           0 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    1976             :     //Set key and data
    1977           0 :     req.key.reset(new InetUnicastRouteKey(peer,
    1978           0 :                                           vrf_entry()->GetName(),
    1979             :                                           ip_addr,
    1980           0 :                                           plen));
    1981           0 :     req.data.reset(new EvpnRoutingData(nh_req,
    1982             :                                        sg_list,
    1983             :                                        communities,
    1984             :                                        path_preference,
    1985             :                                        ecmp_load_balance,
    1986             :                                        tag_list,
    1987             :                                        vrf,
    1988             :                                        vxlan_id,
    1989             :                                        vn_list,
    1990           0 :                                        origin_vn));
    1991           0 :     Process(req);
    1992           0 : }
    1993             : 
    1994           0 : void InetUnicastAgentRouteTable::AddEvpnRoutingRouteReq(const IpAddress &ip_addr,
    1995             :                                     uint8_t plen,
    1996             :                                     const VrfEntry *vrf,
    1997             :                                     const Peer *peer,
    1998             :                                     const SecurityGroupList &sg_list,
    1999             :                                     const CommunityList &communities,
    2000             :                                     const PathPreference &path_preference,
    2001             :                                     const EcmpLoadBalance &ecmp_load_balance,
    2002             :                                     const TagList &tag_list,
    2003             :                                     DBRequest &nh_req,
    2004             :                                     uint32_t vxlan_id,
    2005             :                                     const VnListType& vn_list,
    2006             :                                     const std::string& origin_vn) {
    2007           0 :     DBRequest req;
    2008           0 :     req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
    2009             :     //Set key and data
    2010           0 :     req.key.reset(new InetUnicastRouteKey(peer,
    2011           0 :                                           vrf_entry()->GetName(),
    2012             :                                           ip_addr,
    2013           0 :                                           plen));
    2014           0 :     req.data.reset(new EvpnRoutingData(nh_req,
    2015             :                                        sg_list,
    2016             :                                        communities,
    2017             :                                        path_preference,
    2018             :                                        ecmp_load_balance,
    2019             :                                        tag_list,
    2020             :                                        vrf,
    2021             :                                        vxlan_id,
    2022             :                                        vn_list,
    2023           0 :                                        origin_vn));
    2024           0 :     InetUnicastTableEnqueue(Agent::GetInstance(), vrf->GetName(), &req);
    2025           0 : }

Generated by: LCOV version 1.14