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

Generated by: LCOV version 1.14