LCOV - code coverage report
Current view: top level - vnsw/agent/oper - route_leak.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 202 289 69.9 %
Date: 2026-06-18 01:51:13 Functions: 18 25 72.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #include <cmn/agent_cmn.h>
       2             : #include <route/route.h>
       3             : #include <oper/nexthop.h>
       4             : #include <oper/tunnel_nh.h>
       5             : #include <oper/route_common.h>
       6             : #include <oper/vrf.h>
       7             : #include <oper/vrouter.h>
       8             : #include <oper/route_leak.h>
       9             : 
      10           0 : void RouteLeakState::AddIndirectRoute(const AgentRoute *route) {
      11           0 :     InetUnicastAgentRouteTable *table = dest_vrf_->GetInet4UnicastRouteTable();
      12           0 :     const InetUnicastRouteEntry *uc_rt =
      13             :         static_cast<const InetUnicastRouteEntry *>(route);
      14           0 :     const AgentPath *active_path = uc_rt->GetActivePath();
      15           0 :     const TunnelNH *nh = dynamic_cast<const TunnelNH *>(active_path->nexthop());
      16             : 
      17           0 :     if (nh == NULL) {
      18           0 :         return;
      19             :     }
      20             : 
      21           0 :     Ip4Address gw_ip = *(nh->GetDip());
      22             : 
      23           0 :     if (gw_ip == uc_rt->prefix_address().to_v4() &&
      24           0 :         InetUnicastAgentRouteTable::FindResolveRoute(dest_vrf_->GetName(),
      25           0 :                                                      uc_rt->prefix_address().to_v4())) {
      26           0 :         bool resolved = false;
      27           0 :         MacAddress mac;
      28           0 :         const Interface *itf = agent_->vhost_interface();
      29           0 :         ArpNHKey nh_key(dest_vrf_->GetName(), uc_rt->prefix_address().to_v4(), false);
      30           0 :         ArpNH *arp_nh = static_cast<ArpNH *>(agent_->nexthop_table()->
      31           0 :                                              FindActiveEntry(&nh_key));
      32           0 :         if (arp_nh) {
      33           0 :             resolved = arp_nh->GetResolveState();
      34           0 :             mac = arp_nh->GetMac();
      35           0 :             itf = arp_nh->GetInterface();
      36             :         }
      37             :         InetUnicastAgentRouteTable::CheckAndAddArpRoute
      38           0 :             (dest_vrf_->GetName(), uc_rt->prefix_address().to_v4(), mac, itf,
      39             :              resolved, active_path->dest_vn_list(),
      40             :              active_path->sg_list(), active_path->tag_list());
      41           0 :         return;
      42           0 :     }
      43             : 
      44           0 :     const Peer *peer = agent_->local_peer();
      45           0 :     peer_list_.insert(peer);
      46             : 
      47           0 :     if (gw_ip == uc_rt->prefix_address().to_v4()) {
      48           0 :         gw_ip = agent_->vhost_default_gateway()[0];
      49             :     }
      50             : 
      51           0 :     table->AddGatewayRoute(peer, dest_vrf_->GetName(),
      52           0 :                            uc_rt->prefix_address().to_v4(),
      53           0 :                            uc_rt->prefix_length(),
      54           0 :                            AddressList(1, gw_ip),
      55             :                            active_path->dest_vn_list(),
      56             :                            MplsTable::kInvalidExportLabel,
      57             :                            active_path->sg_list(),
      58             :                            active_path->tag_list(),
      59             :                            active_path->communities(), true);
      60             : }
      61             : 
      62           8 : void RouteLeakState::AddInterfaceRoute(const AgentRoute *route,
      63             :                                        const AgentPath *path) {
      64           8 :     const InetUnicastRouteEntry *uc_rt =
      65             :         static_cast<const InetUnicastRouteEntry *>(route);
      66           8 :     const AgentPath *active_path = path;
      67             : 
      68           8 :     if (active_path == NULL) {
      69           0 :         active_path = uc_rt->GetActivePath();
      70             :     }
      71             : 
      72           8 :     InterfaceNH *intf_nh = dynamic_cast<InterfaceNH *>(active_path->nexthop());
      73           8 :     if (intf_nh == NULL) {
      74           3 :         return;
      75             :     }
      76             : 
      77          16 :     if (uc_rt->IsHostRoute() &&
      78          16 :         uc_rt->prefix_address() == agent_->router_id()) {
      79             :         //Dont overwrite vhost IP in default VRF
      80           3 :         if (intf_nh->GetInterface() != agent_->vhost_interface()) {
      81           0 :             return;
      82             :         }
      83             :     }
      84             : 
      85           8 :     if (intf_nh->GetInterface()->type() == Interface::PACKET) {
      86           0 :         peer_list_.insert(agent_->local_peer());
      87             :         InetUnicastAgentRouteTable *table =
      88             :             static_cast<InetUnicastAgentRouteTable *>
      89           0 :             (dest_vrf_->GetInet4UnicastRouteTable());
      90             : 
      91           0 :         table->AddHostRoute(dest_vrf_->GetName(), uc_rt->prefix_address(), uc_rt->prefix_length(),
      92             :                             "", true);
      93           0 :         return;
      94             :     }
      95             : 
      96           8 :     if (intf_nh->GetInterface()->type() == Interface::VM_INTERFACE) {
      97             :         const VmInterface *vm_intf =
      98           8 :             static_cast<const VmInterface *>(intf_nh->GetInterface());
      99           8 :         if (vm_intf->vmi_type() == VmInterface::VHOST) {
     100           8 :             if (uc_rt->prefix_address() == agent_->router_id()) {
     101           3 :                 if (uc_rt->FindLocalVmPortPath() == NULL) {
     102           0 :                     peer_list_.insert(agent_->local_peer());
     103             :                 } else {
     104           3 :                     peer_list_.insert(agent_->fabric_rt_export_peer());
     105             :                 }
     106           3 :                 AddReceiveRoute(route);
     107           3 :                 return;
     108             :             }
     109             :         }
     110             :     }
     111             : 
     112           5 :     const Peer *peer = active_path->peer();
     113           5 :     if (uc_rt->FindLocalVmPortPath() == NULL) {
     114           0 :         peer = agent_->local_peer();
     115             :     }
     116             : 
     117             :     /* Don't export /32 routes on fabric-vrf, if they are part of vrouter's
     118             :      * subnet list. To disable export, use local_peer */
     119          10 :     if ((uc_rt->IsHostRoute()) &&
     120           5 :         dest_vrf_->GetName() == agent_->fabric_vrf_name()) {
     121           5 :         if (agent_->oper_db()->vrouter()->IsSubnetMember(uc_rt->prefix_address())) {
     122           0 :             peer = agent_->local_peer();
     123             :         }
     124             :     }
     125             : 
     126           5 :     peer_list_.insert(peer);
     127             :     VmInterfaceKey intf_key(AgentKey::ADD_DEL_CHANGE, intf_nh->GetIfUuid(),
     128           5 :             intf_nh->GetInterface()->name());
     129           5 :     LocalVmRoute *local_vm_route = NULL;
     130          15 :     local_vm_route =
     131             :         new LocalVmRoute(intf_key, MplsTable::kInvalidExportLabel,
     132             :                          VxLanTable::kInvalidvxlan_id, false,
     133           5 :                          active_path->dest_vn_list(), InterfaceNHFlags::INET4,
     134           5 :                          SecurityGroupList(),
     135          10 :                          TagList(),
     136          10 :                          CommunityList(),
     137           5 :                          active_path->path_preference(),
     138          15 :                          Ip4Address(0), EcmpLoadBalance(),
     139           5 :                          false, false, peer->sequence_number(),
     140           5 :                          false, true);
     141           5 :     local_vm_route->set_native_vrf_id(uc_rt->vrf()->rd());
     142             : 
     143           5 :     DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
     144          10 :     req.key.reset(new InetUnicastRouteKey(peer, dest_vrf_->GetName(),
     145           5 :                                           uc_rt->prefix_address(), uc_rt->prefix_length()));
     146           5 :     req.data.reset(local_vm_route);
     147             : 
     148             :     AgentRouteTable *table =
     149           5 :         agent_->vrf_table()->GetInet4UnicastRouteTable(dest_vrf_->GetName());
     150           5 :     if (table) {
     151           5 :         table->Process(req);
     152             :     }
     153           5 : }
     154             : 
     155           0 : void RouteLeakState::AddCompositeRoute(const AgentRoute *route) {
     156           0 :     for(Route::PathList::const_iterator it = route->GetPathList().begin();
     157           0 :         it != route->GetPathList().end(); it++) {
     158           0 :         const AgentPath *path = static_cast<const AgentPath *>(it.operator->());
     159           0 :         if (path->peer()->GetType() == Peer::LOCAL_VM_PORT_PEER) {
     160           0 :             AddInterfaceRoute(route, path);
     161             :         }
     162             :     }
     163           0 : }
     164             : 
     165           3 : void RouteLeakState::AddReceiveRoute(const AgentRoute *route) {
     166           3 :     const InetUnicastRouteEntry *uc_rt =
     167             :         static_cast<const InetUnicastRouteEntry *>(route);
     168           3 :     const AgentPath *active_path = uc_rt->GetActivePath();
     169             : 
     170             :     /* This is a defensive check added to prevent the code below from casting NHs
     171             :      * not containing an interface to RECEIVE NH */
     172           3 :     const NextHop* nh = active_path->nexthop();
     173           3 :     if ((nh->GetType() != NextHop::INTERFACE) &&
     174           0 :         (nh->GetType() != NextHop::RECEIVE)) {
     175           0 :         return;
     176             :     }
     177             : 
     178             :     const ReceiveNH *rch_nh =
     179           3 :         static_cast<const ReceiveNH*>(active_path->nexthop());
     180             :     const VmInterface *vm_intf =
     181           3 :         static_cast<const VmInterface *>(rch_nh->GetInterface());
     182             : 
     183             :     InetUnicastAgentRouteTable *table =
     184             :         static_cast<InetUnicastAgentRouteTable *>(
     185           3 :                 dest_vrf_->GetInet4UnicastRouteTable());
     186             : 
     187             :     VmInterfaceKey vmi_key(AgentKey::ADD_DEL_CHANGE, vm_intf->GetUuid(),
     188           3 :                            vm_intf->name());
     189           3 :     table->AddVHostRecvRoute(agent_->fabric_rt_export_peer(),
     190             :                              dest_vrf_->GetName(),
     191             :                              vmi_key,
     192           3 :                              uc_rt->prefix_address(),
     193           3 :                              uc_rt->prefix_length(),
     194           3 :                              agent_->fabric_vn_name(), false, true);
     195           3 : }
     196             : 
     197          13 : bool RouteLeakState::CanAdd(const InetUnicastRouteEntry *rt) {
     198             :     //Never replace resolve route and default route
     199             :     InetUnicastAgentRouteTable *table =
     200          13 :         agent_->fabric_vrf()->GetInet4UnicastRouteTable();
     201          13 :     std::vector<Ip4Address> gateway_list = agent_->vhost_default_gateway();
     202             : 
     203          13 :     if (rt->prefix_address() == Ip4Address(0) && rt->prefix_length() == 0) {
     204           5 :         return false;
     205             :     }
     206             : 
     207           8 :     InetUnicastRouteEntry *rsl_rt = table->FindResolveRoute(rt->prefix_address().to_v4());
     208           8 :     if (rsl_rt && rt->prefix_address() == rsl_rt->prefix_address() &&
     209           0 :         rt->prefix_length() == rsl_rt->prefix_length()) {
     210             :         //Dont overwrite resolve route
     211           0 :         return false;
     212             :     }
     213             : 
     214          16 :     if (rt->IsHostRoute() &&
     215           8 :         std::find(gateway_list.begin(), gateway_list.end(),
     216          24 :                   rt->prefix_address()) != gateway_list.end()) {
     217           0 :         return false;
     218             :     }
     219             : 
     220             :     //Always add gateway and DNS routes
     221             :     const InterfaceNH *nh =
     222           8 :         dynamic_cast<const InterfaceNH *>(rt->GetActiveNextHop());
     223           8 :     if (nh && nh->GetInterface()->type() == Interface::PACKET) {
     224           0 :         return true;
     225             :     }
     226             : 
     227           8 :     if ((rt->GetActivePath()->tunnel_bmap() & TunnelType::NativeType()) == 0) {
     228           0 :         return false;
     229             :     }
     230             : 
     231           8 :     return true;
     232          13 : }
     233             : 
     234          13 : void RouteLeakState::AddRoute(const AgentRoute *route) {
     235          13 :     const InetUnicastRouteEntry *uc_rt =
     236             :         static_cast<const InetUnicastRouteEntry *>(route);
     237          13 :     const NextHop *anh = uc_rt->GetActiveNextHop();
     238          13 :     if (CanAdd(uc_rt) == false && anh) {
     239           5 :         DeleteRoute(route, peer_list_);
     240           5 :         return;
     241             :     }
     242             : 
     243           8 :     std::set<const Peer *> old_peer_list = peer_list_;
     244           8 :     peer_list_.clear();
     245             : 
     246           8 :     if (anh->GetType() == NextHop::TUNNEL) {
     247           0 :         AddIndirectRoute(route);
     248          16 :     } else if ((anh->GetType() == NextHop::COMPOSITE)||
     249           8 :             (route->FindLocalVmPortPath() &&
     250          16 :             route->FindLocalVmPortPath()->nexthop() &&
     251           8 :             route->FindLocalVmPortPath()->nexthop()->GetType()
     252             :                             == NextHop::COMPOSITE)) {
     253           0 :         AddCompositeRoute(route);
     254           8 :     } else if (anh->GetType() == NextHop::INTERFACE) {
     255           8 :         AddInterfaceRoute(route, route->FindLocalVmPortPath());
     256             :     }
     257             : 
     258           8 :     bool sync = false;
     259           8 :     if (old_peer_list != peer_list_) {
     260           2 :         sync = true;
     261             :     }
     262             : 
     263           8 :     std::set<const Peer *>::iterator it = old_peer_list.begin();
     264          15 :     while(it != old_peer_list.end()) {
     265           7 :         std::set<const Peer *>::iterator prev_it = it;
     266           7 :         it++;
     267           7 :         if (peer_list_.find(*prev_it) != peer_list_.end()) {
     268           6 :             old_peer_list.erase(prev_it);
     269             :         }
     270             :     }
     271             : 
     272           8 :     DeleteRoute(route, old_peer_list);
     273             : 
     274           8 :     if (sync) {
     275             :         InetUnicastAgentRouteTable *table =
     276           2 :             dest_vrf_->GetInet4UnicastRouteTable();
     277           2 :         table->ResyncRoute(agent_->fabric_rt_export_peer(),
     278           2 :                            dest_vrf_->GetName(), uc_rt->prefix_address(), uc_rt->prefix_length());
     279             :     }
     280           8 : }
     281             : 
     282          17 : void RouteLeakState::DeleteRoute(const AgentRoute *route,
     283             :                                  const std::set<const Peer *> &peer_list) {
     284          17 :     if (dest_vrf_ == NULL) {
     285           2 :         return;
     286             :     }
     287             : 
     288          15 :     std::set<const Peer *>::const_iterator it = peer_list.begin();
     289          17 :     for(; it != peer_list.end(); it++) {
     290           2 :         const InetUnicastRouteEntry *uc_rt =
     291             :             static_cast<const InetUnicastRouteEntry *>(route);
     292           4 :         dest_vrf_->GetInet4UnicastRouteTable()->Delete(*it,
     293             :                                                        dest_vrf_->GetName(),
     294           2 :                                                        uc_rt->prefix_address(),
     295           2 :                                                        uc_rt->prefix_length());
     296             :     }
     297             : }
     298             : 
     299           1 : RouteLeakVrfState::RouteLeakVrfState(VrfEntry *source_vrf,
     300           1 :                                      VrfEntry *dest_vrf):
     301           1 :     source_vrf_(source_vrf), dest_vrf_(dest_vrf), deleted_(false) {
     302             : 
     303           1 :     AgentRouteTable *table = source_vrf->GetInet4UnicastRouteTable();
     304           1 :     route_listener_id_ =  table->Register(boost::bind(&RouteLeakVrfState::Notify,
     305             :                                                       this, _1, _2));
     306             : 
     307             :     //Walker would be used to address change of dest VRF table
     308             :     //Everytime dest vrf change all the route from old dest VRF
     309             :     //would be deleted and added to new dest VRF if any
     310             :     //If VRF is deleted upon walk done state would be deleted.
     311           2 :     walk_ref_ = table->AllocWalker(
     312             :                     boost::bind(&RouteLeakVrfState::WalkCallBack, this, _1, _2),
     313           1 :                     boost::bind(&RouteLeakVrfState::WalkDoneInternal, this, _2));
     314           1 :     table->WalkTable(walk_ref_);
     315           1 : }
     316             : 
     317           2 : RouteLeakVrfState::~RouteLeakVrfState() {
     318           1 :     source_vrf_->GetInet4UnicastRouteTable()->ReleaseWalker(walk_ref_);
     319           1 :     source_vrf_->GetInet4UnicastRouteTable()->Unregister(route_listener_id_);
     320           2 : }
     321             : 
     322           2 : void RouteLeakVrfState::WalkDoneInternal(DBTableBase *part) {
     323           2 :     if (deleted_) {
     324           1 :         delete this;
     325             :     }
     326           2 : }
     327             : 
     328           2 : bool RouteLeakVrfState::WalkCallBack(DBTablePartBase *partition, DBEntryBase *entry) {
     329           2 :     Notify(partition, entry);
     330           2 :     return true;
     331             : }
     332             : 
     333           1 : void RouteLeakVrfState::AddDefaultRoute() {
     334           1 :     InetUnicastAgentRouteTable *table = source_vrf_->GetInet4UnicastRouteTable();
     335             : 
     336           1 :     VnListType vn_list;
     337           1 :     vn_list.insert(table->agent()->fabric_vn_name());
     338             : 
     339           1 :     table->AddGatewayRoute(table->agent()->local_peer(),
     340           1 :                            source_vrf_->GetName(), Ip4Address(0), 0,
     341           2 :                            table->agent()->vhost_default_gateway(), vn_list,
     342           2 :                            MplsTable::kInvalidLabel, SecurityGroupList(),
     343           2 :                            TagList(), CommunityList(), true);
     344           1 : }
     345             : 
     346           1 : void RouteLeakVrfState::DeleteDefaultRoute() {
     347           1 :     InetUnicastAgentRouteTable *table = source_vrf_->GetInet4UnicastRouteTable();
     348           1 :     table->Delete(table->agent()->local_peer(), source_vrf_->GetName(),
     349           1 :                   Ip4Address(0), 0);
     350           1 : }
     351             : 
     352           1 : void RouteLeakVrfState::Delete() {
     353           1 :     deleted_ = true;
     354           1 :     source_vrf_->GetInet4UnicastRouteTable()->WalkAgain(walk_ref_);
     355           1 :     DeleteDefaultRoute();
     356           1 : }
     357             : 
     358          15 : bool RouteLeakVrfState::Notify(DBTablePartBase *partition, DBEntryBase *entry) {
     359          15 :     AgentRoute *route = static_cast<AgentRoute *>(entry);
     360             :     RouteLeakState *state =
     361          15 :         static_cast<RouteLeakState *>(entry->GetState(partition->parent(),
     362             :                                                       route_listener_id_));
     363             : 
     364          15 :     if (route->IsDeleted() || deleted_) {
     365           2 :         if (state) {
     366             :             //Delete the route
     367           2 :             entry->ClearState(partition->parent(), route_listener_id_);
     368           2 :             state->DeleteRoute(route, state->peer_list());
     369           2 :             delete state;
     370             :         }
     371           2 :         return true;
     372             :     }
     373             : 
     374          13 :     if (state == NULL && dest_vrf_) {
     375           2 :         state = new RouteLeakState(dest_vrf_->GetInet4UnicastRouteTable()->agent(),
     376           2 :                                    NULL);
     377           2 :         route->SetState(partition->parent(), route_listener_id_, state);
     378             :     }
     379             : 
     380          13 :     if (state == NULL) {
     381           0 :         return true;
     382             :     }
     383             : 
     384          13 :     if (state->dest_vrf() != dest_vrf_) {
     385           2 :         state->DeleteRoute(route, state->peer_list());
     386             :     }
     387             : 
     388          13 :     if (state->dest_vrf() != dest_vrf_) {
     389             :         //Add the route in new VRF
     390           2 :         state->set_dest_vrf(dest_vrf_.get());
     391             :     }
     392             : 
     393          13 :     if (state->dest_vrf()) {
     394          13 :         state->AddRoute(route);
     395             :     }
     396          13 :     return true;
     397             : }
     398             : 
     399           1 : void RouteLeakVrfState::SetDestVrf(VrfEntry *vrf) {
     400           1 :     if (dest_vrf_ != vrf) {
     401           1 :         dest_vrf_ = vrf;
     402           1 :         source_vrf_->GetInet4UnicastRouteTable()->WalkAgain(walk_ref_);
     403             :     }
     404             : 
     405           1 :     if (vrf == NULL) {
     406           0 :         DeleteDefaultRoute();
     407             :     } else {
     408           1 :         AddDefaultRoute();
     409             :     }
     410           1 : }
     411             : 
     412           1 : RouteLeakManager::RouteLeakManager(Agent *agent): agent_(agent) {
     413           1 :     vrf_listener_id_ = agent_->vrf_table()->Register(
     414             :                            boost::bind(&RouteLeakManager::Notify, this, _1, _2));
     415           1 : }
     416             : 
     417           1 : RouteLeakManager::~RouteLeakManager() {
     418           1 :     agent_->vrf_table()->Unregister(vrf_listener_id_);
     419           1 : }
     420             : 
     421          15 : void RouteLeakManager::Notify(DBTablePartBase *partition, DBEntryBase *entry) {
     422          15 :     VrfEntry *vrf = static_cast<VrfEntry *>(entry);
     423             :     RouteLeakVrfState *state =
     424          15 :         static_cast<RouteLeakVrfState *>(entry->GetState(partition->parent(),
     425             :                                                          vrf_listener_id_));
     426             : 
     427          15 :     if (vrf->IsDeleted()) {
     428          13 :         if (state) {
     429           1 :             entry->ClearState(partition->parent(), vrf_listener_id_);
     430           1 :             state->Delete();
     431             :         }
     432          13 :         return;
     433             :     }
     434             : 
     435             : 
     436           2 :     if (state == NULL && vrf->forwarding_vrf()) {
     437           1 :         state = new RouteLeakVrfState(vrf, NULL);
     438             :     }
     439             : 
     440           2 :     if (state == NULL) {
     441           1 :         return;
     442             :     }
     443             : 
     444           1 :     vrf->SetState(partition->parent(), vrf_listener_id_, state);
     445             : 
     446           1 :     if (vrf->forwarding_vrf() != state->dest_vrf()) {
     447           1 :         state->SetDestVrf(vrf->forwarding_vrf());
     448             :     }
     449             : }
     450             : 
     451           0 : void RouteLeakManager::ReEvaluateRouteExports() {
     452           0 :     if (vrf_walk_ref_.get() == NULL) {
     453           0 :         vrf_walk_ref_ = agent_->vrf_table()->AllocWalker(
     454             :             boost::bind(&RouteLeakManager::VrfWalkNotify, this, _1, _2),
     455           0 :             boost::bind(&RouteLeakManager::VrfWalkDone, this, _2));
     456             :     }
     457           0 :     agent_->vrf_table()->WalkAgain(vrf_walk_ref_);
     458           0 : }
     459             : 
     460           0 : bool RouteLeakManager::VrfWalkNotify(DBTablePartBase *partition,
     461             :                                      DBEntryBase *e) {
     462           0 :     VrfEntry *vrf = static_cast<VrfEntry *>(e);
     463             :     RouteLeakVrfState *state =
     464           0 :         static_cast<RouteLeakVrfState *>(e->GetState(partition->parent(),
     465             :                                                      vrf_listener_id_));
     466           0 :     if (vrf->IsDeleted()) {
     467           0 :         return true;
     468             :     }
     469             :     /* Ignore VRFs on which routes are not leaked by RouteLeakManager */
     470           0 :     if (state == NULL) {
     471           0 :         return true;
     472             :     }
     473           0 :     if (state->deleted()) {
     474           0 :         return true;
     475             :     }
     476             : 
     477           0 :     StartRouteWalk(vrf, state);
     478           0 :     return true;
     479             : }
     480             : 
     481           0 : void RouteLeakManager::VrfWalkDone(DBTableBase *part) {
     482           0 : }
     483             : 
     484           0 : void RouteLeakManager::StartRouteWalk(VrfEntry *vrf, RouteLeakVrfState *state) {
     485           0 :     InetUnicastAgentRouteTable *table = vrf->GetInet4UnicastRouteTable();
     486           0 :     if (!table) {
     487           0 :         return;
     488             :     }
     489             :     DBTable::DBTableWalkRef rt_table_walk_ref = table->AllocWalker(
     490             :         boost::bind(&RouteLeakVrfState::Notify, state, _1, _2),
     491           0 :         boost::bind(&RouteLeakManager::RouteWalkDone, this, _2));
     492           0 :     table->WalkAgain(rt_table_walk_ref);
     493           0 : }
     494             : 
     495           0 : void RouteLeakManager::RouteWalkDone(DBTableBase *part) {
     496           0 : }

Generated by: LCOV version 1.14