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

Generated by: LCOV version 1.14