LCOV - code coverage report
Current view: top level - vnsw/agent/services - arp_proto.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 490 652 75.2 %
Date: 2026-11-09 02:10:49 Functions: 52 66 78.8 %
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 "sandesh/sandesh_types.h"
       7             : #include "sandesh/sandesh.h"
       8             : #include "base/address_util.h"
       9             : #include "init/agent_init.h"
      10             : #include "oper/nexthop.h"
      11             : #include "oper/tunnel_nh.h"
      12             : #include "oper/mirror_table.h"
      13             : #include "oper/route_common.h"
      14             : #include "pkt/pkt_init.h"
      15             : #include "services/arp_proto.h"
      16             : #include "services/services_sandesh.h"
      17             : #include "services_init.h"
      18             : #include "mac_learning/mac_learning_proto.h"
      19             : 
      20           2 : ArpProto::ArpProto(Agent *agent, boost::asio::io_context &io,
      21           2 :                    bool run_with_vrouter) :
      22             :     Proto(agent, "Agent::Services", PktHandler::ARP, io),
      23           2 :     run_with_vrouter_(run_with_vrouter), ip_fabric_interface_index_(-1),
      24           4 :     ip_fabric_interface_(NULL), max_retries_(kMaxRetries),
      25           2 :     retry_timeout_(kRetryTimeout), aging_timeout_(kAgingTimeout) {
      26             :     // limit the number of entries in the workqueue
      27           2 :     work_queue_.SetSize(agent->params()->services_queue_limit());
      28           2 :     work_queue_.SetBounded(true);
      29             : 
      30           2 :     vrf_table_listener_id_ = agent->vrf_table()->Register(
      31             :                              boost::bind(&ArpProto::VrfNotify, this, _1, _2));
      32           2 :     interface_table_listener_id_ = agent->interface_table()->Register(
      33             :                                    boost::bind(&ArpProto::InterfaceNotify,
      34             :                                                this, _2));
      35           2 :     nexthop_table_listener_id_ = agent->nexthop_table()->Register(
      36             :                                  boost::bind(&ArpProto::NextHopNotify, this, _2));
      37           2 : }
      38             : 
      39           4 : ArpProto::~ArpProto() {
      40           4 : }
      41             : 
      42           2 : void ArpProto::Shutdown() {
      43             :     // we may have arp entries in arp cache without ArpNH, empty them
      44           2 :     for (ArpIterator it = arp_cache_.begin(); it != arp_cache_.end(); ) {
      45           0 :         it = DeleteArpEntry(it);
      46             :     }
      47             : 
      48           2 :     for (GratuitousArpIterator it = gratuitous_arp_cache_.begin();
      49           2 :             it != gratuitous_arp_cache_.end(); it++) {
      50           0 :         for (ArpEntrySet::iterator sit = it->second.begin();
      51           0 :              sit != it->second.end();) {
      52           0 :             ArpEntry *entry = *sit;
      53           0 :             it->second.erase(sit++);
      54           0 :             delete entry;
      55             :         }
      56             :     }
      57           2 :     gratuitous_arp_cache_.clear();
      58           2 :     agent_->vrf_table()->Unregister(vrf_table_listener_id_);
      59           2 :     agent_->interface_table()->Unregister(interface_table_listener_id_);
      60           2 :     agent_->nexthop_table()->Unregister(nexthop_table_listener_id_);
      61           2 : }
      62             : 
      63         736 : ProtoHandler *ArpProto::AllocProtoHandler(boost::shared_ptr<PktInfo> info,
      64             :                                           boost::asio::io_context &io) {
      65         736 :     return new ArpHandler(agent(), info, io);
      66             : }
      67             : 
      68         683 : void ArpProto::VrfNotify(DBTablePartBase *part, DBEntryBase *entry) {
      69         683 :     VrfEntry *vrf = static_cast<VrfEntry *>(entry);
      70             :     ArpVrfState *state;
      71             : 
      72         683 :     state = static_cast<ArpVrfState *>(entry->GetState(part->parent(),
      73             :                                                    vrf_table_listener_id_));
      74         683 :     if (entry->IsDeleted()) {
      75         541 :         if (state) {
      76         223 :             for (ArpProto::ArpIterator it = arp_cache_.begin();
      77         434 :                  it != arp_cache_.end();) {
      78         211 :                 ArpEntry *arp_entry = it->second;
      79         211 :                 if (arp_entry->key().vrf == vrf && arp_entry->DeleteArpRoute()) {
      80           0 :                     it = DeleteArpEntry(it);
      81             :                 } else
      82         211 :                     it++;
      83             :             }
      84         223 :             for (GratuitousArpIterator it = gratuitous_arp_cache_.begin();
      85        2706 :                  it != gratuitous_arp_cache_.end(); ) {
      86        2483 :                  ArpKey key = it->first;
      87        2483 :                  if (key.vrf == vrf) {
      88         138 :                      for (ArpEntrySet::iterator sit = it->second.begin();
      89         259 :                           sit != it->second.end();) {
      90         121 :                          ArpEntry *entry = *sit;
      91         121 :                          it->second.erase(sit++);
      92         121 :                          delete entry;
      93             :                      }
      94         138 :                     gratuitous_arp_cache_.erase(it++);
      95             :                  }else {
      96        2345 :                     it++;
      97             :                  }
      98             :             }
      99         223 :             state->Delete();
     100             :         }
     101         541 :         return;
     102             :     }
     103             : 
     104         142 :     if (!state){
     105          74 :         state = new ArpVrfState(agent_, this, vrf,
     106          74 :                                 vrf->GetInet4UnicastRouteTable(),
     107          74 :                                 vrf->GetEvpnRouteTable());
     108          74 :         state->route_table_listener_id = vrf->
     109          74 :             GetInet4UnicastRouteTable()->
     110          74 :             Register(boost::bind(&ArpVrfState::RouteUpdate, state,  _1, _2));
     111          74 :         state->evpn_route_table_listener_id = vrf->GetEvpnRouteTable()->
     112          74 :             Register(boost::bind(&ArpVrfState::EvpnRouteUpdate, state,  _1, _2));
     113          74 :         entry->SetState(part->parent(), vrf_table_listener_id_, state);
     114             :     }
     115             : }
     116             : 
     117         782 : void intrusive_ptr_add_ref(ArpPathPreferenceState *aps) {
     118         782 :     aps->refcount_++;
     119         782 : }
     120             : 
     121         782 : void intrusive_ptr_release(ArpPathPreferenceState *aps) {
     122         782 :     ArpVrfState *state = aps->vrf_state();
     123         782 :     int prev = aps->refcount_.fetch_sub(1);
     124         782 :     if (prev == 1) {
     125         559 :         state->Erase(aps->ip(), aps->plen());
     126         559 :         delete aps;
     127             :     }
     128         782 : }
     129             : 
     130         559 : ArpPathPreferenceState::ArpPathPreferenceState(ArpVrfState *state,
     131             :                                                uint32_t vrf_id,
     132             :                                                const IpAddress &ip,
     133         559 :                                                uint8_t plen):
     134         559 :     vrf_state_(state), arp_req_timer_(NULL), vrf_id_(vrf_id),
     135         559 :     vm_ip_(ip), plen_(plen) {
     136         559 :     refcount_ = 0;
     137         559 : }
     138             : 
     139         559 : ArpPathPreferenceState::~ArpPathPreferenceState() {
     140         559 :     if (arp_req_timer_) {
     141         126 :         arp_req_timer_->Cancel();
     142         126 :         TimerManager::DeleteTimer(arp_req_timer_);
     143             :     }
     144         559 :     assert(refcount_ == 0);
     145         559 : }
     146             : 
     147        1179 : void ArpPathPreferenceState::StartTimer() {
     148        1179 :     if (arp_req_timer_ == NULL) {
     149         252 :         arp_req_timer_ = TimerManager::CreateTimer(
     150         126 :                 *(vrf_state_->agent->event_manager()->io_service()),
     151             :                 "Arp Entry timer for VM",
     152             :                 TaskScheduler::GetInstance()->
     153             :                 GetTaskId("Agent::Services"), PktHandler::ARP);
     154             :     }
     155        1179 :     arp_req_timer_->Start(kTimeout,
     156             :                           boost::bind(&ArpPathPreferenceState::SendArpRequest,
     157             :                                       this));
     158        1179 : }
     159             : 
     160        2362 : bool ArpPathPreferenceState::SendArpRequest(WaitForTrafficIntfMap
     161             :                                             &wait_for_traffic_map,
     162             :                                             ArpTransmittedIntfMap
     163             :                                             &arp_transmitted_map) {
     164        2362 :     bool ret = false;
     165        2362 :     boost::shared_ptr<PktInfo> pkt(new PktInfo(vrf_state_->agent,
     166             :                                                ARP_TX_BUFF_LEN,
     167        2362 :                                                PktHandler::ARP, 0));
     168        2362 :     ArpHandler arp_handler(vrf_state_->agent, pkt,
     169        2362 :             *(vrf_state_->agent->event_manager()->io_service()));
     170             : 
     171        2362 :     WaitForTrafficIntfMap::iterator it = wait_for_traffic_map.begin();
     172        5230 :     for (;it != wait_for_traffic_map.end(); it++) {
     173             :         const VmInterface *vm_intf = static_cast<const VmInterface *>(
     174        2868 :                 vrf_state_->agent->interface_table()->FindInterface(it->first));
     175        2868 :         if (!vm_intf) {
     176        1168 :             continue;
     177             :         }
     178             : 
     179        2844 :         InterfaceArpPathPreferenceInfo &data = it->second;
     180        2844 :         bool inserted = arp_transmitted_map.insert(it->first).second;
     181        2844 :         ++data.arp_retry_count;
     182        2844 :         if (inserted == false) {
     183             :             //ARP request already sent due to IP route
     184        1144 :             continue;
     185             :         }
     186        1700 :         if ((plen_ != 32) && (!data.prev_responded_ip.is_unspecified())) {
     187           0 :             if ((data.arp_send_count >= 1) && (data.arp_reply_count == 0)) {
     188           0 :                 ++data.arp_failure_count;
     189             :             }
     190           0 :             if (data.arp_failure_count >= ArpProto::kMaxFailures) {
     191           0 :                 data.prev_responded_ip = Ip4Address(0);
     192           0 :                 data.arp_failure_count = 0;
     193           0 :                 data.arp_reply_count = 0;
     194           0 :                 data.arp_send_count = 0;
     195             :             }
     196             :         }
     197        1700 :         ++data.arp_send_count;
     198             : 
     199             :         // Post message to delete MIL entry.
     200        1700 :         MacAddress mil_mac = vrf_state_->agent->mac_learning_proto()->
     201             :                         GetMacIpLearningTable()->GetPairedMacAddress(
     202        1700 :                                 vm_intf->vrf_id(), ip());
     203        1700 :         if (mil_mac != MacAddress()) {
     204           0 :             ++data.arp_try_count;
     205           0 :             if (data.arp_try_count == kArpTryCount) {
     206           0 :                 IpAddress ip = vm_ip_;
     207           0 :                 MacAddress mac = mil_mac;
     208           0 :                 vrf_state_->agent->mac_learning_proto()->
     209           0 :                         GetMacIpLearningTable()->MacIpEntryUnreachable(
     210             :                                 vm_intf->vrf_id(), ip, mac);
     211           0 :                 return true;
     212             :             }
     213             :         }
     214             : 
     215        1700 :         MacAddress smac = vm_intf->GetVifMac(vrf_state_->agent);
     216        1700 :         arp_handler.SendArpRequestByPlen(vm_intf, smac, this,
     217        1700 :                                          data.prev_responded_ip);
     218             : 
     219             :         // reduce the frequency of ARP requests after some tries
     220        1700 :         if (data.arp_send_count >= kMaxRetry) {
     221           0 :             if ((mac() != MacAddress()) && (mac() != vm_intf->vm_mac())) {
     222           0 :                 arp_req_timer_->Reschedule(5000);
     223           0 :             } else if (vm_intf->vmi_type() != VmInterface::REMOTE_VM) {
     224             :                 // change frequency only if not in gateway mode with remote VMIs
     225           0 :                 arp_req_timer_->Reschedule(kTimeout * 5);
     226             :             }
     227             :         }
     228             : 
     229        1700 :         ret = true;
     230             :     }
     231        2362 :     return ret;
     232        2362 : }
     233             : 
     234        1181 : bool ArpPathPreferenceState::SendArpRequest() {
     235        1194 :     if (l3_wait_for_traffic_map_.size() == 0 &&
     236          13 :         evpn_wait_for_traffic_map_.size() == 0) {
     237           0 :         return false;
     238             :     }
     239             : 
     240        1181 :     bool ret = false;
     241        1181 :     ArpTransmittedIntfMap arp_transmitted_map;
     242        1181 :     if (SendArpRequest(l3_wait_for_traffic_map_, arp_transmitted_map)) {
     243        1168 :         ret = true;
     244             :     }
     245             : 
     246        1181 :     if (SendArpRequest(evpn_wait_for_traffic_map_, arp_transmitted_map)) {
     247          16 :         ret = true;
     248             :     }
     249             : 
     250        1181 :     return ret;
     251        1181 : }
     252             : 
     253             : //Send ARP request on interface in Active-BackUp mode
     254             : //So that preference of route can be incremented if the VM replies to ARP
     255        1901 : void ArpPathPreferenceState::SendArpRequestForAllIntf(const
     256             :                                                       AgentRoute *route) {
     257        1901 :     WaitForTrafficIntfMap new_wait_for_traffic_map;
     258        1901 :     WaitForTrafficIntfMap wait_for_traffic_map = evpn_wait_for_traffic_map_;
     259        1901 :     if (dynamic_cast<const InetUnicastRouteEntry *>(route)) {
     260        1218 :         wait_for_traffic_map = l3_wait_for_traffic_map_;
     261             :     }
     262             : 
     263        5796 :     for (Route::PathList::const_iterator it = route->GetPathList().begin();
     264       11592 :             it != route->GetPathList().end(); it++) {
     265        3895 :         const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
     266        7790 :         if (path->peer() &&
     267        3895 :             path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER) {
     268        2159 :             const NextHop *nh = path->ComputeNextHop(vrf_state_->agent);
     269        2159 :             if (nh->GetType() != NextHop::INTERFACE) {
     270         683 :                 continue;
     271             :             }
     272        1903 :             if (path->is_health_check_service()) {
     273             :                 // skip sending ARP request for Health Check Service IP
     274           0 :                 continue;
     275             :             }
     276             : 
     277        1903 :             const InterfaceNH *intf_nh =
     278             :                 static_cast<const  InterfaceNH *>(nh);
     279             :             const Interface *intf =
     280        1903 :                 static_cast<const Interface *>(intf_nh->GetInterface());
     281        1903 :             if (intf->type() != Interface::VM_INTERFACE) {
     282             :                 //Ignore non vm interface nexthop
     283           0 :                 continue;
     284             :             }
     285        1903 :             if (path->subnet_service_ip().is_v4() == false) {
     286           0 :                 continue;
     287             :             }
     288        1903 :             if (path->path_preference().IsDependentRt() == true) {
     289         427 :                 continue;
     290             :             }
     291        1476 :             uint32_t intf_id = intf->id();
     292             :             WaitForTrafficIntfMap::const_iterator wait_for_traffic_it =
     293        1476 :                 wait_for_traffic_map.find(intf_id);
     294        1476 :             if (wait_for_traffic_it == wait_for_traffic_map.end()) {
     295         492 :                 InterfaceArpPathPreferenceInfo data;
     296         492 :                 new_wait_for_traffic_map.insert(WaitForTrafficIntfPair(intf_id,
     297             :                                                                        data));
     298             :             } else {
     299         984 :                 new_wait_for_traffic_map.insert(WaitForTrafficIntfPair(intf_id,
     300         984 :                     wait_for_traffic_it->second));
     301             :             }
     302             :         }
     303             :     }
     304             : 
     305        1901 :     if (dynamic_cast<const InetUnicastRouteEntry *>(route)) {
     306        1218 :         l3_wait_for_traffic_map_ = new_wait_for_traffic_map;
     307             :     } else {
     308         683 :         evpn_wait_for_traffic_map_ = new_wait_for_traffic_map;
     309             :     }
     310        1901 :     if (new_wait_for_traffic_map.size() > 0) {
     311        1179 :         SendArpRequest();
     312        1179 :         StartTimer();
     313             :     }
     314        1901 : }
     315             : 
     316         909 : ArpDBState::ArpDBState(ArpVrfState *vrf_state, uint32_t vrf_id, IpAddress ip,
     317        1818 :                        uint8_t plen) : vrf_state_(vrf_state),
     318         909 :     sg_list_(), tag_list_(), policy_(false), resolve_route_(false) {
     319         909 :     if (ip != Ip4Address(0)) {
     320         782 :        arp_path_preference_state_.reset(vrf_state->Locate(ip, plen));
     321             :     }
     322         909 : }
     323             : 
     324        1818 : ArpDBState::~ArpDBState() {
     325        1818 : }
     326             : 
     327        1434 : void ArpDBState::UpdateMac(const InterfaceNH *nh) {
     328             : 
     329        1434 :     if (nh && arp_path_preference_state_.get()) {
     330         827 :         arp_path_preference_state_.get()->set_mac(nh->GetDMac());
     331             :     }
     332             : 
     333             : 
     334        1434 :     return;
     335             : }
     336             : 
     337           0 : void ArpDBState::UpdateArpRoutes(const InetUnicastRouteEntry *rt) {
     338           0 :     int plen = rt->prefix_length();
     339           0 :     uint32_t start_ip = rt->prefix_address().to_v4().to_ulong();
     340           0 :     ArpKey start_key(start_ip, rt->vrf());
     341             : 
     342             :     ArpProto::ArpIterator start_iter =
     343           0 :         vrf_state_->arp_proto->FindUpperBoundArpEntry(start_key);
     344             : 
     345             : 
     346           0 :     while (start_iter != vrf_state_->arp_proto->arp_cache().end() &&
     347           0 :            start_iter->first.vrf == rt->vrf() &&
     348           0 :            IsIp4SubnetMember(Ip4Address(start_iter->first.ip),
     349           0 :                              rt->prefix_address().to_v4(), plen)) {
     350           0 :         start_iter->second->Resync(policy_, vn_list_, sg_list_, tag_list_);
     351           0 :         start_iter++;
     352             :     }
     353           0 : }
     354             : 
     355         571 : void ArpDBState::Delete(const InetUnicastRouteEntry *rt) {
     356         571 :     int plen = rt->prefix_length();
     357         571 :     uint32_t start_ip = rt->prefix_address().to_v4().to_ulong();
     358             : 
     359         571 :     ArpKey start_key(start_ip, rt->vrf());
     360             : 
     361             :     ArpProto::ArpIterator start_iter =
     362         571 :         vrf_state_->arp_proto->FindUpperBoundArpEntry(start_key);
     363             : 
     364         586 :     while (start_iter != vrf_state_->arp_proto->arp_cache().end() &&
     365         586 :            start_iter->first.vrf == rt->vrf() &&
     366           6 :            IsIp4SubnetMember(Ip4Address(start_iter->first.ip),
     367         579 :                              rt->prefix_address().to_v4(), plen)) {
     368           2 :         ArpProto::ArpIterator tmp = start_iter++;
     369           2 :         if (tmp->second->DeleteArpRoute()) {
     370           0 :             vrf_state_->arp_proto->DeleteArpEntry(tmp->second);
     371             :         }
     372             :     }
     373         571 : }
     374             : 
     375        2744 : void ArpDBState::Update(const AgentRoute *rt) {
     376        2744 :     if (arp_path_preference_state_) {
     377        1901 :         arp_path_preference_state_->SendArpRequestForAllIntf(rt);
     378             :     }
     379             : 
     380             :     const InetUnicastRouteEntry *ip_rt =
     381        2744 :         dynamic_cast<const InetUnicastRouteEntry *>(rt);
     382        2744 :     if (ip_rt == NULL) {
     383        1509 :         return;
     384             :     }
     385        1235 :     const NextHop *anh =ip_rt->GetActiveNextHop();
     386        1235 :     if (anh == NULL) {
     387           0 :         return;
     388             :     }
     389             : 
     390        1235 :     if (anh->GetType() == NextHop::RESOLVE) {
     391           0 :         resolve_route_ = true;
     392             :     }
     393             : 
     394        1235 :     bool policy = anh->PolicyEnabled();
     395        1235 :     const SecurityGroupList sg = ip_rt->GetActivePath()->sg_list();
     396        1235 :     const TagList tag = ip_rt->GetActivePath()->tag_list();
     397             : 
     398             : 
     399        2215 :     if (policy_ != policy || sg != sg_list_ || tag != tag_list_ ||
     400         980 :         vn_list_ != ip_rt->GetActivePath()->dest_vn_list()) {
     401         403 :         policy_ = policy;
     402         403 :         sg_list_ = sg;
     403         403 :         tag_list_ = tag;
     404         403 :         vn_list_ = ip_rt->GetActivePath()->dest_vn_list();
     405         403 :         if (resolve_route_) {
     406           0 :             UpdateArpRoutes(ip_rt);
     407             :         }
     408             :     }
     409        1235 : }
     410             : 
     411        1847 : void ArpVrfState::EvpnRouteUpdate(DBTablePartBase *part, DBEntryBase *entry) {
     412        1847 :     EvpnRouteEntry *route = static_cast<EvpnRouteEntry *>(entry);
     413             :     /* Ignore route updates for Non-IPv4 addresses */
     414        1847 :     if (!route->prefix_address().is_v4()) {
     415           0 :         return;
     416             :     }
     417             : 
     418        1847 :     ArpDBState *state = static_cast<ArpDBState *>(entry->GetState(part->parent(),
     419             :                                                   evpn_route_table_listener_id));
     420             : 
     421        1847 :     if (entry->IsDeleted() || deleted) {
     422         338 :         if (state) {
     423         338 :             entry->ClearState(part->parent(), evpn_route_table_listener_id);
     424         338 :             delete state;
     425             :         }
     426         338 :         return;
     427             :     }
     428             : 
     429        1509 :     if (state == NULL) {
     430         338 :         state = new ArpDBState(this, route->vrf_id(), route->prefix_address(),
     431         338 :                                route->prefix_length());
     432         338 :         entry->SetState(part->parent(), evpn_route_table_listener_id, state);
     433             :     }
     434             : 
     435        1509 :     state->Update(route);
     436             : }
     437             : 
     438        2047 : void ArpVrfState::RouteUpdate(DBTablePartBase *part, DBEntryBase *entry) {
     439        2047 :     InetUnicastRouteEntry *route = static_cast<InetUnicastRouteEntry *>(entry);
     440             : 
     441             :     ArpDBState *state =
     442             :         static_cast<ArpDBState *>
     443        2047 :         (entry->GetState(part->parent(), route_table_listener_id));
     444             : 
     445        2047 :     const InterfaceNH *intf_nh = dynamic_cast<const InterfaceNH *>(
     446        2047 :             route->GetActiveNextHop());
     447        2047 :     const Interface *intf = (intf_nh) ?
     448         827 :         static_cast<const Interface *>(intf_nh->GetInterface()) : NULL;
     449             : 
     450        2047 :     ArpKey key(route->prefix_address().to_v4().to_ulong(), route->vrf());
     451        2047 :     ArpEntry *arpentry = arp_proto->GratuitousArpEntry(key, intf);
     452        2047 :     if (entry->IsDeleted() || deleted) {
     453         613 :         if (state) {
     454         571 :             arp_proto->DeleteGratuitousArpEntry(arpentry);
     455         571 :             entry->ClearState(part->parent(), route_table_listener_id);
     456         571 :             state->Delete(route);
     457         571 :             delete state;
     458             :         }
     459         613 :         return;
     460             :     }
     461             : 
     462        1434 :     if (!state) {
     463         571 :         state = new ArpDBState(this, route->vrf_id(), route->prefix_address(),
     464         571 :                                route->prefix_length());
     465         571 :         entry->SetState(part->parent(), route_table_listener_id, state);
     466             :     }
     467             : 
     468        1434 :     state->UpdateMac(intf_nh);
     469             : 
     470        1798 :     if (route->vrf()->GetName() == agent->fabric_vrf_name() && intf_nh &&
     471        1798 :         route->GetActiveNextHop()->GetType() == NextHop::RECEIVE &&
     472        1434 :         arp_proto->agent()->router_id() == route->prefix_address().to_v4()) {
     473             :         //Send Grat ARP
     474           0 :         arp_proto->AddGratuitousArpEntry(key);
     475           0 :         arp_proto->SendArpIpc(ArpProto::ARP_SEND_GRATUITOUS,
     476           0 :                               route->prefix_address().to_v4().to_ulong(), route->vrf(),
     477           0 :                               arp_proto->ip_fabric_interface());
     478             :     } else {
     479        1434 :         if (intf_nh) {
     480        1553 :             if (intf->type() == Interface::VM_INTERFACE &&
     481         726 :                 static_cast<const VmInterface*>(intf)->IsActive()) {
     482         726 :                 ArpKey intf_key(route->prefix_address().to_v4().to_ulong(), route->vrf());
     483         726 :                 arp_proto->AddGratuitousArpEntry(intf_key);
     484        2178 :                 arp_proto->SendArpIpc(ArpProto::ARP_SEND_GRATUITOUS,
     485        1452 :                         route->prefix_address().to_v4().to_ulong(), intf->vrf(), intf);
     486             :             }
     487             :         }
     488             :     }
     489             : 
     490             :     //Check if there is a local VM path, if yes send a
     491             :     //ARP request, to trigger route preference state machine
     492        1434 :     if (state && route->vrf()->GetName() != agent->fabric_vrf_name()) {
     493        1235 :         state->Update(route);
     494             :     }
     495             : }
     496             : 
     497          40 : bool ArpVrfState::DeleteRouteState(DBTablePartBase *part, DBEntryBase *entry) {
     498          40 :     RouteUpdate(part, entry);
     499          40 :     return true;
     500             : }
     501             : 
     502           0 : bool ArpVrfState::DeleteEvpnRouteState(DBTablePartBase *part,
     503             :                                        DBEntryBase *entry) {
     504           0 :     EvpnRouteUpdate(part, entry);
     505           0 :     return true;
     506             : }
     507             : 
     508             : 
     509         223 : void ArpVrfState::Delete() {
     510         223 :     if (managed_delete_walk_ref.get() == NULL)
     511          95 :         return;
     512             : 
     513         128 :     rt_table->WalkAgain(managed_delete_walk_ref);
     514         128 :     if (evpn_walk_ref_.get())
     515         128 :         evpn_rt_table->WalkAgain(evpn_walk_ref_);
     516         128 :     deleted = true;
     517             : }
     518             : 
     519         148 : void ArpVrfState::WalkDone(DBTableBase *partition, ArpVrfState *state) {
     520         148 :     if (partition == state->rt_table) {
     521          74 :         state->rt_table->ReleaseWalker(state->managed_delete_walk_ref);
     522          74 :         state->managed_delete_walk_ref = NULL;
     523          74 :         state->l3_walk_completed_ = true;
     524             :     } else {
     525             :         //Get rt table from partition
     526          74 :         state->evpn_rt_table->ReleaseWalker(state->evpn_walk_ref_);
     527          74 :         state->evpn_walk_ref_ = NULL;
     528          74 :         state->evpn_walk_completed_ = true;
     529             :     }
     530         148 :     if (state->PreWalkDone(partition)) {
     531          74 :         delete state;
     532             :     }
     533         148 : }
     534             : 
     535         148 : bool ArpVrfState::PreWalkDone(DBTableBase *partition) {
     536         148 :     if (arp_proto->ValidateAndClearVrfState(vrf, this) == false) {
     537          74 :         return false;
     538             :     }
     539             : 
     540          74 :     rt_table->Unregister(route_table_listener_id);
     541          74 :     table_delete_ref.Reset(NULL);
     542             : 
     543          74 :     evpn_rt_table->Unregister(evpn_route_table_listener_id);
     544          74 :     evpn_table_delete_ref.Reset(NULL);
     545          74 :     return true;
     546             : }
     547             : 
     548         782 : ArpPathPreferenceState* ArpVrfState::Locate(const IpAddress &ip, uint8_t plen) {
     549         782 :     ArpPathPreferenceStateKey key(ip, plen);
     550         782 :     ArpPathPreferenceState* ptr = NULL;
     551         782 :     ArpPathPreferenceStateMap::iterator it = arp_path_preference_map_.find(key);
     552         782 :     if (it == arp_path_preference_map_.end()) {
     553         559 :         ptr = new ArpPathPreferenceState(this, vrf->vrf_id(), ip, plen);
     554         559 :         arp_path_preference_map_.insert(ArpPathPreferenceStatePair(key, ptr));
     555             :     } else {
     556         223 :         ptr = it->second;
     557             :     }
     558         782 :     return ptr;
     559             : }
     560             : 
     561         559 : void ArpVrfState::Erase(const IpAddress &ip, uint8_t plen) {
     562         559 :     ArpPathPreferenceStateKey key(ip, plen);
     563         559 :     ArpPathPreferenceStateMap::iterator it = arp_path_preference_map_.find(key);
     564         559 :     if (it != arp_path_preference_map_.end()) {
     565         559 :         arp_path_preference_map_.erase(it);
     566             :     }
     567         559 : }
     568             : 
     569             : 
     570           0 : ArpPathPreferenceState* ArpVrfState::Get(const IpAddress ip, uint8_t plen) {
     571           0 :     ArpPathPreferenceStateKey key(ip, plen);
     572           0 :     ArpPathPreferenceStateMap::iterator it = arp_path_preference_map_.find(key);
     573           0 :     if (it != arp_path_preference_map_.end()) {
     574           0 :         return it->second;
     575             :     }
     576           0 :     return NULL;
     577             : }
     578             : 
     579          74 : ArpVrfState::ArpVrfState(Agent *agent_ptr, ArpProto *proto, VrfEntry *vrf_entry,
     580          74 :                          AgentRouteTable *table, AgentRouteTable *evpn_table):
     581          74 :     agent(agent_ptr), arp_proto(proto), vrf(vrf_entry), rt_table(table),
     582          74 :     evpn_rt_table(evpn_table), route_table_listener_id(DBTableBase::kInvalidId),
     583          74 :     evpn_route_table_listener_id(DBTableBase::kInvalidId),
     584          74 :     table_delete_ref(this, table->deleter()),
     585          74 :     evpn_table_delete_ref(this, evpn_table->deleter()),
     586          74 :     deleted(false),
     587         148 :     l3_walk_completed_(false), evpn_walk_completed_(false) {
     588         148 :     evpn_walk_ref_ = evpn_rt_table->AllocWalker(
     589             :             boost::bind(&ArpVrfState::DeleteEvpnRouteState, this, _1, _2),
     590          74 :             boost::bind(&ArpVrfState::WalkDone, _2, this));
     591         148 :     managed_delete_walk_ref = rt_table->AllocWalker(
     592             :             boost::bind(&ArpVrfState::DeleteRouteState, this, _1, _2),
     593          74 :             boost::bind(&ArpVrfState::WalkDone, _2, this));
     594          74 : }
     595             : 
     596         148 : ArpVrfState::~ArpVrfState() {
     597          74 :     assert(arp_path_preference_map_.size() == 0);
     598         148 : }
     599             : 
     600        1421 : void ArpProto::InterfaceNotify(DBEntryBase *entry) {
     601        1421 :     Interface *intf = static_cast<Interface *>(entry);
     602             :     ArpInterfaceState *state = static_cast<ArpInterfaceState *>
     603        1421 :         (entry->GetState(entry->get_table_partition()->parent(),
     604             :                        interface_table_listener_id_));
     605             : 
     606             :     /* On phy intf down, delete its associated arp route and set state to resolving */
     607        1421 :     if (agent_->is_l3mh() && intf->type() == Interface::PHYSICAL && intf->os_oper_state() == false) {
     608           0 :         InterfaceArpInfo &intf_entry = ArpMapIndexToEntry(intf->id());
     609           0 :         ArpKeySet::iterator key_it = intf_entry.arp_key_list.begin();
     610           0 :         while (key_it != intf_entry.arp_key_list.end()) {
     611           0 :             ArpKey key = *key_it;
     612           0 :             ++key_it;
     613           0 :             ArpEntry *arp_entry = FindArpEntry(key);
     614           0 :             if (arp_entry) {
     615           0 :                 arp_entry->SetState(ArpEntry::RESOLVING);
     616           0 :                 arp_entry->DeleteArpRoute();
     617             :             }
     618             :         }
     619           0 :         return;
     620             :     }
     621             : 
     622        1421 :     Interface *itf = static_cast<Interface *>(entry);
     623        1421 :     if (entry->IsDeleted()) {
     624         176 :         if (state) {
     625         176 :             intf->ClearState(intf->get_table_partition()->parent(),
     626             :                              interface_table_listener_id_);
     627         176 :             delete state;
     628             :         }
     629             : 
     630         176 :         InterfaceArpMap::iterator it = interface_arp_map_.find(itf->id());
     631         176 :         if (it != interface_arp_map_.end()) {
     632           4 :             InterfaceArpInfo &intf_entry = it->second;
     633           4 :             ArpKeySet::iterator key_it = intf_entry.arp_key_list.begin();
     634           6 :             while (key_it != intf_entry.arp_key_list.end()) {
     635           2 :                 ArpKey key = *key_it;
     636           2 :                 ++key_it;
     637           2 :                 ArpIterator arp_it = arp_cache_.find(key);
     638           2 :                 if (arp_it != arp_cache_.end()) {
     639           0 :                     ArpEntry *arp_entry = arp_it->second;
     640           0 :                     if (arp_entry->DeleteArpRoute()) {
     641           0 :                         DeleteArpEntry(arp_it);
     642             :                     }
     643             :                 }
     644             :             }
     645           4 :             intf_entry.arp_key_list.clear();
     646           4 :             interface_arp_map_.erase(it);
     647             :         }
     648             : 
     649         176 :         if (itf->type() == Interface::VM_INTERFACE) {
     650             :             ArpKey key(static_cast<VmInterface *>
     651         169 :                        (itf)->primary_ip_addr().to_ulong(), itf->vrf());
     652         169 :             ArpEntry *arpentry = GratuitousArpEntry(key, itf);
     653         169 :             if (arpentry) {
     654           0 :                 DeleteGratuitousArpEntry(arpentry);
     655             :             }
     656             :         }
     657             : 
     658         179 :         if (itf->type() == Interface::PHYSICAL &&
     659           3 :             itf->name() == agent_->fabric_interface_name()) {
     660           2 :             set_ip_fabric_interface(NULL);
     661           2 :             set_ip_fabric_interface_index(-1);
     662             :         }
     663             :     } else {
     664        1245 :         if (state == NULL) {
     665         176 :             state = new ArpInterfaceState(intf);
     666         176 :             intf->SetState(entry->get_table_partition()->parent(),
     667             :                            interface_table_listener_id_, state);
     668             :         }
     669             : 
     670        1249 :         if (itf->type() == Interface::PHYSICAL &&
     671           4 :             itf->name() == agent_->fabric_interface_name()) {
     672           2 :             set_ip_fabric_interface(itf);
     673           2 :             set_ip_fabric_interface_index(itf->id());
     674           2 :             if (run_with_vrouter_) {
     675           0 :                 set_ip_fabric_interface_mac(itf->mac());
     676             :             } else {
     677           2 :                 set_ip_fabric_interface_mac(MacAddress());
     678             :             }
     679             :         }
     680             : 
     681        1245 :         if (itf->type() == Interface::VM_INTERFACE) {
     682        1231 :             const VmInterface *vm_intf =
     683             :                 static_cast<const VmInterface *>(itf);
     684        1231 :             VrfEntry *forwarding_vrf = NULL;
     685        1231 :             if (vm_intf->vrf()) {
     686         977 :                 forwarding_vrf = vm_intf->vrf()->forwarding_vrf();
     687             :             }
     688        1231 :             state->SetVrf(vm_intf->vrf(), forwarding_vrf);
     689             :         }
     690             :     }
     691             : }
     692             : 
     693           4 : ArpProto::InterfaceArpInfo& ArpProto::ArpMapIndexToEntry(uint32_t idx) {
     694           4 :     InterfaceArpMap::iterator it = interface_arp_map_.find(idx);
     695           4 :     if (it == interface_arp_map_.end()) {
     696           2 :         InterfaceArpInfo entry;
     697           2 :         std::pair<InterfaceArpMap::iterator, bool> ret;
     698           2 :         ret = interface_arp_map_.insert(InterfaceArpPair(idx, entry));
     699           2 :         return ret.first->second;
     700           2 :     } else {
     701           2 :         return it->second;
     702             :     }
     703             : }
     704             : 
     705           4 : void ArpProto::IncrementStatsArpRequest(uint32_t idx) {
     706           4 :     InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
     707           4 :     entry.stats.arp_req++;
     708           4 : }
     709             : 
     710           0 : void ArpProto::IncrementStatsArpReply(uint32_t idx) {
     711           0 :     InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
     712           0 :     entry.stats.arp_replies++;
     713           0 : }
     714             : 
     715           0 : void ArpProto::IncrementStatsResolved(uint32_t idx) {
     716           0 :     InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
     717           0 :     entry.stats.resolved++;
     718           0 : }
     719             : 
     720           0 : uint32_t ArpProto::ArpRequestStatsCounter(uint32_t idx) {
     721           0 :     InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
     722           0 :     return entry.stats.arp_req;
     723             : }
     724             : 
     725           0 : uint32_t ArpProto::ArpReplyStatsCounter(uint32_t idx) {
     726           0 :     InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
     727           0 :     return entry.stats.arp_replies;
     728             : }
     729             : 
     730           0 : uint32_t ArpProto::ArpResolvedStatsCounter(uint32_t idx) {
     731           0 :     InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
     732           0 :     return entry.stats.resolved;
     733             : }
     734             : 
     735           0 : void ArpProto::ClearInterfaceArpStats(uint32_t idx) {
     736           0 :     InterfaceArpInfo &entry = ArpMapIndexToEntry(idx);
     737           0 :     entry.stats.Reset();
     738           0 : }
     739             : 
     740        3457 : void ArpProto::NextHopNotify(DBEntryBase *entry) {
     741        3457 :     NextHop *nh = static_cast<NextHop *>(entry);
     742             : 
     743        3457 :     switch(nh->GetType()) {
     744           6 :     case NextHop::ARP: {
     745           6 :         ArpNH *arp_nh = (static_cast<ArpNH *>(nh));
     746           6 :         if (arp_nh->IsDeleted()) {
     747           2 :             SendArpIpc(ArpProto::ARP_DELETE, arp_nh->GetIp()->to_ulong(),
     748             :                        arp_nh->GetVrf(), arp_nh->GetInterface());
     749           4 :         } else if (arp_nh->IsValid() == false && arp_nh->GetInterface()) {
     750           4 :             SendArpIpc(ArpProto::ARP_RESOLVE, arp_nh->GetIp()->to_ulong(),
     751             :                        arp_nh->GetVrf(), arp_nh->GetInterface());
     752             :         }
     753           6 :         break;
     754             :     }
     755             : 
     756        3451 :     default:
     757        3451 :         break;
     758             :     }
     759        3457 : }
     760             : 
     761           4 : bool ArpProto::TimerExpiry(ArpKey &key, uint32_t timer_type,
     762             :                            const Interface* itf) {
     763           6 :     if (arp_cache_.find(key) != arp_cache_.end() ||
     764           6 :         gratuitous_arp_cache_.find(key) != gratuitous_arp_cache_.end()) {
     765           4 :         if (itf) {
     766           4 :             SendArpIpc((ArpProto::ArpMsgType)timer_type, key, itf);
     767             :         }
     768             :     }
     769           4 :     return false;
     770             : }
     771             : 
     772         726 :  void ArpProto::AddGratuitousArpEntry(ArpKey &key) {
     773         726 :      ArpEntrySet empty_set;
     774         726 :      gratuitous_arp_cache_.insert(GratuitousArpCachePair(key, empty_set));
     775         726 : }
     776             : 
     777         572 : void ArpProto::DeleteGratuitousArpEntry(ArpEntry *entry) {
     778         572 :     if (!entry)
     779         571 :         return ;
     780             : 
     781           1 :     ArpProto::GratuitousArpIterator iter = gratuitous_arp_cache_.find(entry->key());
     782           1 :     if (iter == gratuitous_arp_cache_.end()) {
     783           0 :         return;
     784             :     }
     785             : 
     786           1 :     iter->second.erase(entry);
     787           1 :     delete entry;
     788           1 :     if (iter->second.empty()) {
     789           1 :         gratuitous_arp_cache_.erase(iter);
     790             :     }
     791             : }
     792             : 
     793             : ArpEntry *
     794        2218 : ArpProto::GratuitousArpEntry(const ArpKey &key, const Interface *intf) {
     795        2218 :     ArpProto::GratuitousArpIterator it = gratuitous_arp_cache_.find(key);
     796        2218 :     if (it == gratuitous_arp_cache_.end())
     797        1327 :         return NULL;
     798             : 
     799         891 :     for (ArpEntrySet::iterator sit = it->second.begin();
     800        1025 :          sit != it->second.end(); sit++) {
     801         555 :         ArpEntry *entry = *sit;
     802         555 :         if (entry->get_interface() == intf)
     803         421 :             return *sit;
     804             :     }
     805             : 
     806         470 :     return NULL;
     807             : }
     808             : 
     809             : ArpProto::GratuitousArpIterator
     810         726 : ArpProto::GratuitousArpEntryIterator(const ArpKey &key, bool *key_valid) {
     811         726 :     ArpProto::GratuitousArpIterator it = gratuitous_arp_cache_.find(key);
     812         726 :     if (it == gratuitous_arp_cache_.end())
     813         185 :         return it;
     814         541 :     const VrfEntry *vrf = key.vrf;
     815         541 :     if (!vrf)
     816           0 :         return it;
     817             :     const ArpVrfState *state = static_cast<const ArpVrfState *>
     818         541 :                          (vrf->GetState(vrf->get_table_partition()->parent(),
     819             :                           vrf_table_listener_id_));
     820             :     // If VRF is delete marked, do not add ARP entries to cache
     821         541 :     if (state == NULL || state->deleted == true)
     822           0 :         return it;
     823         541 :     *key_valid = true;
     824         541 :     return it;
     825             : }
     826             : 
     827         732 : void ArpProto::SendArpIpc(ArpProto::ArpMsgType type, in_addr_t ip,
     828             :                           const VrfEntry *vrf, InterfaceConstRef itf) {
     829         732 :     ArpIpc *ipc = new ArpIpc(type, ip, vrf, itf);
     830         732 :     agent_->pkt()->pkt_handler()->SendMessage(PktHandler::ARP, ipc);
     831         732 : }
     832             : 
     833           4 : void ArpProto::SendArpIpc(ArpProto::ArpMsgType type, ArpKey &key,
     834             :                           InterfaceConstRef itf) {
     835           4 :     ArpIpc *ipc = new ArpIpc(type, key, itf);
     836           4 :     agent_->pkt()->pkt_handler()->SendMessage(PktHandler::ARP, ipc);
     837           4 : }
     838             : 
     839           2 : bool ArpProto::AddArpEntry(ArpEntry *entry) {
     840           2 :     const VrfEntry *vrf = entry->key().vrf;
     841             :     const ArpVrfState *state = static_cast<const ArpVrfState *>
     842           2 :                          (vrf->GetState(vrf->get_table_partition()->parent(),
     843             :                           vrf_table_listener_id_));
     844             :     // If VRF is delete marked, do not add ARP entries to cache
     845           2 :     if (state == NULL || state->deleted == true)
     846           0 :         return false;
     847             : 
     848           2 :     bool ret = arp_cache_.insert(ArpCachePair(entry->key(), entry)).second;
     849           2 :     uint32_t intf_id = entry->get_interface()->id();
     850           2 :     InterfaceArpMap::iterator it = interface_arp_map_.find(intf_id);
     851           2 :     if (it == interface_arp_map_.end()) {
     852           2 :         InterfaceArpInfo intf_entry;
     853           2 :         intf_entry.arp_key_list.insert(entry->key());
     854           2 :         interface_arp_map_.insert(InterfaceArpPair(intf_id, intf_entry));
     855           2 :     } else {
     856           0 :         InterfaceArpInfo &intf_entry = it->second;
     857           0 :         ArpKeySet::iterator key_it = intf_entry.arp_key_list.find(entry->key());
     858           0 :         if (key_it == intf_entry.arp_key_list.end()) {
     859           0 :             intf_entry.arp_key_list.insert(entry->key());
     860             :         }
     861             :     }
     862           2 :     return ret;
     863             : }
     864             : 
     865           2 : bool ArpProto::DeleteArpEntry(ArpEntry *entry) {
     866           2 :     if (!entry)
     867           0 :         return false;
     868             : 
     869           2 :     ArpProto::ArpIterator iter = arp_cache_.find(entry->key());
     870           2 :     if (iter == arp_cache_.end()) {
     871           0 :         return false;
     872             :     }
     873             : 
     874           2 :     DeleteArpEntry(iter);
     875           2 :     return true;
     876             : }
     877             : 
     878             : ArpProto::ArpIterator
     879           2 : ArpProto::DeleteArpEntry(ArpProto::ArpIterator iter) {
     880           2 :     ArpEntry *entry = iter->second;
     881           2 :     arp_cache_.erase(iter++);
     882           2 :     delete entry;
     883           2 :     return iter;
     884             : }
     885             : 
     886         193 : ArpEntry *ArpProto::FindArpEntry(const ArpKey &key) {
     887         193 :     ArpIterator it = arp_cache_.find(key);
     888         193 :     if (it == arp_cache_.end())
     889         187 :         return NULL;
     890           6 :     return it->second;
     891             : }
     892             : 
     893         148 : bool ArpProto::ValidateAndClearVrfState(VrfEntry *vrf,
     894             :                                         const ArpVrfState *vrf_state) {
     895         148 :     if (!vrf_state->deleted) {
     896           0 :         ARP_TRACE(Trace, "ARP state not cleared - VRF is not delete marked",
     897             :                   "", vrf->GetName(), "");
     898           0 :         return false;
     899             :     }
     900             : 
     901         148 :     if (vrf_state->l3_walk_completed() == false) {
     902           0 :         return false;
     903             :     }
     904             : 
     905         148 :     if (vrf_state->evpn_walk_completed() == false) {
     906          74 :         return false;
     907             :     }
     908             : 
     909         148 :     if (vrf_state->managed_delete_walk_ref.get() != NULL ||
     910          74 :         vrf_state->evpn_walk_ref_.get() != NULL) {
     911           0 :         ARP_TRACE(Trace, "ARP state not cleared - Route table walk not complete",
     912             :                   "", vrf->GetName(), "");
     913           0 :         return false;
     914             :     }
     915             : 
     916             :     DBState *state = static_cast<DBState *>
     917          74 :         (vrf->GetState(vrf->get_table_partition()->parent(),
     918             :                        vrf_table_listener_id_));
     919          74 :     if (state) {
     920          74 :         vrf->ClearState(vrf->get_table_partition()->parent(),
     921             :                         vrf_table_listener_id_);
     922             :     }
     923          74 :     return true;
     924             : }
     925             : 
     926             : ArpProto::ArpIterator
     927         571 : ArpProto::FindUpperBoundArpEntry(const ArpKey &key) {
     928         571 :         return arp_cache_.upper_bound(key);
     929             : }
     930             : 
     931             : ArpProto::ArpIterator
     932           0 : ArpProto::FindLowerBoundArpEntry(const ArpKey &key) {
     933           0 :         return arp_cache_.lower_bound(key);
     934             : }
     935             : 
     936           0 : void ArpPathPreferenceState::HandleArpReply(Ip4Address sip, uint32_t itf) {
     937           0 :     WaitForTrafficIntfMap::iterator it = l3_wait_for_traffic_map_.find(itf);
     938           0 :     if (it == l3_wait_for_traffic_map_.end()) {
     939           0 :         return;
     940             :     }
     941             : 
     942           0 :     InterfaceArpPathPreferenceInfo &data = it->second;
     943             :     // reset arp_try_count to 0.
     944           0 :     data.arp_try_count = 0;
     945             : 
     946           0 :     if (data.prev_responded_ip == sip) {
     947           0 :         ++data.arp_reply_count;
     948           0 :         data.arp_failure_count = 0;
     949             :     } else {
     950           0 :         data.prev_responded_ip = sip;
     951           0 :         data.arp_send_count = 0;
     952             :     }
     953             : }
     954             : 
     955           0 : void ArpProto::HandlePathPreferenceArpReply(const VrfEntry *vrf, uint32_t itf,
     956             :                                             Ip4Address sip) {
     957           0 :     if (!vrf) {
     958           0 :         return;
     959             :     }
     960           0 :     InetUnicastRouteEntry *rt = vrf->GetUcRoute(sip);
     961           0 :     if (!rt) {
     962           0 :         return;
     963             :     }
     964             : 
     965             :     ArpVrfState *state = static_cast<ArpVrfState *>
     966           0 :         (vrf->GetState(vrf->get_table_partition()->parent(),
     967             :                        vrf_table_listener_id_));
     968           0 :     if (!state) {
     969           0 :         return;
     970             :     }
     971           0 :     ArpPathPreferenceState* pstate = state->Get(sip, rt->prefix_length());
     972           0 :     if (!pstate) {
     973           0 :         return;
     974             :     }
     975           0 :     pstate->HandleArpReply(sip, itf);
     976             : }
     977             : 
     978         176 : ArpInterfaceState::ArpInterfaceState(Interface *intf):
     979         176 :     intf_(intf), vrf_(NULL), fabric_vrf_(NULL), walk_ref_(NULL) {
     980         176 : }
     981             : 
     982         352 : ArpInterfaceState::~ArpInterfaceState() {
     983         176 :     if (walk_ref_.get() && vrf_) {
     984           2 :         vrf_->GetEvpnRouteTable()->ReleaseWalker(walk_ref_);
     985             :     }
     986         352 : }
     987             : 
     988        1231 : void ArpInterfaceState::SetVrf(VrfEntry *vrf, VrfEntry *fabric_vrf) {
     989        1231 :     bool walk = false;
     990             : 
     991        1231 :     if (vrf_ != vrf) {
     992         169 :         if (walk_ref_.get() && vrf_) {
     993           0 :             vrf_->GetEvpnRouteTable()->ReleaseWalker(walk_ref_);
     994             :         }
     995         169 :         vrf_ = vrf;
     996             :     }
     997             : 
     998        1231 :     if (fabric_vrf_ != fabric_vrf) {
     999           2 :         fabric_vrf_ = fabric_vrf;
    1000           2 :         walk = true;
    1001             :     }
    1002             : 
    1003        1231 :     if (vrf_ == NULL) {
    1004         254 :         return;
    1005             :     }
    1006             : 
    1007         977 :     if (walk && walk_ref_.get() == NULL) {
    1008           4 :         walk_ref_ = vrf_->GetEvpnRouteTable()->AllocWalker(
    1009             :                 boost::bind(&ArpInterfaceState::WalkNotify, this, _1, _2),
    1010           2 :                 boost::bind(&ArpInterfaceState::WalkDone, this, _2));
    1011             :     }
    1012             : 
    1013         977 :     if (vrf_->vn() && vrf_->vn()->bridging()) {
    1014         934 :         if (walk) {
    1015           0 :             vrf_->GetEvpnRouteTable()->WalkAgain(walk_ref_);
    1016             :         }
    1017             :     }
    1018             : }
    1019             : 
    1020           0 : void ArpInterfaceState::WalkDone(DBTableBase *part) {
    1021           0 : }
    1022             : 
    1023           0 : bool ArpInterfaceState::WalkNotify(DBTablePartBase *partition,
    1024             :                                    DBEntryBase *e) {
    1025           0 :     const EvpnRouteEntry *evpn = static_cast<const EvpnRouteEntry *>(e);
    1026             : 
    1027           0 :     if (evpn->prefix_address().is_v4() == false) {
    1028           0 :         return true;
    1029             :     }
    1030             : 
    1031           0 :     if (evpn->prefix_address() == Ip4Address(0)) {
    1032           0 :         return true;
    1033             :     }
    1034             : 
    1035             :     const InterfaceNH *nh =
    1036           0 :         dynamic_cast<const InterfaceNH *>(evpn->GetActiveNextHop());
    1037           0 :     if (nh && nh->GetInterface() == intf_) {
    1038           0 :         return true;
    1039             :     }
    1040             : 
    1041           0 :     EvpnAgentRouteTable *table = static_cast<EvpnAgentRouteTable *>(evpn->get_table());
    1042           0 :     const VmInterface *vmi = static_cast<const VmInterface *>(intf_.get());
    1043           0 :     Agent *agent = table->agent();
    1044             :     boost::shared_ptr<PktInfo> pkt(new PktInfo(agent, ARP_TX_BUFF_LEN,
    1045           0 :                                    PktHandler::ARP, 0));
    1046           0 :     ArpHandler arp_handler(agent, pkt, *(agent->event_manager()->io_service()));
    1047             : 
    1048           0 :     MacAddress smac = vmi->GetVifMac(agent);
    1049           0 :     if (vrf_->forwarding_vrf() == NULL) {
    1050           0 :         smac = evpn->mac();
    1051             :     }
    1052             : 
    1053           0 :     agent->GetArpProto()->IncrementStatsVmGarpReq();
    1054           0 :     arp_handler.SendArp(ARPOP_REQUEST, smac, evpn->prefix_address().to_v4().to_ulong(),
    1055           0 :                         smac, vmi->vm_mac(), evpn->prefix_address().to_v4().to_ulong(),
    1056             :                         intf_->id(), intf_->vrf()->vrf_id());
    1057           0 :     return true;
    1058           0 : }

Generated by: LCOV version 1.14