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

Generated by: LCOV version 1.14