LCOV - code coverage report
Current view: top level - vnsw/agent/controller - controller_export.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 264 312 84.6 %
Date: 2026-08-03 02:19:58 Functions: 17 17 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <boost/uuid/uuid_io.hpp>
       6             : 
       7             : #include <cmn/agent_cmn.h>
       8             : #include <init/agent_param.h>
       9             : #include <oper/ecmp_load_balance.h>
      10             : #include <oper/route_common.h>
      11             : #include <oper/peer.h>
      12             : #include <oper/nexthop.h>
      13             : #include <oper/peer.h>
      14             : #include <oper/mirror_table.h>
      15             : #include "oper/tunnel_nh.h"
      16             : 
      17             : #include <controller/controller_vrf_export.h>
      18             : #include <controller/controller_init.h>
      19             : #include <controller/controller_export.h>
      20             : #include <controller/controller_peer.h>
      21             : #include <controller/controller_types.h>
      22             : 
      23          62 : RouteExport::State::State() :
      24          62 :     DBState(), exported_(false), ingress_replication_exported_(false),
      25          62 :     multicast_exported_(false),
      26          62 :     force_chg_(false), label_(MplsTable::kInvalidLabel), vn_(), sg_list_(),
      27         124 :     tag_list_(), tunnel_type_(TunnelType::INVALID), path_preference_(),
      28         186 :     destination_(), source_(), ecmp_load_balance_(), isid_(0), tunnel_bmap_(0) {
      29          62 : }
      30             : 
      31         112 : bool RouteExport::State::Changed(const AgentRoute *route, const AgentPath *path) const {
      32         112 :     if (exported_ == false)
      33          35 :         return true;
      34             : 
      35          77 :     if (force_chg_ == true)
      36           0 :         return true;
      37             : 
      38          77 :     if (label_ != path->GetActiveLabel())
      39           2 :         return true;
      40             : 
      41          75 :     if (tunnel_type_ != path->tunnel_type()) {
      42           0 :         return true;
      43             :     };
      44             : 
      45          75 :     if (vn_ != path->dest_vn_name())
      46           0 :         return true;
      47             : 
      48          75 :     if (sg_list_ != path->sg_list())
      49          15 :         return true;
      50             : 
      51          60 :     if (tag_list_ != path->tag_list())
      52           0 :         return true;
      53             : 
      54          60 :     if (communities_ != path->communities())
      55           0 :         return true;
      56             : 
      57          60 :     if (path_preference_ != path->path_preference())
      58          13 :         return true;
      59             : 
      60          47 :     if(ecmp_load_balance_ != path->ecmp_load_balance())
      61           0 :         return true;
      62             : 
      63          47 :     if (etree_leaf_ != path->etree_leaf())
      64           0 :         return true;
      65             : 
      66          47 :     if (tunnel_bmap_ != path->tunnel_bmap())
      67           0 :         return true;
      68             : 
      69          47 :     return false;
      70             : }
      71             : 
      72          65 : void RouteExport::State::Update(const AgentRoute *route, const AgentPath *path) {
      73          65 :     force_chg_ = false;
      74          65 :     label_ = path->GetActiveLabel();
      75          65 :     vn_ = path->dest_vn_name();
      76          65 :     sg_list_ = path->sg_list();
      77          65 :     tag_list_ = path->tag_list();
      78          65 :     communities_ = path->communities();
      79          65 :     tunnel_type_ = path->tunnel_type();
      80          65 :     path_preference_ = path->path_preference();
      81          65 :     ecmp_load_balance_ = path->ecmp_load_balance();
      82          65 :     etree_leaf_ = path->etree_leaf();
      83          65 :     tunnel_bmap_ = path->tunnel_bmap();
      84          65 : }
      85             : 
      86          36 : RouteExport::RouteExport(AgentRouteTable *rt_table):
      87          36 :     rt_table_(rt_table), marked_delete_(false),
      88          36 :     table_delete_ref_(this, rt_table->deleter()) {
      89          72 :     walk_ref_ = rt_table->AllocWalker(
      90             :             boost::bind(&RouteExport::DeleteState, this, _1, _2),
      91          36 :             boost::bind(&RouteExport::Walkdone, _1, _2, this));
      92          36 : }
      93             : 
      94          36 : RouteExport::~RouteExport() {
      95          36 :     if (rt_table_) {
      96          36 :         rt_table_->Unregister(id_);
      97          36 :         rt_table_->ReleaseWalker(walk_ref_);
      98             :     }
      99          36 :     table_delete_ref_.Reset(NULL);
     100          36 : }
     101             : 
     102          36 : void RouteExport::ManagedDelete() {
     103          36 :     marked_delete_ = true;
     104          36 : }
     105             : 
     106             : // Route entry add/change/del notification handler
     107         432 : void RouteExport::Notify(const Agent *agent,
     108             :                          AgentXmppChannel *bgp_xmpp_peer,
     109             :                          bool associate,
     110             :                          Agent::RouteTableType type,
     111             :                          DBTablePartBase *partition,
     112             :                          DBEntryBase *e) {
     113         432 :     AgentRoute *route = static_cast<AgentRoute *>(e);
     114             : 
     115             :     // Primitive checks for non-delete notification
     116         432 :     if (!route->IsDeleted()) {
     117             :         // If there is no active BGP peer attached to channel, ignore
     118             :         // non-delete notification for this channel
     119         330 :         if (!AgentXmppChannel::IsBgpPeerActive(agent, bgp_xmpp_peer))
     120           0 :             return;
     121             : 
     122         330 :         if (route->GetActivePath()->inactive())
     123           0 :             return;
     124             : 
     125             :         // Extract the listener ID of active BGP peer for route table to which
     126             :         // this route entry belongs to. Listeners of route table can be active
     127             :         // bgp peers as well as decommisioned BGP peers(if they exist). Active
     128             :         // and decommisoned BGP peer can co-exist till cleanup timer is fired.
     129             :         // During this interval ignore notification for decommisioned bgp peer
     130             :         // listener id
     131         330 :         VrfEntry *vrf = route->vrf();
     132             :         BgpPeer *bgp_peer = static_cast<BgpPeer *>(bgp_xmpp_peer->
     133         330 :                                                    bgp_peer_id());
     134         330 :         DBTableBase::ListenerId vrf_id = bgp_peer->GetVrfExportListenerId();
     135             :         VrfExport::State *vs =
     136         330 :             static_cast<VrfExport::State *>(vrf->GetState(vrf->get_table(),
     137             :                                                           vrf_id));
     138             :         // If VRF state is not present then listener has not been added.
     139             :         // Addition of listener later will result in walk to notify all routes.
     140             :         // That in turn will add state as well by calling current routine.
     141             :         // Therefore return when empty VRF state is found.
     142         330 :         if (!vs)
     143           0 :             return;
     144             : 
     145             :         //Make sure that vrf has been subscribed before route is published.
     146         330 :         if (vs->IsExportable(bgp_xmpp_peer->sequence_number()))
     147           0 :             return;
     148             : 
     149             :         // There may be instances when decommisioned peer is not yet
     150             :         // unregistered while a new peer is already present. So there will be
     151             :         // two notifications. If its for decommisioned peer then ignore the same
     152             :         // by checking the listener id with active bgp peer listener id.
     153         330 :         DBTableBase::ListenerId id = vs->rt_export_[route->GetTableType()]->
     154         330 :             GetListenerId();
     155         330 :         if (id != id_)
     156           0 :             return;
     157             :     }
     158             : 
     159             :     //If channel is no more active, ignore any updates.
     160             :     //It may happen that notify is enqueued before channel is removed.
     161         432 :     if (!AgentXmppChannel::IsBgpPeerActive(agent, bgp_xmpp_peer))
     162           0 :         return;
     163             : 
     164         432 :     if (route->is_multicast()) {
     165          47 :         MulticastNotify(bgp_xmpp_peer, associate, partition, e);
     166             :     } else {
     167         385 :         UnicastNotify(bgp_xmpp_peer, partition, e, type);
     168             :     }
     169             : }
     170             : 
     171         385 : void RouteExport::UnicastNotify(AgentXmppChannel *bgp_xmpp_peer,
     172             :                                 DBTablePartBase *partition, DBEntryBase *e,
     173             :                                 Agent::RouteTableType type) {
     174         385 :     AgentRoute *route = static_cast<AgentRoute *>(e);
     175             :     //TODO Currently BRIDGE notifications are coming because multicast route
     176             :     //are installed in same. Once multicast route is shifted to EVPN table
     177             :     //then there will be no export from Bridge and check below can be removed.
     178         385 :     if (route->GetTableType() == Agent::BRIDGE)
     179         163 :         return;
     180             : 
     181         222 :     if (route->vrf()->ShouldExportRoute() == false) {
     182           0 :         return;
     183             :     }
     184             : 
     185             :     AgentRouteTable *table = static_cast<AgentRouteTable *>
     186         222 :         (partition->parent());
     187         222 :     State *state = static_cast<State *>(route->GetState(partition->parent(),
     188             :                                                         id_));
     189         222 :     AgentPath *path = NULL;
     190         222 :     path = route->FindLocalVmPortPath();
     191             : 
     192         222 :     std::stringstream path_str;
     193         222 :     if (path && path->peer())
     194         112 :         path_str << path->peer()->GetName();
     195             :     else
     196         110 :         path_str << "None";
     197             : 
     198         222 :     if (marked_delete_) {
     199             :         //Ignore route updates on delete marked vrf
     200          10 :         goto done;
     201             :     }
     202             :     // if vrf is fabric vrf and route is not labelled inet route
     203             :     // then don't export the route
     204         112 :     if (path && (route->vrf()->GetName() == table->agent()->fabric_vrf_name())
     205         324 :             && (type != Agent::INET4_MPLS)) {
     206             :         //Dont export vhost IP path to control-node
     207             :         const InetUnicastRouteEntry *inet_rt =
     208           0 :             dynamic_cast<const InetUnicastRouteEntry *>(route);
     209           0 :         if (inet_rt && inet_rt->prefix_address() == table->agent()->router_id()) {
     210           0 :             path = NULL;
     211             :         }
     212             :     }
     213             : 
     214         212 :     if (!state && route->IsDeleted()) {
     215           0 :         goto done;
     216             :     }
     217             : 
     218         212 :     if (state == NULL) {
     219          56 :         state = new State();
     220          56 :         route->SetState(partition->parent(), id_, state);
     221             :     }
     222             : 
     223         212 :     if (path && !path->is_local()) {
     224         112 :         if (state->Changed(route, path)) {
     225          65 :             state->Update(route, path);
     226          65 :             VnListType vn_list;
     227          65 :             vn_list.insert(state->vn_);
     228          65 :             uint32_t label = state->label_;
     229          65 :             if ((route->vrf()->GetName() == table->agent()->fabric_vrf_name()) &&
     230          65 :                     (label != MplsTable::kInvalidLabel )&& (label != MplsTable::kImplicitNullLabel )) {
     231           0 :                 label  = 0;
     232             :             }
     233          65 :             state->exported_ =
     234         130 :                 AgentXmppChannel::ControllerSendRouteAdd(bgp_xmpp_peer,
     235             :                       static_cast<AgentRoute * >(route),
     236             :                       path->NexthopIp(table->agent()), vn_list,
     237             :                       label, path->GetTunnelBmap(),
     238          65 :                       &path->sg_list(), &path->tag_list(), &path->communities(),
     239          65 :                       type, state->path_preference_,
     240          65 :                       state->ecmp_load_balance_,
     241             :                       path->native_vrf_id());
     242          65 :         }
     243             :     } else {
     244         100 :         if (state->exported_ == true) {
     245          35 :             VnListType vn_list;
     246          35 :             vn_list.insert(state->vn_);
     247          35 :             AgentXmppChannel::ControllerSendRouteDelete(bgp_xmpp_peer,
     248             :                     static_cast<AgentRoute *>(route), vn_list,
     249          35 :                     (state->tunnel_type_ == TunnelType::VXLAN ?
     250             :                      state->label_ : 0),
     251             :                     TunnelType::AllType(), NULL, NULL, NULL,
     252          35 :                     type, state->path_preference_);
     253          35 :             state->exported_ = false;
     254          35 :         }
     255             :     }
     256          65 : done:
     257         222 :     if (route->IsDeleted()) {
     258          56 :         if (state) {
     259          55 :             route->ClearState(partition->parent(), id_);
     260          55 :             delete state;
     261             :         }
     262             :     }
     263         222 : }
     264             : 
     265         110 : static const AgentPath *GetMulticastExportablePath(const Agent *agent,
     266             :                                                    const AgentRoute *route) {
     267         110 :     const AgentPath *active_path = route->FindPath(agent->local_vm_peer());
     268             : 
     269             :     //OVS peer path
     270         110 :     if (active_path == NULL) {
     271             :         const EvpnRouteEntry *evpn_route =
     272          22 :             dynamic_cast<const EvpnRouteEntry *>(route);
     273          22 :         active_path = evpn_route ? evpn_route->FindOvsPath() : NULL;
     274             :     }
     275             :     //If no loca peer, then look for tor peer as that should also result
     276             :     //in export of route.
     277         110 :     if (active_path == NULL)
     278          22 :         active_path = route->FindPath(agent->multicast_tor_peer());
     279             :     //Subnet discard
     280         110 :     if (active_path == NULL) {
     281          22 :         const AgentPath *local_path = route->FindPath(agent->local_peer());
     282          22 :         if (local_path && !agent->tor_agent_enabled()) {
     283          16 :             return local_path;
     284             :         }
     285             :     }
     286             : 
     287          94 :     return active_path;
     288             : }
     289             : 
     290          47 : bool RouteExport::MulticastRouteCanDissociate(const AgentRoute *route) {
     291          47 :     bool can_dissociate = route->IsDeleted();
     292          47 :     Agent *agent = static_cast<AgentRouteTable*>(route->get_table())->
     293          47 :         agent();
     294          47 :     const AgentPath *local_path = route->FindPath(agent->local_peer());
     295             : 
     296          47 :     if (route->GetTableType() == Agent::INET4_MULTICAST) {
     297           0 :         const AgentPath *active_path = route->FindPath(agent->local_vm_peer());
     298           0 :         if (!active_path) {
     299           0 :             return true;
     300             :         }
     301           0 :         return can_dissociate;
     302             :     }
     303             : 
     304          47 :     if (local_path && !agent->tor_agent_enabled()) {
     305          19 :         return can_dissociate;
     306             :     }
     307          28 :     if (route->is_multicast()) {
     308          28 :         const AgentPath *active_path = GetMulticastExportablePath(agent, route);
     309          28 :         if (active_path == NULL)
     310           6 :             return true;
     311          22 :         const NextHop *nh = active_path ? active_path->ComputeNextHop(agent) : NULL;
     312          22 :         const CompositeNH *cnh = static_cast<const CompositeNH *>(nh);
     313          22 :         if (cnh && cnh->ComponentNHCount() == 0)
     314           0 :             return true;
     315             :     }
     316          22 :     return can_dissociate;
     317             : }
     318             : 
     319          41 : void RouteExport::SubscribeMulticastRouting(const Agent *agent,
     320             :                                            AgentXmppChannel *bgp_xmpp_peer,
     321             :                                            AgentRoute *route,
     322             :                                            RouteExport::State *state) {
     323          41 :     const AgentPath *active_path = GetMulticastExportablePath(agent, route);
     324             :     //Agent running as tor(simulate_evpn_tor) - dont subscribe
     325             :     //Route has path with peer OVS_PEER i.e. TOR agent mode - dont subscribe
     326             :     //Subscribe condition:
     327             :     //first time subscription or force change
     328          82 :     if (!(agent->simulate_evpn_tor()) &&
     329          82 :         (active_path->peer()->GetType() != Peer::OVS_PEER) &&
     330          41 :         ((state->multicast_exported_ == false) ||
     331          35 :          (state->force_chg_ == true))) {
     332             :         //TODO optimize by checking for force_chg? In other cases duplicate
     333             :         //request can be filtered.
     334           6 :         if (state->multicast_exported_ == true) {
     335             :             //Unsubscribe before re-sending subscription, this makes sure in any
     336             :             //corner case control-node does not see this as a duplicate request.
     337           0 :             AgentXmppChannel::ControllerSendMcastRouteDelete(bgp_xmpp_peer,
     338             :                                                              route);
     339           0 :             state->multicast_exported_ = false;
     340             :         }
     341             :         //Sending 255.255.255.255 for fabric tree
     342           6 :         state->multicast_exported_ =
     343           6 :             AgentXmppChannel::ControllerSendMcastRouteAdd(bgp_xmpp_peer,
     344             :                                                           route);
     345             :     }
     346          41 : }
     347             : 
     348             : // Handles subscription of multicast routes.
     349             : // Following are the kind of subscription:
     350             : // Fabric - For fabric replication tree
     351             : // EVPN Ingress replication - For adding compute node in EVPN replication list.
     352             : // TOR Ingress replication - For adding in TOR replication list (relevant for
     353             : // TSN).
     354             : //
     355             : // For Tor-agent its a route with tunnel NH and there is no subscription.
     356          47 : void RouteExport::MulticastNotify(AgentXmppChannel *bgp_xmpp_peer,
     357             :                                   bool associate,
     358             :                                   DBTablePartBase *partition,
     359             :                                   DBEntryBase *e) {
     360          47 :     Agent *agent = bgp_xmpp_peer->agent();
     361          47 :     AgentRoute *route = static_cast<AgentRoute *>(e);
     362          47 :     State *state = static_cast<State *>(route->GetState(partition->parent(), id_));
     363             : 
     364             :     // Bridge Multicast routes are not sent to control.
     365          47 :     BridgeRouteEntry *l2_route = dynamic_cast<BridgeRouteEntry *>(route);
     366          94 :     if ((route->GetTableType() == Agent::BRIDGE) &&
     367          47 :         (l2_route->prefix_address() != MacAddress::BroadcastMac())) {
     368             : 
     369           0 :         return;
     370             :     }
     371             : 
     372          47 :     bool route_can_be_dissociated = MulticastRouteCanDissociate(route);
     373             : 
     374          47 :     if (marked_delete_ && state) {
     375           0 :         route->ClearState(partition->parent(), id_);
     376           0 :         delete state;
     377           0 :         state = NULL;
     378           0 :         return;
     379             :     }
     380             : 
     381             :     //Handle withdraw for following cases:
     382             :     //- Route is not having any active multicast exportable path or is deleted.
     383             :     //- associate(false): Bgp Peer has gone down and state needs to be removed.
     384          47 :     if (route_can_be_dissociated || !associate) {
     385           6 :         if (state == NULL) {
     386           0 :             return;
     387             :         }
     388             : 
     389           6 :         if (state->multicast_exported_ == true) {
     390           6 :             AgentXmppChannel::ControllerSendMcastRouteDelete(bgp_xmpp_peer,
     391             :                                                              route);
     392           6 :             state->multicast_exported_ = false;
     393             :         }
     394             : 
     395           6 :         if ((state->ingress_replication_exported_ == true)) {
     396           3 :             uint32_t label = state->label_;
     397           3 :             if (route->vrf()->IsPbbVrf()) {
     398           0 :                 label = state->isid_;
     399             :             }
     400           3 :             state->tunnel_type_ = TunnelType::INVALID;
     401           6 :             AgentXmppChannel::ControllerSendEvpnRouteDelete(bgp_xmpp_peer,
     402             :                                                             route,
     403           3 :                                                             state->vn_,
     404             :                                                             label,
     405           3 :                                                             state->destination_,
     406           3 :                                                             state->source_,
     407             :                                                             TunnelType::AllType());
     408           3 :             state->ingress_replication_exported_ = false;
     409             :         }
     410             : 
     411           6 :         route->ClearState(partition->parent(), id_);
     412           6 :         delete state;
     413           6 :         state = NULL;
     414           6 :         return;
     415             :     }
     416             : 
     417          41 :     if (marked_delete_) {
     418             :         //Ignore route updates on delete marked vrf
     419           0 :         return;
     420             :     }
     421             : 
     422          41 :     if (state == NULL) {
     423           6 :         state = new State();
     424           6 :         route->SetState(partition->parent(), id_, state);
     425             :     }
     426             : 
     427             :     // Bridge Broadcast route is sent with 255.255.255.255 address to control.
     428             :     // Inet Multicast route can be because of MVPN or EVPN:
     429             :     //  For EVPN: send route updates for ERMVPN and EVPN.
     430             :     //  For MVPN: send route updates for ERMVPN on native VRF
     431             :     //              and MVPN on ip-fabric VRF.
     432          41 :     if (route->vrf()->ShouldExportRoute()) {
     433          41 :         SubscribeMulticastRouting(agent, bgp_xmpp_peer, route, state);
     434             :     }
     435             : 
     436          41 :     bool ingress_replication = true;
     437          41 :     if ((route->GetTableType() == Agent::INET4_MULTICAST) &&
     438           0 :         (agent->params()->mvpn_ipv4_enable())) {
     439             : 
     440           0 :         ingress_replication = false;
     441             :     }
     442          41 :     if (ingress_replication) {
     443          41 :         SubscribeIngressReplication(agent, bgp_xmpp_peer, route, state);
     444             :     }
     445             : 
     446          41 :     state->force_chg_ = false;
     447          41 :     return;
     448             : }
     449             : 
     450          41 : void RouteExport::SubscribeIngressReplication(Agent *agent,
     451             :                                               AgentXmppChannel *bgp_xmpp_peer,
     452             :                                               AgentRoute *route,
     453             :                                               RouteExport::State *state) {
     454             :     //Check if bridging mode is enabled for this VN by verifying bridge flag
     455             :     //in local peer path.
     456          41 :     bool bridging = false;
     457          41 :     if (route->vrf() && route->vrf()->vn() && route->vrf()->vn()->bridging())
     458          19 :         bridging = true;
     459             : 
     460          41 :     const AgentPath *active_path = GetMulticastExportablePath(agent, route);
     461             :     //Sending ff:ff:ff:ff:ff:ff for evpn replication
     462          41 :     TunnelType::Type old_tunnel_type = state->tunnel_type_;
     463          41 :     uint32_t old_label = state->label_;
     464          41 :     TunnelType::Type new_tunnel_type = active_path->tunnel_type();
     465          41 :     uint32_t new_label = active_path->GetActiveLabel();
     466             : 
     467             :     //Evaluate if ingress replication subscription needs to be withdrawn.
     468             :     //Conditions: Tunnel type changed (VXLAN to MPLS) in turn label change,
     469             :     //bridging is disabled/enabled on VN
     470          41 :     if ((state->ingress_replication_exported_ == true) ||
     471          25 :         (state->force_chg_ == true)) {
     472          16 :         bool withdraw = false;
     473          16 :         uint32_t withdraw_label = 0;
     474             : 
     475          16 :         if (old_tunnel_type == TunnelType::VXLAN) {
     476           5 :             if ((new_tunnel_type != TunnelType::VXLAN) ||
     477             :                 (old_label != new_label)) {
     478           2 :                 withdraw_label = old_label;
     479           2 :                 withdraw = true;
     480             :             }
     481          11 :         } else if (new_tunnel_type == TunnelType::VXLAN) {
     482           2 :             withdraw = true;
     483             :         }
     484             : 
     485          16 :         if (route->vrf()->IsPbbVrf()) {
     486           0 :             if (state->isid_ != active_path->vxlan_id()) {
     487           0 :                 uint32_t old_isid = state->isid_;
     488           0 :                 state->isid_ = active_path->vxlan_id();
     489           0 :                 withdraw_label = old_isid;
     490           0 :                 withdraw = true;
     491             :             } else {
     492           0 :                 state->isid_ = active_path->vxlan_id();
     493             :             }
     494             :         }
     495             : 
     496          16 :         if (bridging == false)
     497           0 :             withdraw = true;
     498             : 
     499          16 :         if (withdraw) {
     500             :             AgentXmppChannel::ControllerSendEvpnRouteDelete
     501           4 :                 (bgp_xmpp_peer, route, state->vn_, withdraw_label,
     502           4 :                  state->destination_, state->source_,
     503           4 :                  state->tunnel_type_);
     504           4 :             state->ingress_replication_exported_ = false;
     505             :         }
     506             :     }
     507             : 
     508          41 :     state->isid_ = active_path->vxlan_id();
     509             :     //Update state values with new values if there is any change.
     510             :     //Also force change same i.e. update.
     511          41 :     if (active_path->tunnel_type() != state->tunnel_type_) {
     512          10 :         state->force_chg_ = true;
     513          10 :         state->tunnel_type_ = active_path->tunnel_type();
     514             :     }
     515             : 
     516          41 :     if (active_path->GetActiveLabel() != state->label_) {
     517          10 :         state->force_chg_ = true;
     518          10 :         state->label_ = active_path->GetActiveLabel();
     519             :     }
     520             : 
     521          41 :     if (route->vrf()->IsPbbVrf()) {
     522           0 :         if (active_path->vxlan_id() == 0) {
     523           0 :             return;
     524             :         }
     525             :     }
     526             : 
     527             :     //Subcribe if:
     528             :     //- Bridging is enabled
     529             :     //- First time (ingress_replication_exported is false)
     530             :     //- Forced Change
     531          41 :     if (bridging &&
     532          19 :         ((state->ingress_replication_exported_ == false) ||
     533          12 :         (state->force_chg_ == true))) {
     534           7 :         state->label_ = active_path->GetActiveLabel();
     535           7 :         state->vn_ = route->dest_vn_name();
     536             :         const TunnelNH *tnh =
     537           7 :             dynamic_cast<const TunnelNH *>(active_path->nexthop());
     538           7 :         if (tnh) {
     539           0 :             state->destination_ = tnh->GetDip()->to_string();
     540           0 :             state->source_ = tnh->GetSip()->to_string();
     541             :         }
     542           7 :         SecurityGroupList sg;
     543           7 :         TagList tag;
     544           7 :         state->ingress_replication_exported_ =
     545             :             AgentXmppChannel::ControllerSendEvpnRouteAdd
     546           7 :             (bgp_xmpp_peer, route,
     547             :              active_path->NexthopIp(agent),
     548           7 :              route->dest_vn_name(), state->label_,
     549             :              TunnelType::GetTunnelBmap(state->tunnel_type_),
     550           7 :              &sg, &tag, NULL, state->destination_,
     551          14 :              state->source_, PathPreference());
     552           7 :     }
     553             : }
     554             : 
     555           1 : bool RouteExport::DeleteState(DBTablePartBase *partition,
     556             :                               DBEntryBase *entry) {
     557             :     State *state = static_cast<State *>
     558           1 :                        (entry->GetState(partition->parent(), id_));
     559           1 :     if (state) {
     560           1 :         entry->ClearState(partition->parent(), id_);
     561           1 :         delete state;
     562             :     }
     563           1 :     return true;
     564             : }
     565             : 
     566          36 : void RouteExport::Walkdone(DBTable::DBTableWalkRef walk_ref,
     567             :                            DBTableBase *partition,
     568             :                            RouteExport *rt_export) {
     569          36 :     delete rt_export;
     570          36 : }
     571             : 
     572          36 : void RouteExport::Unregister() {
     573             :     //Start unregister process
     574          36 :     rt_table_->WalkTable(walk_ref_);
     575          36 : }
     576             : 
     577          36 : RouteExport* RouteExport::Init(AgentRouteTable *table,
     578             :                                AgentXmppChannel *bgp_xmpp_peer) {
     579          36 :     RouteExport *rt_export = new RouteExport(table);
     580          36 :     bool associate = true;
     581          72 :     rt_export->id_ = table->Register(boost::bind(&RouteExport::Notify,
     582             :                                      rt_export, table->agent(), bgp_xmpp_peer,
     583          36 :                                      associate, table->GetTableType(), _1, _2));
     584          36 :     return rt_export;
     585             : }
     586             : 

Generated by: LCOV version 1.14