LCOV - code coverage report
Current view: top level - vnsw/agent/vrouter/ksync - route_ksync.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 709 802 88.4 %
Date: 2026-11-09 02:10:49 Functions: 70 73 95.9 %
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/asio.hpp>
       7             : #include <boost/bind/bind.hpp>
       8             : 
       9             : #include <base/logging.h>
      10             : #include <db/db_entry.h>
      11             : #include <db/db_table.h>
      12             : #include <db/db_table_partition.h>
      13             : #include <ksync/ksync_index.h>
      14             : #include <ksync/ksync_entry.h>
      15             : #include <ksync/ksync_object.h>
      16             : #include <ksync/ksync_netlink.h>
      17             : #include <ksync/ksync_sock.h>
      18             : 
      19             : #include "cmn/agent.h"
      20             : #include "oper/interface_common.h"
      21             : #include "oper/tunnel_nh.h"
      22             : #include "oper/nexthop.h"
      23             : #include "oper/route_common.h"
      24             : #include "oper/mirror_table.h"
      25             : #include "oper/agent_route_walker.h"
      26             : #include "oper/hbf.h"
      27             : 
      28             : #include "vrouter/ksync/interface_ksync.h"
      29             : #include "vrouter/ksync/nexthop_ksync.h"
      30             : #include "vrouter/ksync/route_ksync.h"
      31             : 
      32             : #include "ksync_init.h"
      33             : #include "vr_types.h"
      34             : #include "vr_defs.h"
      35             : #include "vr_nexthop.h"
      36             : #include "vr_vrf_table.h"
      37             : 
      38             : using namespace boost::placeholders;
      39             : 
      40        2858 : RouteKSyncEntry::RouteKSyncEntry(RouteKSyncObject* obj,
      41             :                                  const RouteKSyncEntry *entry,
      42        2858 :                                  uint32_t index) :
      43        2858 :     KSyncNetlinkDBEntry(index), ksync_obj_(obj),
      44        2858 :     rt_type_(entry->rt_type_), vrf_id_(entry->vrf_id_),
      45        2858 :     addr_(entry->addr_), src_addr_(entry->src_addr_), mac_(entry->mac_),
      46        2858 :     prefix_len_(entry->prefix_len_), nh_(entry->nh_), label_(entry->label_),
      47        2858 :     proxy_arp_(false), flood_dhcp_(entry->flood_dhcp_),
      48        2858 :     address_string_(entry->address_string_),
      49        2858 :     tunnel_type_(entry->tunnel_type_),
      50        2858 :     wait_for_traffic_(entry->wait_for_traffic_),
      51        2858 :     local_vm_peer_route_(entry->local_vm_peer_route_),
      52        2858 :     flood_(entry->flood_), ethernet_tag_(entry->ethernet_tag_),
      53        2858 :     layer2_control_word_(entry->layer2_control_word_),
      54        2858 :     is_learnt_route_(entry->is_learnt_route_) {
      55        2858 : }
      56             : 
      57        2059 : RouteKSyncEntry::RouteKSyncEntry(RouteKSyncObject* obj, const AgentRoute *rt) :
      58        2059 :     KSyncNetlinkDBEntry(kInvalidIndex), ksync_obj_(obj),
      59        2059 :     vrf_id_(rt->vrf_id()), mac_(), nh_(NULL), label_(0), proxy_arp_(false),
      60        2059 :     flood_dhcp_(false), tunnel_type_(TunnelType::DefaultType()),
      61        2059 :     wait_for_traffic_(false), local_vm_peer_route_(false),
      62        2059 :     flood_(false), ethernet_tag_(0), layer2_control_word_(false),
      63        4118 :     is_learnt_route_(false) {
      64        2059 :     boost::system::error_code ec;
      65        2059 :     rt_type_ = rt->GetTableType();
      66        2059 :     switch (rt_type_) {
      67         571 :     case Agent::INET4_UNICAST: {
      68         571 :           const InetUnicastRouteEntry *uc_rt =
      69             :               static_cast<const InetUnicastRouteEntry *>(rt);
      70         571 :           addr_ = uc_rt->prefix_address();
      71         571 :           src_addr_ = IpAddress::from_string("0.0.0.0", ec).to_v4();
      72         571 :           prefix_len_ = uc_rt->prefix_length();
      73         571 :           AgentPath *local_vm_path = uc_rt->FindLocalVmPortPath();
      74         571 :           if (local_vm_path && local_vm_path->IsDynamicLearntRoute()) {
      75           3 :               is_learnt_route_ = true;
      76             :           }
      77             : 
      78         571 :           break;
      79             :     }
      80         365 :     case Agent::INET6_UNICAST: {
      81         365 :           const InetUnicastRouteEntry *uc_rt =
      82             :               static_cast<const InetUnicastRouteEntry *>(rt);
      83         365 :           addr_ = uc_rt->prefix_address();
      84         365 :           src_addr_ = Ip6Address();
      85         365 :           prefix_len_ = uc_rt->prefix_length();
      86         365 :           break;
      87             :     }
      88           0 :     case Agent::INET4_MULTICAST: {
      89           0 :           const Inet4MulticastRouteEntry *mc_rt =
      90             :               static_cast<const Inet4MulticastRouteEntry *>(rt);
      91           0 :           addr_ = mc_rt->dest_ip_addr();
      92           0 :           src_addr_ = mc_rt->src_ip_addr();
      93           0 :           prefix_len_ = 32;
      94           0 :           break;
      95             :     }
      96        1123 :     case Agent::BRIDGE: {
      97        1123 :           const BridgeRouteEntry *l2_rt =
      98             :               static_cast<const BridgeRouteEntry *>(rt);
      99        1123 :           mac_ = l2_rt->prefix_address();
     100        1123 :           prefix_len_ = 0;
     101        1123 :           break;
     102             :     }
     103           0 :     default: {
     104           0 :           assert(0);
     105             :     }
     106             :     }
     107        2059 :     address_string_ = rt->GetAddressString();
     108        2059 : }
     109             : 
     110        7775 : RouteKSyncEntry::~RouteKSyncEntry() {
     111        7775 : }
     112             : 
     113       74934 : KSyncDBObject *RouteKSyncEntry::GetObject() const {
     114       74934 :     return ksync_obj_;
     115             : }
     116             : 
     117      194086 : bool RouteKSyncEntry::UcIsLess(const KSyncEntry &rhs) const {
     118      194086 :     const RouteKSyncEntry &entry = static_cast<const RouteKSyncEntry &>(rhs);
     119      194086 :     if (vrf_id_ != entry.vrf_id_) {
     120           0 :         return vrf_id_ < entry.vrf_id_;
     121             :     }
     122             : 
     123      194086 :     if (addr_ != entry.addr_) {
     124      188204 :         return addr_ < entry.addr_;
     125             :     }
     126             : 
     127        5882 :     return (prefix_len_ < entry.prefix_len_);
     128             : }
     129             : 
     130           0 : bool RouteKSyncEntry::McIsLess(const KSyncEntry &rhs) const {
     131           0 :     const RouteKSyncEntry &entry = static_cast<const RouteKSyncEntry &>(rhs);
     132           0 :     if (vrf_id_ != entry.vrf_id_) {
     133           0 :         return vrf_id_ < entry.vrf_id_;
     134             :     }
     135             : 
     136           0 :     if (src_addr_ != entry.src_addr_) {
     137           0 :         return src_addr_ < entry.src_addr_;
     138             :     }
     139             : 
     140           0 :     return (addr_ < entry.addr_);
     141             : }
     142             : 
     143        7416 : bool RouteKSyncEntry::L2IsLess(const KSyncEntry &rhs) const {
     144        7416 :     const RouteKSyncEntry &entry = static_cast<const RouteKSyncEntry &>(rhs);
     145             : 
     146        7416 :     if (vrf_id_ != entry.vrf_id_) {
     147           0 :         return vrf_id_ < entry.vrf_id_;
     148             :     }
     149             : 
     150        7416 :     return mac_ < entry.mac_;
     151             : }
     152             : 
     153      201502 : bool RouteKSyncEntry::IsLess(const KSyncEntry &rhs) const {
     154      201502 :     const RouteKSyncEntry &entry = static_cast<const RouteKSyncEntry &>(rhs);
     155      201502 :     if (rt_type_ != entry.rt_type_)
     156           0 :         return rt_type_ < entry.rt_type_;
     157             : 
     158             :     //First unicast
     159      201502 :     if ((rt_type_ == Agent::INET4_UNICAST) ||
     160      153153 :         (rt_type_ == Agent::INET6_UNICAST)) {
     161      194086 :         return UcIsLess(rhs);
     162             :     }
     163             : 
     164        7416 :     if (rt_type_ == Agent::BRIDGE) {
     165        7416 :         return L2IsLess(rhs);
     166             :     }
     167             : 
     168           0 :     return McIsLess(rhs);
     169             : }
     170             : 
     171       13899 : static std::string RouteTypeToString(Agent::RouteTableType type) {
     172       13899 :     switch (type) {
     173        6308 :     case Agent::INET4_UNICAST:
     174        6308 :         return "INET4_UNICAST";
     175             :         break;
     176        2416 :     case Agent::INET6_UNICAST:
     177        2416 :         return "INET6_UNICAST";
     178             :         break;
     179           0 :     case Agent::INET4_MULTICAST:
     180           0 :         return "INET_MULTICAST";
     181             :         break;
     182        5175 :     case Agent::BRIDGE:
     183        5175 :         return "BRIDGE";
     184             :         break;
     185           0 :     default:
     186           0 :         break;
     187             :     }
     188             : 
     189           0 :     assert(0);
     190             :     return "";
     191             : }
     192             : 
     193        9848 : std::string RouteKSyncEntry::ToString() const {
     194        9848 :     std::stringstream s;
     195             :     NHKSyncEntry *nexthop;
     196        9848 :     nexthop = nh();
     197             : 
     198        9848 :     s << "Type : " << RouteTypeToString(rt_type_) << " ";
     199             :     const VrfEntry* vrf =
     200        9848 :         ksync_obj_->ksync()->agent()->vrf_table()->FindVrfFromId(vrf_id_);
     201        9848 :     if (vrf) {
     202        8451 :         s << "Route Vrf : " << vrf->GetName() << " ";
     203             :     }
     204        9848 :     s << address_string_ << "/" << prefix_len_ << " Type:" << rt_type_;
     205             : 
     206             : 
     207        9848 :     s << " Label : " << label_;
     208        9848 :     s << " Tunnel Type: " << tunnel_type_;
     209             : 
     210        9848 :     if (nexthop) {
     211        9304 :         s << nexthop->ToString();
     212             :     } else {
     213         544 :         s << " NextHop : <NULL>";
     214             :     }
     215             : 
     216        9848 :     s << " Mac: " << mac_.ToString();
     217        9848 :     s << " Flood DHCP:" << flood_dhcp_;
     218       19696 :     return s.str();
     219        9848 : }
     220             : 
     221             : // Check if NH points to a service-chain interface or a Gateway interface
     222        3221 : static bool IsGatewayOrServiceInterface(const NextHop *nh) {
     223        3766 :     if (nh->GetType() != NextHop::INTERFACE &&
     224        3766 :         nh->GetType() != NextHop::VLAN && nh->GetType() != NextHop::ARP)
     225         519 :         return false;
     226             : 
     227        2702 :     const Interface *intf = NULL;
     228        2702 :     if (nh->GetType() == NextHop::INTERFACE) {
     229        2676 :         intf = (static_cast<const InterfaceNH *>(nh))->GetInterface();
     230        2676 :         if (intf->type() == Interface::PACKET)
     231         988 :             return true;
     232          26 :     } else if (nh->GetType() == NextHop::VLAN) {
     233           0 :         intf = (static_cast<const VlanNH *>(nh))->GetInterface();
     234          26 :     } else if (nh->GetType() == NextHop::ARP) {
     235          26 :         intf = (static_cast<const ArpNH *>(nh))->GetInterface();
     236             :     }
     237             : 
     238        1714 :     const VmInterface *vmi = dynamic_cast<const VmInterface *>(intf);
     239        1714 :     if (vmi == NULL)
     240          20 :         return false;
     241             : 
     242        1694 :     if (vmi->HasServiceVlan())
     243           0 :         return true;
     244        1694 :     if (vmi->device_type() == VmInterface::LOCAL_DEVICE)
     245          20 :         return true;
     246             : 
     247        1674 :     return false;
     248             : }
     249             : 
     250             : // Set the flood_ and proxy_arp_ flag for the route
     251             : // flood_ flag says that ARP packets hitting route should be flooded
     252             : // proxy_arp_ flag says VRouter should do proxy ARP
     253             : //
     254             : // The flags are set based on NH and Interface-type
     255        2850 : bool RouteKSyncEntry::BuildArpFlags(const DBEntry *e, const AgentPath *path,
     256             :                                     const MacAddress &mac) {
     257        2850 :     bool ret = false;
     258             : 
     259             :     //Route flags for inet4 and inet6
     260        2850 :     if ((rt_type_ != Agent::INET6_UNICAST) &&
     261        2279 :         (rt_type_ != Agent::INET4_UNICAST))
     262           0 :         return false;
     263             : 
     264        2850 :     Agent *agent = ksync_obj_->ksync()->agent();
     265        2850 :     const InetUnicastRouteEntry *rt =
     266             :         static_cast<const InetUnicastRouteEntry *>(e);
     267             : 
     268             :     // Assume no flood and proxy_arp by default
     269        2850 :     bool flood = false;
     270        2850 :     bool proxy_arp = false;
     271        2850 :     const NextHop *nh = rt->GetActiveNextHop();
     272             : 
     273        2850 :     if (nh == NULL) {
     274           0 :         return false;
     275             :     }
     276        2850 :     switch (nh->GetType()) {
     277           4 :     case NextHop::RESOLVE:
     278             :         // RESOLVE NH can be used by Gateway Interface or Fabric VRF
     279             :         // VRouter does not honour flood_ and proxy_arp_ flag for Fabric VRF
     280             :         // We dont want to flood ARP on Gateway Interface
     281           4 :         if (rt->vrf()->GetName() != agent->fabric_vrf_name()) {
     282           0 :             proxy_arp = true;
     283             :         }
     284           4 :         break;
     285             : 
     286             : 
     287         604 :     case NextHop::COMPOSITE:
     288             :         // ECMP flows have composite NH. We want to do routing for ECMP flows
     289             :         // So, set proxy_arp flag
     290         604 :         proxy_arp = true;
     291         604 :         break;
     292             : 
     293          78 :     case NextHop::TUNNEL:
     294             :         {
     295             :             // set proxy arp flag for MPLS VPN routes
     296             :             // these routes' nexthop is either labelled tunnel or
     297             :             // composite of labelled tunnel nexthops
     298          78 :             const TunnelNH *tunnel_nh = static_cast<const TunnelNH *>(nh);
     299          78 :             if (tunnel_nh->GetTunnelType().GetType() ==
     300             :                                     TunnelType::MPLS_OVER_MPLS) {
     301           0 :                 proxy_arp = true;
     302           0 :                 break;
     303             :                 // other tunnel cases should be evaluated under
     304             :                 // default case
     305             :             }
     306             :         }
     307             : 
     308             :     default:
     309             : 
     310        2242 :         if (mac != MacAddress::ZeroMac()) {
     311             :             // Proxy-ARP without flood if mac-stitching is present
     312         775 :             proxy_arp = true;
     313         775 :             flood = false;
     314         775 :             break;
     315             :         }
     316             : 
     317             :         // MAC stitching not present.
     318             :         // If interface belongs to service-chain or Gateway, we want packet to
     319             :         // be routed. Following config ensures routing,
     320             :         //     - Enable Proxy
     321             :         //     - Disable Flood-bit
     322             :         //     - Dont do MAC Stitching (in RouteNeedsMacBinding)
     323        1467 :         if (IsGatewayOrServiceInterface(nh) == true) {
     324         521 :             proxy_arp = true;
     325         521 :             flood = false;
     326         521 :             break;
     327             :         }
     328             : 
     329         946 :         AgentPath *local_vm_path = rt->FindLocalVmPortPath();
     330         946 :         if (local_vm_path != NULL) {
     331         159 :             if (local_vm_path->is_health_check_service()) {
     332             :                 // for local vm path exported by health check service
     333             :                 // set proxy arp to be true to arp with vrouter MAC
     334           0 :                 proxy_arp = true;
     335           0 :                 flood = false;
     336             :             } else {
     337             :                 // Local port without MAC stitching should only be a transition
     338             :                 // case. In the meanwhile, flood ARP so that VM can respond
     339             :                 // Note: In case VN is in L3 forwarding mode flags will be reset
     340             :                 // This is done below when VN entry is extracted.
     341         159 :                 proxy_arp_ = false;
     342         159 :                 flood = true;
     343             :             }
     344             :         } else {
     345             :             // Non local-route. Set flags based on the route
     346         787 :             proxy_arp = rt->proxy_arp();
     347         787 :             flood = rt->ipam_host_route();
     348             :         }
     349         946 :         break;
     350             :     }
     351             : 
     352             :     // There is an exception for IPAM subnet routes.
     353             :     // IPAM subnet routes always result in flood of ARP even if the route
     354             :     // is ECMP (resulting from gateway routes)
     355        2850 :     if (rt->ipam_subnet_route()) {
     356         362 :         proxy_arp = false;
     357         362 :         flood = true;
     358             :     }
     359             : 
     360             :     // If the route crosses a VN, we want packet to be routed. So, override
     361             :     // the flags set above and set only Proxy flag
     362             :     // When L2 forwarding mode is disabled, reset the proxy arp to true and flood
     363             :     // of arp to false.
     364        2850 :     VnEntry *vn= rt->vrf()->vn();
     365        4746 :     if (vn == NULL || !path->dest_vn_match(vn->GetName()) ||
     366        7596 :         (path->dest_vn_list().size() > 1) ||
     367        2366 :         (vn->bridging() == false)) {
     368         484 :         proxy_arp = true;
     369         484 :         flood = false;
     370             :     }
     371             : 
     372             :     //If VN is running in l2 mode, then any l3 route installed should
     373             :     //have flood flag set for ARP.
     374        2850 :     if (vn && (vn->layer3_forwarding() == false)) {
     375           0 :         proxy_arp = false;
     376           0 :         flood = true;
     377             :     }
     378             : 
     379             :     // VRouter does not honour flood/proxy_arp flags for fabric-vrf
     380        2850 :     if (rt->vrf()->GetName() == agent->fabric_vrf_name()) {
     381         406 :         if (mac != MacAddress() || nh->GetType() == NextHop::INTERFACE ||
     382          38 :             nh->GetType() == NextHop::COMPOSITE) {
     383         330 :             proxy_arp = true;
     384             :         } else {
     385          38 :             proxy_arp = false;
     386             :         }
     387         368 :         flood = false;
     388             :     }
     389             : 
     390        2850 :     if (proxy_arp != proxy_arp_) {
     391         888 :         proxy_arp_ = proxy_arp;
     392         888 :         ret = true;
     393             :     }
     394             : 
     395        2850 :     if (flood != flood_) {
     396         278 :         flood_ = flood;
     397         278 :         ret = true;
     398             :     }
     399        2850 :     return ret;
     400             : }
     401             : 
     402             : //Uses internal API to extract path.
     403        5055 : const NextHop *RouteKSyncEntry::GetActiveNextHop(const AgentRoute *route) const {
     404        5055 :     const AgentPath *path = GetActivePath(route);
     405        5055 :     if (path == NULL)
     406           0 :         return NULL;
     407        5055 :     return path->ComputeNextHop(ksync_obj_->ksync()->agent());
     408             : }
     409             : 
     410             : //Returns the usable path.
     411             : //In case of bridge tables the path contains reference path which
     412             : //has all the data. This path known as evpn_path is a level of indirection
     413             : //to leaked path from MAC+IP route.
     414       10110 : const AgentPath *RouteKSyncEntry::GetActivePath(const AgentRoute *route) const {
     415       10110 :     const AgentPath *path = route->GetActivePath();
     416       10110 :     return path;
     417             : }
     418             : 
     419        5055 : bool RouteKSyncEntry::Sync(DBEntry *e) {
     420        5055 :     bool ret = false;
     421        5055 :     Agent *agent = ksync_obj_->ksync()->agent();
     422        5055 :     const AgentRoute *route = static_cast<AgentRoute *>(e);
     423             : 
     424        5055 :     const AgentPath *path = GetActivePath(route);
     425        5055 :     if (path->peer() == agent->local_vm_peer())
     426         291 :         local_vm_peer_route_ = true;
     427             :     else
     428        4764 :         local_vm_peer_route_ = false;
     429             : 
     430        5055 :     NHKSyncObject *nh_object = ksync_obj_->ksync()->nh_ksync_obj();
     431        5055 :     NHKSyncEntry *old_nh = nh();
     432             : 
     433        5055 :     const NextHop *tmp = NULL;
     434        5055 :     tmp = GetActiveNextHop(route);
     435             : 
     436             :     // NHs should not be delete marked here. Interface NHs are an exception. If
     437             :     // an NH is found to be delete marked here, dont go ahead and initialize the
     438             :     // ksync entry with a delete marked NH. Make the route ksync entry use the
     439             :     // Discard NH's ksync entry until an update is received for the route.
     440       12313 :     if (tmp == NULL ||
     441        7258 :         ((tmp->GetType() != NextHop::INTERFACE) && tmp->IsDeleted())) {
     442           0 :         DiscardNHKey key;
     443           0 :         tmp = static_cast<NextHop *>(agent->nexthop_table()->
     444           0 :              FindActiveEntry(&key));
     445           0 :     }
     446        5055 :     NHKSyncEntry nexthop(nh_object, tmp);
     447        5055 :     nh_ = static_cast<NHKSyncEntry *>(nh_object->GetReference(&nexthop));
     448        5055 :     if (old_nh != nh()) {
     449        1817 :         ret = true;
     450             :     }
     451             : 
     452             :     //Bother for label for unicast and bridge routes
     453        5055 :     if (rt_type_ != Agent::INET4_MULTICAST) {
     454        5055 :         uint32_t old_label = label_;
     455             : 
     456        5055 :         if (route->is_multicast()) {
     457         769 :             label_ = path->vxlan_id();
     458             :         } else {
     459        4286 :             label_ = path->GetActiveLabel();
     460             :         }
     461        5055 :         if (label_ != old_label) {
     462        1353 :             ret = true;
     463             :         }
     464             : 
     465        5055 :         if (tunnel_type_ != path->GetTunnelType()) {
     466         127 :             tunnel_type_ = path->GetTunnelType();
     467         127 :             ret = true;
     468             :         }
     469             :     }
     470             : 
     471        5055 :     if (wait_for_traffic_ != route->WaitForTraffic()) {
     472        2150 :         wait_for_traffic_ =  route->WaitForTraffic();
     473        2150 :         ret = true;
     474             :     }
     475             : 
     476        5055 :     if (route->GetActivePath()) {
     477        5055 :         if (layer2_control_word_ != route->GetActivePath()->layer2_control_word()) {
     478           0 :             layer2_control_word_ = route->GetActivePath()->layer2_control_word();
     479           0 :             ret = true;
     480             :         }
     481             :     }
     482             : 
     483        5055 :     if (rt_type_ == Agent::INET4_UNICAST || rt_type_ == Agent::INET6_UNICAST) {
     484        2850 :         VrfKSyncObject *obj = ksync_obj_->ksync()->vrf_ksync_obj();
     485        2850 :         const InetUnicastRouteEntry *uc_rt =
     486             :             static_cast<const InetUnicastRouteEntry *>(e);
     487        2850 :         MacAddress mac = MacAddress::ZeroMac();
     488        2850 :         bool wait_for_traffic = false;
     489             : 
     490        2850 :         if (obj->RouteNeedsMacBinding(uc_rt)) {
     491        1261 :             mac = obj->GetIpMacBinding(uc_rt->vrf(), addr_, uc_rt);
     492        1261 :             wait_for_traffic = obj->GetIpMacWaitForTraffic(uc_rt->vrf(), addr_);
     493             :         }
     494             : 
     495        2850 :         if (wait_for_traffic_ == false &&
     496        1037 :             wait_for_traffic_ != wait_for_traffic) {
     497         627 :             wait_for_traffic_ = wait_for_traffic;
     498         627 :             ret = true;
     499             :         }
     500             : 
     501        2850 :         if (mac != mac_) {
     502         120 :             mac_ = mac;
     503         120 :             ret = true;
     504             :         }
     505             : 
     506        2850 :         if (BuildArpFlags(e, path, mac_))
     507        1067 :             ret = true;
     508             :     }
     509             : 
     510        5055 :     if (rt_type_ == Agent::BRIDGE) {
     511        2205 :         const BridgeRouteEntry *l2_rt =
     512             :             static_cast<const BridgeRouteEntry *>(route);
     513             : 
     514             :         //First search for v4
     515        2205 :         const MacVmBindingPath *dhcp_path = l2_rt->FindMacVmBindingPath();
     516        2205 :         bool flood_dhcp = true; // Flood DHCP if MacVmBindingPath is not present
     517        2205 :         if (dhcp_path)
     518         763 :             flood_dhcp = dhcp_path->flood_dhcp();
     519             : 
     520        2205 :         if (flood_dhcp_ != flood_dhcp) {
     521         522 :             flood_dhcp_ = flood_dhcp;
     522         522 :             ret = true;
     523             :         }
     524             :     }
     525             : 
     526        5055 :     return ret;
     527        5055 : }
     528             : 
     529        4051 : void RouteKSyncEntry::FillObjectLog(sandesh_op::type type,
     530             :                                     KSyncRouteInfo &info) const {
     531        4051 :     if (type == sandesh_op::ADD) {
     532        2622 :         info.set_operation("ADD/CHANGE");
     533             :     } else {
     534        1429 :         info.set_operation("DELETE");
     535             :     }
     536             : 
     537        4051 :     info.set_addr(address_string_);
     538        4051 :     info.set_plen(prefix_len_);
     539        4051 :     info.set_vrf(vrf_id_);
     540             : 
     541        4051 :     if (nh()) {
     542        3507 :         info.set_nh_idx(nh()->nh_id());
     543        3507 :         if (nh()->type() == NextHop::TUNNEL) {
     544          80 :             info.set_label(label_);
     545             :         }
     546             :     } else {
     547         544 :         info.set_nh_idx(NH_DISCARD_ID);
     548             :     }
     549             : 
     550        4051 :     info.set_mac(mac_.ToString());
     551        4051 :     info.set_type(RouteTypeToString(rt_type_));
     552        4051 : }
     553             : 
     554        4051 : int RouteKSyncEntry::Encode(sandesh_op::type op, uint8_t replace_plen,
     555             :                             char *buf, int buf_len) {
     556        4051 :     vr_route_req encoder;
     557             :     int encode_len;
     558        4051 :     NHKSyncEntry *nexthop = nh();
     559             : 
     560        4051 :     encoder.set_h_op(op);
     561        4051 :     encoder.set_rtr_rid(0);
     562        4051 :     encoder.set_rtr_vrf_id(vrf_id_);
     563        4051 :     if (rt_type_ != Agent::BRIDGE) {
     564        2596 :         if (addr_.is_v4()) {
     565        1866 :             encoder.set_rtr_family(AF_INET);
     566        1866 :             Ip4Address::bytes_type bytes = addr_.to_v4().to_bytes();
     567        1866 :             std::vector<int8_t> rtr_prefix(bytes.begin(), bytes.end());
     568        1866 :             encoder.set_rtr_prefix(rtr_prefix);
     569        2596 :         } else if (addr_.is_v6()) {
     570         730 :             encoder.set_rtr_family(AF_INET6);
     571         730 :             Ip6Address::bytes_type bytes = addr_.to_v6().to_bytes();
     572         730 :             std::vector<int8_t> rtr_prefix(bytes.begin(), bytes.end());
     573         730 :             encoder.set_rtr_prefix(rtr_prefix);
     574         730 :         }
     575        2596 :         encoder.set_rtr_prefix_len(prefix_len_);
     576        2596 :         if (mac_ != MacAddress::ZeroMac()) {
     577        1232 :             if ((addr_.is_v4() && prefix_len_ != 32) ||
     578         616 :                 (addr_.is_v6() && prefix_len_ != 128)) {
     579           0 :                 LOG(ERROR, "Unexpected MAC stitching for route "
     580             :                     << ToString());
     581           0 :                 mac_ = MacAddress::ZeroMac();
     582             :             }
     583             :             std::vector<int8_t> mac((int8_t *)mac_,
     584         616 :                                     (int8_t *)mac_ + mac_.size());
     585         616 :             encoder.set_rtr_mac(mac);
     586         616 :         }
     587             :     } else {
     588        1455 :         encoder.set_rtr_family(AF_BRIDGE);
     589             :         //TODO add support for mac
     590             :         std::vector<int8_t> mac((int8_t *)mac_,
     591        1455 :                                 (int8_t *)mac_ + mac_.size());
     592        1455 :         encoder.set_rtr_mac(mac);
     593        1455 :     }
     594             : 
     595        4051 :     int label = 0;
     596        4051 :     int flags = 0;
     597        4051 :     if (rt_type_ != Agent::INET4_MULTICAST) {
     598             :         // if next hop is tunnel
     599             :         // or nexthop is composite and composite type is LU_ECMP, then
     600             :         // label is valid
     601        8052 :         if (nexthop != NULL && ((nexthop->type() == NextHop::TUNNEL) ||
     602        4001 :                     ((nexthop->type() == NextHop::COMPOSITE) &&
     603         574 :                     (nexthop->CompositeType() == Composite::LU_ECMP)))) {
     604          80 :             label = label_;
     605          80 :             flags |= VR_RT_LABEL_VALID_FLAG;
     606             :         }
     607             :     }
     608             : 
     609        4051 :     if (rt_type_ == Agent::BRIDGE) {
     610        1455 :         label = label_;
     611        2484 :         if (nexthop != NULL && ((nexthop->type() == NextHop::COMPOSITE) ||
     612        1029 :                                (nexthop->type() == NextHop::TUNNEL))) {
     613         437 :             flags |= VR_BE_LABEL_VALID_FLAG;
     614             :         }
     615        1455 :         if (flood_dhcp_) {
     616        1316 :             flags |= VR_BE_FLOOD_DHCP_FLAG;
     617             :         }
     618        1455 :         if (ksync_obj_->ksync()->agent()->tsn_no_forwarding_enabled()) {
     619           0 :             flags |= VR_BE_EVPN_CONTROL_PROCESSING_FLAG;
     620             :         }
     621             :     } else {
     622             : 
     623        2596 :         if (proxy_arp_) {
     624        1480 :             flags |= VR_RT_ARP_PROXY_FLAG;
     625             :         }
     626             : 
     627        2596 :         if (wait_for_traffic_) {
     628        1961 :             flags |= VR_RT_ARP_TRAP_FLAG;
     629             :         }
     630             : 
     631        2596 :         if (flood_) {
     632         393 :             flags |= VR_RT_ARP_FLOOD_FLAG;
     633             :         }
     634             :        
     635        2596 :         if (is_learnt_route_) {
     636           8 :             flags |= VR_RT_MAC_IP_LEARNT_FLAG;
     637             :         }
     638             : 
     639             :     }
     640             : 
     641        4051 :     if (layer2_control_word_) {
     642           0 :         flags |= VR_BE_L2_CONTROL_DATA_FLAG;
     643             :     }
     644             : 
     645        4051 :     encoder.set_rtr_label_flags(flags);
     646        4051 :     encoder.set_rtr_label(label);
     647        4051 :     if (nexthop != NULL) {
     648        3507 :         encoder.set_rtr_nh_id(nexthop->nh_id());
     649             :     } else {
     650         544 :         encoder.set_rtr_nh_id(NH_DISCARD_ID);
     651             :     }
     652             : 
     653        4051 :     if (op == sandesh_op::DEL) {
     654        1429 :         encoder.set_rtr_replace_plen(replace_plen);
     655             :     }
     656             : 
     657        4051 :     int error = 0;
     658        4051 :     encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error);
     659        4051 :     assert(error == 0);
     660        4051 :     assert(encode_len <= buf_len);
     661        4051 :     return encode_len;
     662        4051 : }
     663             : 
     664             : 
     665        1429 : int RouteKSyncEntry::AddMsg(char *buf, int buf_len) {
     666        1429 :     KSyncRouteInfo info;
     667        1429 :     FillObjectLog(sandesh_op::ADD, info);
     668        1429 :     KSYNC_TRACE(Route, GetObject(), info);
     669        2858 :     return Encode(sandesh_op::ADD, 0, buf, buf_len);
     670        1429 : }
     671             : 
     672        1193 : int RouteKSyncEntry::ChangeMsg(char *buf, int buf_len){
     673        1193 :     KSyncRouteInfo info;
     674        1193 :     FillObjectLog(sandesh_op::ADD, info);
     675        1193 :     KSYNC_TRACE(Route, GetObject(), info);
     676             : 
     677        2386 :     return Encode(sandesh_op::ADD, 0, buf, buf_len);
     678        1193 : }
     679             : 
     680        1429 : int RouteKSyncEntry::DeleteMsg(char *buf, int buf_len) {
     681             : 
     682        1429 :     RouteKSyncEntry key(ksync_obj_, this, KSyncEntry::kInvalidIndex);
     683        1429 :     KSyncEntry *found = NULL;
     684        1429 :     RouteKSyncEntry *route = NULL;
     685        1429 :     NHKSyncEntry *ksync_nh = NULL;
     686             : 
     687             :     // IF multicast or bridge delete unconditionally
     688        1429 :     if ((rt_type_ == Agent::BRIDGE) ||
     689         936 :         (rt_type_ == Agent::INET4_MULTICAST)) {
     690         493 :         return DeleteInternal(nh(), NULL, buf, buf_len);
     691             :     }
     692             : 
     693             :     // For INET routes, we need to give replacement NH and prefixlen
     694       58872 :     for (int plen = (prefix_len() - 1); plen >= 0; plen--) {
     695             : 
     696       58328 :         if (addr_.is_v4()) {
     697       11848 :             Ip4Address addr = Address::GetIp4SubnetAddress(addr_.to_v4(), plen);
     698       11848 :             key.set_ip(addr);
     699       46480 :         } else if (addr_.is_v6()) {
     700       46480 :             Ip6Address addr = Address::GetIp6SubnetAddress(addr_.to_v6(), plen);
     701       46480 :             key.set_ip(addr);
     702             :         }
     703             : 
     704       58328 :         key.set_prefix_len(plen);
     705       58328 :         found = GetObject()->Find(&key);
     706             : 
     707       58328 :         if (found) {
     708         400 :             route = static_cast<RouteKSyncEntry *>(found);
     709         400 :             if (route->IsResolved()) {
     710         392 :                 ksync_nh = route->nh();
     711         392 :                 if(ksync_nh) {
     712         392 :                     return DeleteInternal(ksync_nh, route, buf, buf_len);
     713             :                 }
     714           0 :                 ksync_nh = NULL;
     715             :             }
     716             :         }
     717             :     }
     718             : 
     719             :     /* If better route is not found, send discardNH for route */
     720         544 :     return DeleteInternal(NULL, NULL, buf, buf_len);
     721        1429 : }
     722             : 
     723        1429 : uint8_t RouteKSyncEntry::CopyReplacementData(NHKSyncEntry *nexthop,
     724             :                                              RouteKSyncEntry *new_rt) {
     725        1429 :     uint8_t new_plen = 0;
     726        1429 :     nh_ = nexthop;
     727        1429 :     if (new_rt == NULL) {
     728        1037 :         label_ = 0;
     729        1037 :         proxy_arp_ = false;
     730        1037 :         flood_ = false;
     731        1037 :         wait_for_traffic_ = false;
     732             :         // mac_ is key for bridge entries and modifying it will corrut the
     733             :         // KSync tree. So, reset mac in case of non-bridge entries only
     734        1037 :         if (rt_type_ != Agent::BRIDGE) {
     735         544 :             mac_ = MacAddress::ZeroMac();
     736             :         }
     737        1037 :         is_learnt_route_ = false;
     738             :     } else {
     739         392 :         label_ = new_rt->label();
     740         392 :         new_plen = new_rt->prefix_len();
     741         392 :         proxy_arp_ = new_rt->proxy_arp();
     742         392 :         flood_ = new_rt->flood();
     743         392 :         wait_for_traffic_ = new_rt->wait_for_traffic();
     744         392 :         mac_ = new_rt->mac();
     745         392 :         is_learnt_route_ = new_rt->IsLearntRoute();
     746             :     }
     747        1429 :     return new_plen;
     748             : }
     749             : 
     750        1429 : int RouteKSyncEntry::DeleteInternal(NHKSyncEntry *nexthop,
     751             :                                     RouteKSyncEntry *new_rt,
     752             :                                     char *buf, int buf_len) {
     753        1429 :     uint8_t replace_plen = CopyReplacementData(nexthop, new_rt);
     754        1429 :     KSyncRouteInfo info;
     755        1429 :     FillObjectLog(sandesh_op::DEL, info);
     756        1429 :     KSYNC_TRACE(Route, GetObject(), info);
     757             : 
     758        2858 :     return Encode(sandesh_op::DEL, replace_plen, buf, buf_len);
     759        1429 : }
     760             : 
     761        4249 : KSyncEntry *RouteKSyncEntry::UnresolvedReference() {
     762        4249 :     NHKSyncEntry *nexthop = nh();
     763        4249 :     if (!nexthop->IsResolvedAndInSync()) {
     764        1613 :         return nexthop;
     765             :     }
     766             : 
     767        2636 :     if ((rt_type_ == Agent::INET4_UNICAST) ||
     768        1327 :         (rt_type_ == Agent::INET6_UNICAST)) {
     769        1674 :         if (!mac_.IsZero()) {
     770             :             //Get Vrf and bridge ksync object
     771         630 :             VrfKSyncObject *vrf_obj = ksync_obj_->ksync()->vrf_ksync_obj();
     772             :             VrfEntry* vrf =
     773         630 :                 ksync_obj_->ksync()->agent()->vrf_table()->FindVrfFromId(vrf_id_);
     774         630 :             if (vrf) {
     775             :                 VrfKSyncObject::VrfState *state =
     776             :                     static_cast<VrfKSyncObject::VrfState *>
     777         630 :                     (vrf->GetState(vrf->get_table(),
     778             :                                    vrf_obj->vrf_listener_id()));
     779         630 :                 RouteKSyncObject* bridge_ksync_obj = state->bridge_route_table_;
     780         630 :                 BridgeRouteEntry tmp_l2_rt(vrf, mac_, Peer::EVPN_PEER, false);
     781         630 :                 RouteKSyncEntry key(bridge_ksync_obj, &tmp_l2_rt);
     782             :                 RouteKSyncEntry *mac_route_reference =
     783             :                     static_cast<RouteKSyncEntry *>(bridge_ksync_obj->
     784         630 :                                                    GetReference(&key));
     785             :                 //Get the ksync entry for stitched mac
     786             :                 //else mark dependancy on same.
     787         630 :                 if (!mac_route_reference->IsResolved())
     788          14 :                     return mac_route_reference;
     789         644 :             } else {
     790             :                 // clear the mac_ to avoid failure in programming vrouter
     791           0 :                 mac_ = MacAddress::ZeroMac();
     792             :             }
     793             :         }
     794             :     }
     795             : 
     796        2622 :     return NULL;
     797             : }
     798             : 
     799         296 : RouteKSyncObject::RouteKSyncObject(KSync *ksync, AgentRouteTable *rt_table):
     800         296 :     KSyncDBObject("KSync Route"), ksync_(ksync), marked_delete_(false),
     801         296 :     table_delete_ref_(this, rt_table->deleter()) {
     802         296 :     rt_table_ = rt_table;
     803         296 :     RegisterDb(rt_table);
     804         296 : }
     805             : 
     806         592 : RouteKSyncObject::~RouteKSyncObject() {
     807         296 :     UnregisterDb(GetDBTable());
     808         296 :     table_delete_ref_.Reset(NULL);
     809         592 : }
     810             : 
     811             : KSyncDBObject::DBFilterResp
     812        5057 : RouteKSyncObject::DBEntryFilter(const DBEntry *entry,
     813             :                                 const KSyncDBEntry *ksync) {
     814        5057 :     const AgentRoute *route = static_cast<const AgentRoute *>(entry);
     815             :     // Ignore Add/Change notifications when VRF is deleted
     816        5057 :     if (route->vrf()->IsDeleted() == true) {
     817           2 :         return DBFilterIgnore;
     818             :     }
     819             : 
     820        5055 :     if (route->GetActivePath()->inactive())
     821           0 :         return DBFilterIgnore;
     822        5055 :     return DBFilterAccept;
     823             : }
     824             : 
     825        1429 : KSyncEntry *RouteKSyncObject::Alloc(const KSyncEntry *entry, uint32_t index) {
     826        1429 :     const RouteKSyncEntry *route = static_cast<const RouteKSyncEntry *>(entry);
     827        1429 :     RouteKSyncEntry *ksync = new RouteKSyncEntry(this, route, index);
     828        1429 :     return static_cast<KSyncEntry *>(ksync);
     829             : }
     830             : 
     831        1429 : KSyncEntry *RouteKSyncObject::DBToKSyncEntry(const DBEntry *e) {
     832        1429 :     const AgentRoute *route = static_cast<const AgentRoute *>(e);
     833        1429 :     RouteKSyncEntry *key = new RouteKSyncEntry(this, route);
     834        1429 :     return static_cast<KSyncEntry *>(key);
     835             : }
     836             : 
     837         485 : void RouteKSyncObject::Unregister() {
     838         485 :     if (IsEmpty() == true && marked_delete_ == true) {
     839         296 :         KSYNC_TRACE(Trace, this, "Destroying ksync object: "\
     840             :                     + rt_table_->name());
     841         296 :         KSyncObjectManager::Unregister(this);
     842             :     }
     843         485 : }
     844             : 
     845         296 : void RouteKSyncObject::ManagedDelete() {
     846         296 :     marked_delete_ = true;
     847         296 :     Unregister();
     848         296 : }
     849             : 
     850         217 : void RouteKSyncObject::EmptyTable() {
     851         217 :     if (marked_delete_ == true) {
     852         189 :         Unregister();
     853             :     }
     854         217 : }
     855             : 
     856          74 : VrfKSyncEntry::VrfKSyncEntry(VrfKSyncObject *obj, const VrfEntry *entry) :
     857          74 :     KSyncNetlinkDBEntry(kInvalidIndex), ksync_obj_(obj),
     858          74 :     vrf_id_(entry->vrf_id()), hbf_rintf_(entry->hbf_rintf()),
     859         148 :     hbf_lintf_(entry->hbf_lintf()) {
     860          74 : }
     861             : 
     862          74 : VrfKSyncEntry::VrfKSyncEntry(VrfKSyncObject *obj,
     863             :                              const VrfKSyncEntry *entry,
     864          74 :                              uint32_t index) :
     865             :     KSyncNetlinkDBEntry(index),
     866          74 :     vrf_id_(entry->vrf_id()), hbf_rintf_(entry->hbf_rintf()),
     867         148 :     hbf_lintf_(entry->hbf_lintf()) {
     868          74 :         ksync_obj_ = static_cast<VrfKSyncObject*>(entry->GetObject());
     869          74 : }
     870             : 
     871         296 : VrfKSyncEntry::~VrfKSyncEntry() {
     872         296 : }
     873             : 
     874         444 : KSyncDBObject *VrfKSyncEntry::GetObject() const {
     875         444 :         return ksync_obj_;
     876             : }
     877             : 
     878         670 : bool VrfKSyncEntry::IsLess(const KSyncEntry &rhs) const {
     879         670 :     const VrfKSyncEntry &entry = static_cast<const VrfKSyncEntry &> (rhs);
     880             : 
     881         670 :     if (vrf_id_ == entry.vrf_id()) {
     882         148 :         if (hbf_rintf_ == entry.hbf_rintf()) {
     883         148 :             return (hbf_lintf_ < entry.hbf_lintf());
     884             :         } else {
     885           0 :             return (hbf_rintf_ < entry.hbf_rintf());
     886             :         }
     887             :     } else {
     888         522 :         return (vrf_id_ < entry.vrf_id());
     889             :     }
     890             : }
     891             : 
     892         296 : std::string VrfKSyncEntry::ToString() const {
     893         296 :     std::stringstream s;
     894         296 :     s << "Vrf id: " << vrf_id() << " hbf lintf: " << hbf_lintf() <<
     895         296 :         " hbf rintf: " << hbf_rintf();
     896         592 :     return s.str();
     897         296 : }
     898             : 
     899          68 : bool VrfKSyncEntry::Sync(DBEntry* e) {
     900          68 :     VrfEntry *vrf = static_cast<VrfEntry *>(e);
     901             : 
     902         136 :     if ((vrf->hbf_rintf() != hbf_rintf_) ||
     903          68 :         (vrf->hbf_lintf() != hbf_lintf_)) {
     904           0 :         hbf_rintf_ = vrf->hbf_rintf();
     905           0 :         hbf_lintf_ = vrf->hbf_lintf();
     906           0 :         return true;
     907             :     }
     908             : 
     909          68 :     return false;
     910             : }
     911             : 
     912         148 : int VrfKSyncEntry::Encode(sandesh_op::type op, uint8_t replace_plen,
     913             :                             char *buf, int buf_len) {
     914         148 :     vr_vrf_req encoder;
     915             :     int encode_len;
     916             : 
     917         148 :     encoder.set_h_op(op);
     918         148 :     encoder.set_vrf_idx(vrf_id_);
     919         148 :     encoder.set_vrf_hbfr_vif_idx(hbf_rintf_);
     920         148 :     encoder.set_vrf_hbfl_vif_idx(hbf_lintf_);
     921         148 :     encoder.set_vrf_flags(VRF_FLAG_HBF_L_VALID|VRF_FLAG_HBF_R_VALID);
     922             : 
     923         148 :     std::stringstream ss;
     924         148 :     ss << "Encoding VrfKSyncEntry, vrf_id_ " << vrf_id_ <<
     925         148 :          " hbf_rintf_ " << hbf_rintf_ << " hbf_lintf_ " << hbf_lintf_;
     926         148 :     HBFTRACE(Trace, ss.str());
     927             : 
     928         148 :     int error = 0;
     929         148 :     encode_len = encoder.WriteBinary((uint8_t *)buf, buf_len, &error);
     930         148 :     assert(error == 0);
     931         148 :     assert(encode_len <= buf_len);
     932         148 :     return encode_len;
     933         148 : }
     934             : 
     935         148 : void VrfKSyncEntry::FillObjectLog(sandesh_op::type type,
     936             :                                     KSyncVrfInfo &info) const {
     937         148 :     if (type == sandesh_op::ADD) {
     938          74 :         info.set_operation("ADD/CHANGE");
     939             :     } else {
     940          74 :         info.set_operation("DELETE");
     941             :     }
     942             : 
     943         148 :     info.set_vrf_id(vrf_id_);
     944         148 :     info.set_hbf_rintf(hbf_rintf_);
     945         148 :     info.set_hbf_lintf(hbf_lintf_);
     946         148 : }
     947             : 
     948          74 : int VrfKSyncEntry::AddMsg(char *buf, int buf_len) {
     949          74 :     KSyncVrfInfo info;
     950          74 :     FillObjectLog(sandesh_op::ADD, info);
     951          74 :     KSYNC_TRACE(Vrf, GetObject(), info);
     952         148 :     return Encode(sandesh_op::ADD, 0, buf, buf_len);
     953          74 : }
     954             : 
     955           0 : int VrfKSyncEntry::ChangeMsg(char *buf, int buf_len){
     956           0 :     KSyncVrfInfo info;
     957           0 :     FillObjectLog(sandesh_op::ADD, info);
     958           0 :     KSYNC_TRACE(Vrf, GetObject(), info);
     959             : 
     960           0 :     return Encode(sandesh_op::ADD, 0, buf, buf_len);
     961           0 : }
     962             : 
     963          74 : int VrfKSyncEntry::DeleteMsg(char *buf, int buf_len) {
     964          74 :     KSyncVrfInfo info;
     965          74 :     FillObjectLog(sandesh_op::DEL, info);
     966          74 :     KSYNC_TRACE(Vrf, GetObject(), info);
     967             : 
     968         148 :     return Encode(sandesh_op::DEL, 0, buf, buf_len);
     969          74 : }
     970             : 
     971          74 : KSyncEntry *VrfKSyncEntry::UnresolvedReference() {
     972          74 :     return NULL; // TODO: check this
     973             : }
     974             : 
     975          74 : VrfKSyncObject::VrfState::VrfState(Agent *agent) :
     976          74 :     DBState(), seen_(false),
     977          74 :     evpn_rt_table_listener_id_(DBTableBase::kInvalidId) {
     978          74 :     ksync_route_walker_.reset(new KSyncRouteWalker(agent, this));
     979             :     agent->oper_db()->agent_route_walk_manager()->
     980          74 :         RegisterWalker(static_cast<AgentRouteWalker *>
     981             :                        (ksync_route_walker_.get()));
     982          74 : }
     983             : 
     984          74 : KSyncEntry *VrfKSyncObject::Alloc(const KSyncEntry *entry, uint32_t index) {
     985          74 :     const VrfKSyncEntry *vrf = static_cast<const VrfKSyncEntry *>(entry);
     986          74 :     VrfKSyncEntry *ksync = new VrfKSyncEntry(this, vrf, index);
     987          74 :     return static_cast<KSyncEntry *>(ksync);
     988             : }
     989             : 
     990          74 : KSyncEntry *VrfKSyncObject::DBToKSyncEntry(const DBEntry* e) {
     991          74 :     const VrfEntry *vrf = static_cast<const VrfEntry *>(e);
     992          74 :     VrfKSyncEntry *key = new VrfKSyncEntry(this, vrf);
     993          74 :     return static_cast<KSyncEntry *>(key);
     994             : }
     995             : 
     996         683 : void VrfKSyncObject::VrfNotify(DBTablePartBase *partition, DBEntryBase *e) {
     997         683 :     VrfEntry *vrf = static_cast<VrfEntry *>(e);
     998             :     VrfState *state = static_cast<VrfState *>
     999         683 :         (vrf->GetState(partition->parent(), vrf_listener_id_));
    1000         683 :     if (vrf->IsDeleted()) {
    1001         541 :         if (state) {
    1002          74 :             UnRegisterEvpnRouteTableListener(vrf, state);
    1003          74 :             vrf->ClearState(partition->parent(), vrf_listener_id_);
    1004          74 :             (static_cast<KSyncRouteWalker *>(state->ksync_route_walker_.get()))->EnqueueDelete();
    1005             : 
    1006          74 :             if (state->ksync_->IsDeleted() == false) {
    1007          74 :                 if (state->ksync_->GetDBEntry() != NULL) {
    1008          74 :                     state->ksync_->SetDBEntry(NULL);
    1009             :                 }
    1010          74 :                 NotifyEvent(state->ksync_, KSyncEntry::DEL_REQ);
    1011             :             }
    1012             : 
    1013          74 :             delete state;
    1014             :         }
    1015         541 :         return;
    1016             :     }
    1017             : 
    1018         142 :     if (state == NULL) {
    1019          74 :         state = new VrfState(ksync_->agent());
    1020          74 :         state->seen_ = true;
    1021             : 
    1022             :         // Create ksync entry for VRF
    1023             :         KSyncEntry *key;
    1024          74 :         key = DBToKSyncEntry(vrf);
    1025          74 :         state->ksync_ = static_cast<VrfKSyncEntry *>(CreateImpl(key));
    1026          74 :         delete key;
    1027          74 :         vrf->SetState(partition->parent(), vrf_listener_id_, state);
    1028          74 :         state->ksync_->SetDBEntry(vrf);
    1029          74 :         NotifyEvent(state->ksync_, KSyncEntry::ADD_CHANGE_REQ);
    1030             : 
    1031             :         // Get Inet4 Route table and register with KSync
    1032             :         AgentRouteTable *rt_table = static_cast<AgentRouteTable *>(vrf->
    1033          74 :                           GetInet4UnicastRouteTable());
    1034          74 :         state->inet4_uc_route_table_ = new RouteKSyncObject(ksync_, rt_table);
    1035             : 
    1036             :         // Get Inet6 Route table and register with KSync
    1037             :         rt_table = static_cast<AgentRouteTable *>(vrf->
    1038          74 :                           GetInet6UnicastRouteTable());
    1039          74 :         state->inet6_uc_route_table_ = new RouteKSyncObject(ksync_, rt_table);
    1040             : 
    1041             :         // Get Layer 2 Route table and register with KSync
    1042             :         rt_table = static_cast<AgentRouteTable *>(vrf->
    1043          74 :                           GetBridgeRouteTable());
    1044          74 :         state->bridge_route_table_ = new RouteKSyncObject(ksync_, rt_table);
    1045             : 
    1046             :         //Now for multicast table. Ksync object for multicast table is
    1047             :         //not maintained in vrf list
    1048             :         //TODO Enhance ksyncobject for UC/MC, currently there is only one entry
    1049             :         //in MC so just use the UC object for time being.
    1050             :         rt_table = static_cast<AgentRouteTable *>(vrf->
    1051          74 :                           GetInet4MulticastRouteTable());
    1052          74 :         state->inet4_mc_route_table_ = new RouteKSyncObject(ksync_, rt_table);
    1053             : 
    1054             :         //Add EVPN route table listener to update IP MAC binding table.
    1055             :         rt_table = static_cast<AgentRouteTable *>(vrf->
    1056          74 :                                                   GetEvpnRouteTable());
    1057          74 :         KSYNC_TRACE(Trace, state->inet4_uc_route_table_,
    1058             :                     "Subscribing to route table "\
    1059             :                     + vrf->GetName());
    1060          74 :         if (state->evpn_rt_table_listener_id_ == DBTableBase::kInvalidId) {
    1061          74 :             state->evpn_rt_table_listener_id_ =
    1062          74 :                 rt_table->Register(boost::bind(&VrfKSyncObject::EvpnRouteTableNotify,
    1063             :                                            this, _1, _2));
    1064             :         }
    1065          74 :         (static_cast<KSyncRouteWalker *>(state->ksync_route_walker_.get()))->
    1066          74 :             NotifyRoutes(vrf);
    1067             :     } else {
    1068          68 :         VrfKSyncEntry* ksync = state->ksync_;
    1069          68 :         if (ksync->Sync(vrf) || ksync->IsDeleted()) {
    1070           0 :             NotifyEvent(ksync, KSyncEntry::ADD_CHANGE_REQ);
    1071             :         }
    1072             :     }
    1073             : }
    1074             : 
    1075        1847 : void VrfKSyncObject::EvpnRouteTableNotify(DBTablePartBase *partition,
    1076             :                                           DBEntryBase *e) {
    1077        1847 :     const EvpnRouteEntry *evpn_rt = static_cast<const EvpnRouteEntry *>(e);
    1078             : 
    1079        1847 :     if (evpn_rt->IsType5())
    1080           0 :         return;
    1081             : 
    1082        1847 :     if (evpn_rt->IsDeleted()) {
    1083         338 :         DelIpMacBinding(evpn_rt->vrf(), evpn_rt->prefix_address(),
    1084             :                         evpn_rt->mac(), evpn_rt->ethernet_tag());
    1085             :     } else {
    1086        1509 :         AddIpMacBinding(evpn_rt->vrf(), evpn_rt->prefix_address(),
    1087             :                         evpn_rt->mac(),
    1088             :                         evpn_rt->ethernet_tag(),
    1089        1509 :                         evpn_rt->GetActivePath()->path_preference().preference(),
    1090        1509 :                         evpn_rt->WaitForTraffic());
    1091             :     }
    1092        1847 :     return;
    1093             : }
    1094             : 
    1095          74 : void VrfKSyncObject::UnRegisterEvpnRouteTableListener(const VrfEntry *vrf,
    1096             :                                                       VrfState *state) {
    1097          74 :     if (state->evpn_rt_table_listener_id_ == DBTableBase::kInvalidId)
    1098           0 :         return;
    1099             : 
    1100             :     AgentRouteTable *rt_table = static_cast<AgentRouteTable *>(vrf->
    1101          74 :                                             GetEvpnRouteTable());
    1102          74 :     rt_table->Unregister(state->evpn_rt_table_listener_id_);
    1103          74 :     state->evpn_rt_table_listener_id_ = DBTableBase::kInvalidId;
    1104             : }
    1105             : 
    1106           2 : VrfKSyncObject::VrfKSyncObject(KSync *ksync) :
    1107           2 :     KSyncDBObject("KSync Vrf"), ksync_(ksync), marked_delete_(false) {
    1108           2 :     vrf_table_ = ksync_->agent()->vrf_table();
    1109           2 : }
    1110             : 
    1111           4 : VrfKSyncObject::~VrfKSyncObject() {
    1112           4 : }
    1113             : 
    1114           2 : void VrfKSyncObject::RegisterDBClients() {
    1115           2 :     vrf_listener_id_ = ksync_->agent()->vrf_table()->Register
    1116           2 :             (boost::bind(&VrfKSyncObject::VrfNotify, this, _1, _2));
    1117           2 : }
    1118             : 
    1119           0 : void VrfKSyncObject::Shutdown() {
    1120           0 :     ksync_->agent()->vrf_table()->Unregister(vrf_listener_id_);
    1121           0 :     vrf_listener_id_ = -1;
    1122           0 : }
    1123             : 
    1124        4051 : void vr_route_req::Process(SandeshContext *context) {
    1125        4051 :     AgentSandeshContext *ioc = static_cast<AgentSandeshContext *>(context);
    1126        4051 :     ioc->RouteMsgHandler(this);
    1127        4051 : }
    1128             : 
    1129         148 : void vr_vrf_req::Process(SandeshContext *context) {
    1130         148 :     AgentSandeshContext *ioc = static_cast<AgentSandeshContext *>(context);
    1131         148 :     ioc->VrfMsgHandler(this);
    1132         148 : }
    1133             : 
    1134             : /****************************************************************************
    1135             :  * Methods to stitch IP and MAC addresses. The KSync object maintains mapping
    1136             :  * between IP <-> MAC in ip_mac_binding_ tree. The table is built based on
    1137             :  * Evpn routes.
    1138             :  *
    1139             :  * When an Inet route is notified, if it needs MAC Stitching, the MAC to
    1140             :  * stitch is found from the ip_mac_binding_ tree
    1141             :  *
    1142             :  * Any change to ip_mac_binding_ tree will also result in re-evaluation of
    1143             :  * Inet4/Inet6 route that may potentially have stitching changed
    1144             :  ****************************************************************************/
    1145             : 
    1146             : // Compute if a route needs IP-MAC binding. A route needs IP-MAC binding if,
    1147             : // 1. The NH points to interface or Tunnel-NH
    1148             : // 2. NH does not belong to Service-Chain Interface
    1149             : // 3. NH does not belong to Gateway Interface
    1150             : // to interface or tunnel-nh
    1151        2850 : bool VrfKSyncObject::RouteNeedsMacBinding(const InetUnicastRouteEntry *rt) {
    1152        2850 :     if (rt->prefix_address().is_v4() && rt->prefix_length() != 32)
    1153         407 :         return false;
    1154             : 
    1155        2443 :     if (rt->prefix_address().is_v6() && rt->prefix_length() != 128)
    1156           4 :         return false;
    1157             : 
    1158        2439 :     VnEntry *vn = NULL;
    1159        2439 :     if (rt->vrf() != ksync_->agent()->fabric_vrf()) {
    1160             :         //Check if VN is enabled for bridging, if not then skip mac binding.
    1161        2093 :         VnEntry *vn= rt->vrf()->vn();
    1162        2093 :         if (vn == NULL || (vn->bridging() == false))
    1163          92 :             return false;
    1164             :     }
    1165             : 
    1166             :     // If the route crosses a VN, we want packet to be routed. So, override
    1167        2347 :     const NextHop *nh = rt->GetActiveNextHop();
    1168        2347 :     if (nh == NULL)
    1169           0 :         return false;
    1170             : 
    1171        3014 :     if (nh->GetType() != NextHop::INTERFACE &&
    1172        1268 :         nh->GetType() != NextHop::TUNNEL &&
    1173        1202 :         nh->GetType() != NextHop::VLAN &&
    1174        3615 :         nh->GetType() != NextHop::VRF &&
    1175         601 :         nh->GetType() != NextHop::ARP)
    1176         593 :         return false;
    1177             : 
    1178        1754 :     if (IsGatewayOrServiceInterface(nh) == true)
    1179         487 :         return false;
    1180             : 
    1181        1273 :     if (nh->GetType() == NextHop::ARP &&
    1182        1273 :         rt->GetActivePath()->gw_ip() == Ip4Address(0)) {
    1183           6 :         return false;
    1184             :     }
    1185             : 
    1186        1261 :     if (nh->GetType() == NextHop::ARP && nh->IsValid() == false) {
    1187           0 :         return false;
    1188             :     }
    1189             : 
    1190             :     //Is this a IPAM gateway? It may happen that better path is present pointing
    1191             :     //to tunnel. In this case IPAM gateway path will not be active path and
    1192             :     //identifying same will be missed. Stitching has to be avoided on non-TSN
    1193             :     //node.
    1194             :     //This has to be done only when layer3 forwarding is enabled on VN,
    1195             :     //else mac binding should be done irrespective of IPAM gateway.
    1196        1261 :     if (vn && vn->layer3_forwarding()) {
    1197           0 :         const Agent *agent = ksync()->agent();
    1198           0 :         if (agent->tsn_enabled() == false) {
    1199           0 :             const AgentPath *path = rt->FindPath(agent->local_peer());
    1200           0 :             nh = path ? path->nexthop() : NULL;
    1201             :         }
    1202           0 :         if (nh && (IsGatewayOrServiceInterface(nh) == true))
    1203           0 :             return false;
    1204             :     }
    1205             : 
    1206        1261 :     return true;
    1207             : }
    1208             : 
    1209             : // Notify change to KSync entry of InetUnicast Route
    1210        1847 : void VrfKSyncObject::NotifyUcRoute(VrfEntry *vrf, VrfState *state,
    1211             :                                    const IpAddress &ip) {
    1212        1847 :     InetUnicastAgentRouteTable *table = NULL;
    1213        1847 :     if (ip.is_v4()) {
    1214        1847 :         table = vrf->GetInet4UnicastRouteTable();
    1215             :     } else {
    1216           0 :         table = vrf->GetInet6UnicastRouteTable();
    1217             :     }
    1218             : 
    1219        1847 :     InetUnicastRouteEntry *rt = table->FindLPM(ip);
    1220        1847 :     if (rt == NULL || rt->IsDeleted())
    1221        1002 :         return;
    1222             : 
    1223         845 :     if (rt->GetTableType() == Agent::INET4_UNICAST) {
    1224         845 :         state->inet4_uc_route_table_->Notify(rt->get_table_partition(), rt);
    1225           0 :     } else if (rt->GetTableType() == Agent::INET6_UNICAST) {
    1226           0 :         state->inet6_uc_route_table_->Notify(rt->get_table_partition(), rt);
    1227             :     }
    1228             : }
    1229             : 
    1230        1509 : void VrfKSyncObject::AddIpMacBinding(VrfEntry *vrf, const IpAddress &ip,
    1231             :                                      const MacAddress &mac,
    1232             :                                      uint32_t ethernet_tag,
    1233             :                                      uint32_t pref,
    1234             :                                      bool wait_for_traffic) {
    1235             :     VrfState *state = static_cast<VrfState *>
    1236        1509 :         (vrf->GetState(vrf->get_table(), vrf_listener_id_));
    1237        1509 :     if (state == NULL)
    1238           0 :         return;
    1239             : 
    1240             :     IpToMacBinding::iterator it =
    1241        1509 :         state->ip_mac_binding_.find(std::make_pair(ip, ethernet_tag));
    1242             : 
    1243        1509 :     PathPreference path_pref(0, pref, wait_for_traffic, false);
    1244        1509 :     if (it == state->ip_mac_binding_.end()) {
    1245         232 :         MacBinding mac_binding(mac, path_pref);
    1246         232 :         state->ip_mac_binding_.insert(std::pair<IpToMacBindingKey, MacBinding>
    1247         232 :                 (std::make_pair(ip, ethernet_tag), mac_binding));
    1248         232 :     } else {
    1249        1277 :         it->second.set_mac(path_pref, mac);
    1250             :     }
    1251             : 
    1252        1509 :     NotifyUcRoute(vrf, state, ip);
    1253        1509 : }
    1254             : 
    1255         338 : void VrfKSyncObject::DelIpMacBinding(VrfEntry *vrf, const IpAddress &ip,
    1256             :                                      const MacAddress &mac,
    1257             :                                      uint32_t ethernet_tag) {
    1258             :     VrfState *state = static_cast<VrfState *>
    1259         338 :         (vrf->GetState(vrf->get_table(), vrf_listener_id_));
    1260         338 :     if (state == NULL)
    1261           0 :         return;
    1262             : 
    1263             :     IpToMacBinding::iterator it =
    1264         338 :         state->ip_mac_binding_.find(std::make_pair(ip, ethernet_tag));
    1265         338 :     if (it != state->ip_mac_binding_.end()) {
    1266         338 :         it->second.reset_mac(mac);
    1267         338 :         if (it->second.can_erase()) {
    1268         232 :             state->ip_mac_binding_.erase(std::make_pair(ip, ethernet_tag));
    1269             :         }
    1270             :     }
    1271         338 :     NotifyUcRoute(vrf, state, ip);
    1272             : }
    1273             : 
    1274        1261 : bool VrfKSyncObject::GetIpMacWaitForTraffic(VrfEntry *vrf,
    1275             :                                             const IpAddress &ip) const {
    1276             :     VrfState *state = static_cast<VrfState *>
    1277        1261 :         (vrf->GetState(vrf->get_table(), vrf_listener_id_));
    1278        1261 :     if (state == NULL) {
    1279           0 :         return false;
    1280             :     }
    1281             : 
    1282             :     IpToMacBinding::const_iterator it =
    1283        1261 :         state->ip_mac_binding_.lower_bound(std::make_pair(ip, 0));
    1284        2036 :     if (it == state->ip_mac_binding_.end() ||
    1285         775 :         (it->first.first != ip)) {
    1286         486 :         return false;
    1287             :     }
    1288             : 
    1289         775 :     return  it->second.WaitForTraffic();
    1290             : }
    1291             : 
    1292        1261 : MacAddress VrfKSyncObject::GetIpMacBinding(VrfEntry *vrf,
    1293             :                                            const IpAddress &ip,
    1294             :                                            const InetUnicastRouteEntry *rt)
    1295             :                                            const {
    1296             :     VrfState *state = static_cast<VrfState *>
    1297        1261 :         (vrf->GetState(vrf->get_table(), vrf_listener_id_));
    1298        1261 :     if (state == NULL)
    1299           0 :         return MacAddress::ZeroMac();
    1300             : 
    1301        1261 :     if (vrf->GetName() == ksync_->agent()->fabric_vrf_name()) {
    1302         330 :         if (rt->GetActivePath()->gw_ip() != Ip4Address(0)) {
    1303             :             const ArpNH *arp_nh =
    1304           0 :                 dynamic_cast<const ArpNH *>(rt->GetActiveNextHop());
    1305           0 :             if (arp_nh) {
    1306           0 :                 return arp_nh->GetMac();
    1307             :             }
    1308             :         }
    1309             :     }
    1310             : 
    1311             :     IpToMacBinding::const_iterator it =
    1312        1261 :         state->ip_mac_binding_.lower_bound(std::make_pair(ip, 0));
    1313        2036 :     if (it == state->ip_mac_binding_.end() ||
    1314         775 :         (it->first.first != ip)) {
    1315         486 :         return MacAddress::ZeroMac();
    1316             :     }
    1317             : 
    1318         775 :     return it->second.get_mac();
    1319             : }
    1320             : 
    1321          74 : KSyncRouteWalker::KSyncRouteWalker(Agent *agent, VrfKSyncObject::VrfState *state) :
    1322          74 :     AgentRouteWalker("ksyncroutewalker", agent), state_(state),
    1323          74 :     marked_for_deletion_(false) {
    1324          74 : }
    1325             : 
    1326         148 : KSyncRouteWalker::~KSyncRouteWalker() {
    1327         148 : }
    1328             : 
    1329         324 : bool IsStatePresent(AgentRoute *route, DBTableBase::ListenerId id,
    1330             :                     DBTablePartBase *partition) {
    1331         324 :     DBState *state = route->GetState(partition->parent(), id);
    1332         324 :     return (state != NULL);
    1333             : }
    1334             : 
    1335          74 : void KSyncRouteWalker::EnqueueDelete() {
    1336          74 :     marked_for_deletion_ = true;
    1337          74 :     mgr()->ReleaseWalker(static_cast<AgentRouteWalker *>(this));
    1338          74 : }
    1339             : 
    1340         331 : bool KSyncRouteWalker::RouteWalkNotify(DBTablePartBase *partition,
    1341             :                                       DBEntryBase *e) {
    1342         331 :     if (marked_for_deletion_)
    1343           0 :         return true;
    1344             : 
    1345         331 :     AgentRoute *route = static_cast<AgentRoute *>(e);
    1346             : 
    1347         331 :     switch (route->GetTableType()) {
    1348          15 :     case Agent::INET4_UNICAST: {
    1349          15 :         if (IsStatePresent(route, state_->inet4_uc_route_table_->id(),
    1350          15 :                            partition) == false) {
    1351           0 :             state_->inet4_uc_route_table_->Notify(partition, route);
    1352             :         }
    1353          15 :         break;
    1354             :     }
    1355          14 :     case Agent::INET6_UNICAST: {
    1356          14 :         if (IsStatePresent(route, state_->inet6_uc_route_table_->id(),
    1357          14 :                            partition) == false) {
    1358           0 :             state_->inet6_uc_route_table_->Notify(partition, route);
    1359             :         }
    1360          14 :         break;
    1361             :     }
    1362           0 :     case Agent::INET4_MULTICAST: {
    1363           0 :         if (IsStatePresent(route, state_->inet4_mc_route_table_->id(),
    1364           0 :                            partition) == false) {
    1365           0 :             state_->inet4_mc_route_table_->Notify(partition, route);
    1366             :         }
    1367           0 :         break;
    1368             :     }
    1369         295 :     case Agent::BRIDGE: {
    1370         295 :         if (IsStatePresent(route, state_->bridge_route_table_->id(),
    1371         295 :                            partition) == false) {
    1372           0 :             state_->bridge_route_table_->Notify(partition, route);
    1373             :         }
    1374         295 :         break;
    1375             :     }
    1376           7 :     default: {
    1377           7 :         break;
    1378             :     }
    1379             :     }
    1380         331 :     return true;
    1381             : }
    1382             : 
    1383          74 : void KSyncRouteWalker::NotifyRoutes(VrfEntry *vrf) {
    1384          74 :     if (marked_for_deletion_ == false)
    1385          74 :         StartRouteWalk(vrf);
    1386          74 : }

Generated by: LCOV version 1.14