LCOV - code coverage report
Current view: top level - bgp - bgp_xmpp_rtarget_manager.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 149 154 96.8 %
Date: 2026-06-22 02:21:21 Functions: 23 23 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : #include "bgp/bgp_xmpp_rtarget_manager.h"
       5             : 
       6             : #include <utility>
       7             : #include <vector>
       8             : 
       9             : #include <boost/foreach.hpp>
      10             : 
      11             : #include "bgp/ipeer.h"
      12             : #include "bgp/bgp_peer_types.h"
      13             : #include "bgp/bgp_server.h"
      14             : #include "bgp/bgp_xmpp_channel.h"
      15             : #include "routing-instance/routing_instance.h"
      16             : 
      17             : using std::make_pair;
      18             : using std::pair;
      19             : using std::string;
      20             : using std::vector;
      21             : 
      22       10062 : BgpXmppRTargetManager::BgpXmppRTargetManager(BgpXmppChannel *bgp_xmpp_channel) :
      23       10062 :         bgp_xmpp_channel_(bgp_xmpp_channel) {
      24       10062 : }
      25             : 
      26       20106 : BgpXmppRTargetManager::~BgpXmppRTargetManager() {
      27       20106 : }
      28             : 
      29       15944 : bool BgpXmppRTargetManager::IsSubscriptionEmpty() const {
      30       15944 :     return bgp_xmpp_channel_->IsSubscriptionEmpty();
      31             : }
      32             : 
      33        7342 : bool BgpXmppRTargetManager::IsSubscriptionGrStale(
      34             :         RoutingInstance *instance) const {
      35        7342 :     return bgp_xmpp_channel_->IsSubscriptionGrStale(instance);
      36             : }
      37             : 
      38        7342 : bool BgpXmppRTargetManager::IsSubscriptionLlgrStale(
      39             :         RoutingInstance *instance) const {
      40        7342 :     return bgp_xmpp_channel_->IsSubscriptionLlgrStale(instance);
      41             : }
      42             : 
      43       41994 : bool BgpXmppRTargetManager::delete_in_progress() const {
      44       41994 :     return bgp_xmpp_channel_->delete_in_progress();
      45             : }
      46             : 
      47       78475 : const IPeer *BgpXmppRTargetManager::Peer() const {
      48       78475 :     return bgp_xmpp_channel_->Peer();
      49             : }
      50             : 
      51       78475 : void BgpXmppRTargetManager::Enqueue(DBRequest *req) const {
      52             :     RoutingInstanceMgr *instance_mgr =
      53       78475 :         bgp_xmpp_channel_->bgp_server()->routing_instance_mgr();
      54       78475 :     RoutingInstance *master = instance_mgr->GetDefaultRoutingInstance();
      55       78475 :     BgpTable *table = master->GetTable(Address::RTARGET);
      56       78475 :     assert(table);
      57       78475 :     table->Enqueue(req);
      58       78475 : }
      59             : 
      60       60387 : BgpAttrPtr BgpXmppRTargetManager::GetRouteTargetRouteAttr() const {
      61       60387 :     BgpAttrSpec attrs;
      62       60387 :     BgpAttrNextHop nexthop(bgp_xmpp_channel_->bgp_server()->bgp_identifier());
      63       60387 :     attrs.push_back(&nexthop);
      64       60387 :     BgpAttrOrigin origin(BgpAttrOrigin::IGP);
      65       60387 :     attrs.push_back(&origin);
      66      120774 :     return bgp_xmpp_channel_->bgp_server()->attr_db()->Locate(attrs);
      67       60387 : }
      68             : 
      69       74039 : int BgpXmppRTargetManager::local_autonomous_system() const {
      70       74039 :     return bgp_xmpp_channel_->bgp_server()->local_autonomous_system();
      71             : }
      72             : 
      73             : const BgpXmppRTargetManager::RouteTargetList &
      74       14885 : BgpXmppRTargetManager::GetSubscribedRTargets(RoutingInstance *instance) const {
      75       14885 :     return bgp_xmpp_channel_->GetSubscribedRTargets(instance);
      76             : }
      77             : 
      78       37824 : uint32_t BgpXmppRTargetManager::GetRTargetRouteFlag(
      79             :         const RouteTarget &rtarget) const {
      80             :     PublishedRTargetRoutes::const_iterator rt_loc =
      81       37824 :         rtarget_routes_.find(rtarget);
      82       37825 :     if (rt_loc == rtarget_routes_.end() || rt_loc->second.empty())
      83       31022 :         return 0;
      84             : 
      85             :     // Route is [llgr-]stale only if it is stale for all instances in the set.
      86        6803 :     uint32_t flags = BgpPath::Stale | BgpPath::LlgrStale;
      87       14820 :     BOOST_FOREACH(RoutingInstance *routing_instance, rt_loc->second) {
      88        7402 :         if (!IsSubscriptionGrStale(routing_instance))
      89        6787 :             flags &= ~BgpPath::Stale;
      90        7402 :         if (!IsSubscriptionLlgrStale(routing_instance))
      91        7382 :             flags &= ~BgpPath::LlgrStale;
      92        7402 :         if (!flags)
      93        6787 :             break;
      94             :     }
      95             : 
      96        6803 :     return flags;
      97             : }
      98             : 
      99       78583 : void BgpXmppRTargetManager::RTargetRouteOp(as_t asn,
     100             :                                            const RouteTarget &rtarget,
     101             :                                            BgpAttrPtr attr, bool add_change,
     102             :                                            uint32_t flags) const {
     103       78583 :     if (add_change && delete_in_progress())
     104           0 :         return;
     105             : 
     106       78583 :     DBRequest req;
     107       78583 :     RTargetPrefix rt_prefix(asn, rtarget);
     108       78583 :     req.key.reset(new RTargetTable::RequestKey(rt_prefix, Peer()));
     109       78582 :     if (add_change) {
     110             :         // Find correct rtarget route flags if not already known.
     111       42065 :         if (!flags)
     112       37824 :             flags = GetRTargetRouteFlag(rtarget);
     113       42066 :         req.data.reset(new RTargetTable::RequestData(attr, flags, 0, 0, 0));
     114       42066 :         req.oper = DBRequest::DB_ENTRY_ADD_CHANGE;
     115             :     } else {
     116       36517 :         req.oper = DBRequest::DB_ENTRY_DELETE;
     117             :     }
     118       78583 :     Enqueue(&req);
     119       78583 : }
     120             : 
     121        1077 : void BgpXmppRTargetManager::ASNUpdateCallback(as_t old_asn,
     122             :                                               as_t old_local_asn) const {
     123        1077 :     if (local_autonomous_system() == (int)old_local_asn)
     124         501 :         return;
     125        1077 :     if (IsSubscriptionEmpty())
     126         501 :         return;
     127             : 
     128             :     // Delete the route and add with new local ASN
     129         576 :     BgpAttrPtr attr = GetRouteTargetRouteAttr();
     130         576 :     for (PublishedRTargetRoutes::const_iterator it = rtarget_routes_.begin();
     131        6107 :             it != rtarget_routes_.end(); it++) {
     132        5531 :         RTargetRouteOp(old_local_asn, it->first, NULL, false);
     133        5531 :         RTargetRouteOp(local_autonomous_system(), it->first, attr, true);
     134             :     }
     135         576 : }
     136             : 
     137       57908 : void BgpXmppRTargetManager::AddNewRTargetRoute(RoutingInstance *rtinstance,
     138             :         const RouteTarget &rtarget, BgpAttrPtr attr) {
     139       57908 :     PublishedRTargetRoutes::iterator rt_loc = rtarget_routes_.find(rtarget);
     140       57908 :     if (rt_loc == rtarget_routes_.end()) {
     141             :         pair<PublishedRTargetRoutes::iterator, bool> ret =
     142       31022 :             rtarget_routes_.insert(make_pair(rtarget, RoutingInstanceList()));
     143             : 
     144       31022 :         rt_loc = ret.first;
     145             : 
     146             :         // Send rtarget route ADD
     147       31022 :         RTargetRouteOp(local_autonomous_system(), rtarget, attr, true);
     148             :     }
     149       57908 :     rt_loc->second.insert(rtinstance);
     150       57908 : }
     151             : 
     152        4446 : void BgpXmppRTargetManager::DeleteRTargetRoute(
     153             :         RoutingInstance *rtinstance, const RouteTarget &rtarget) {
     154        4446 :     PublishedRTargetRoutes::iterator rt_loc = rtarget_routes_.find(rtarget);
     155        4446 :     assert(rt_loc != rtarget_routes_.end());
     156        4446 :     assert(rt_loc->second.erase(rtinstance));
     157        4446 :     if (rt_loc->second.empty()) {
     158        3185 :         rtarget_routes_.erase(rtarget);
     159             :         // Send rtarget route DELETE
     160        3185 :         RTargetRouteOp(local_autonomous_system(), rtarget, NULL, false);
     161             :     }
     162        4446 : }
     163             : 
     164        1325 : void BgpXmppRTargetManager::RoutingInstanceCallback(
     165             :         RoutingInstance *rt_instance, RouteTargetList *targets) {
     166             :     // Import list in the routing instance
     167        1325 :     const RouteTargetList &new_list = rt_instance->GetImportList();
     168             : 
     169             :     // Previous route target list for which the rtarget route was added
     170        1325 :     RouteTargetList *current = targets;
     171        1325 :     RouteTargetList::iterator cur_next_it, cur_it;
     172        1325 :     cur_it = cur_next_it = current->begin();
     173        1325 :     RouteTargetList::const_iterator new_it = new_list.begin();
     174             : 
     175        1325 :     pair<RouteTargetList::iterator, bool> r;
     176        1325 :     BgpAttrPtr attr = GetRouteTargetRouteAttr();
     177      137774 :     while (cur_it != current->end() && new_it != new_list.end()) {
     178      136449 :         if (*new_it < *cur_it) {
     179         219 :             r = current->insert(*new_it);
     180         219 :             assert(r.second);
     181         219 :             AddNewRTargetRoute(rt_instance, *new_it, attr);
     182         219 :             new_it++;
     183      136230 :         } else if (*new_it > *cur_it) {
     184         966 :             cur_next_it++;
     185         966 :             DeleteRTargetRoute(rt_instance, *cur_it);
     186         966 :             current->erase(cur_it);
     187         966 :             cur_it = cur_next_it;
     188             :         } else {
     189             :             // Update
     190      135264 :             cur_it++;
     191      135264 :             new_it++;
     192             :         }
     193      136449 :         cur_next_it = cur_it;
     194             :     }
     195        1515 :     for (; new_it != new_list.end(); ++new_it) {
     196         190 :         r = current->insert(*new_it);
     197         190 :         assert(r.second);
     198         190 :         AddNewRTargetRoute(rt_instance, *new_it, attr);
     199             :     }
     200        1325 :     for (cur_next_it = cur_it;
     201        1325 :          cur_it != current->end();
     202           0 :          cur_it = cur_next_it) {
     203           0 :         cur_next_it++;
     204           0 :         DeleteRTargetRoute(rt_instance, *cur_it);
     205           0 :         current->erase(cur_it);
     206             :     }
     207        1325 : }
     208             : 
     209         861 : void BgpXmppRTargetManager::UpdateRouteTargetRouteFlag(
     210             :         RoutingInstance *routing_instance, const RouteTargetList &targets,
     211             :         uint32_t flags) const {
     212         861 :     BgpAttrPtr attr = GetRouteTargetRouteAttr();
     213        9343 :     BOOST_FOREACH(RouteTarget rtarget, targets) {
     214             :         // Update route target route [llgr-]stale flag status.
     215        4241 :         RTargetRouteOp(local_autonomous_system(), rtarget, attr, true, flags);
     216             :     }
     217         861 : }
     218             : 
     219        6180 : void BgpXmppRTargetManager::Close() {
     220        6180 :     if (rtarget_routes_.empty())
     221        2871 :         return;
     222             : 
     223        3309 :     for (PublishedRTargetRoutes::iterator it = rtarget_routes_.begin();
     224       31110 :             it != rtarget_routes_.end(); it++) {
     225       27801 :         RTargetRouteOp(local_autonomous_system(), it->first, NULL, false);
     226             :     }
     227        3309 :     rtarget_routes_.clear();
     228             : }
     229             : 
     230         252 : void BgpXmppRTargetManager::Stale(const RouteTargetList &targets) const {
     231         252 :     BgpAttrPtr attr = GetRouteTargetRouteAttr();
     232             : 
     233             :     // Update route targets to clear STALE flag.
     234        2796 :     BOOST_FOREACH(RouteTarget rtarget, targets) {
     235             :         PublishedRTargetRoutes::const_iterator rt_loc =
     236        1272 :             rtarget_routes_.find(rtarget);
     237        1272 :         assert(rt_loc != rtarget_routes_.end());
     238             : 
     239             :         // Send rtarget route ADD
     240        1272 :         RTargetRouteOp(local_autonomous_system(), rtarget, attr, true);
     241             :     }
     242         252 : }
     243             : 
     244             : // Add/Delete rtarget route for import route target of the routing instance.
     245       15029 : void BgpXmppRTargetManager::PublishRTargetRoute(RoutingInstance *rt_instance,
     246             :                                                 bool add_change) {
     247       15029 :     if (IsSubscriptionEmpty())
     248          72 :         return;
     249             : 
     250       14957 :     if (add_change) {
     251      129053 :         BOOST_FOREACH(RouteTarget rtarget, GetSubscribedRTargets(rt_instance)) {
     252       57499 :             AddNewRTargetRoute(rt_instance, rtarget, GetRouteTargetRouteAttr());
     253             :         }
     254             :     } else {
     255        7862 :         BOOST_FOREACH(RouteTarget rtarget, GetSubscribedRTargets(rt_instance)) {
     256        3480 :             DeleteRTargetRoute(rt_instance, rtarget);
     257             :         }
     258             :     }
     259             : }
     260             : 
     261        1900 : void BgpXmppRTargetManager::FillInfo(BgpNeighborRoutingInstance *instance,
     262             :                                      const RouteTargetList &targets) const {
     263        1900 :     vector<string> import_targets;
     264       13300 :     BOOST_FOREACH(RouteTarget rt, targets) {
     265        5700 :         import_targets.push_back(rt.ToString());
     266             :     }
     267        1900 :     instance->set_import_targets(import_targets);
     268        1900 : }

Generated by: LCOV version 1.14