LCOV - code coverage report
Current view: top level - bgp - bgp_route.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 359 459 78.2 %
Date: 2026-11-09 02:10:49 Functions: 32 35 91.4 %
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 "bgp/bgp_config_ifmap.h"
       7             : #include "bgp/bgp_route.h"
       8             : 
       9             : #include "bgp/bgp_peer.h"
      10             : #include "bgp/bgp_server.h"
      11             : #include "bgp/bgp_table.h"
      12             : #include "bgp/extended-community/default_gateway.h"
      13             : #include "bgp/extended-community/es_import.h"
      14             : #include "bgp/extended-community/esi_label.h"
      15             : #include "bgp/extended-community/etree.h"
      16             : #include "bgp/extended-community/load_balance.h"
      17             : #include "bgp/extended-community/mac_mobility.h"
      18             : #include "bgp/extended-community/local_sequence_number.h"
      19             : #include "bgp/extended-community/multicast_flags.h"
      20             : #include "bgp/extended-community/router_mac.h"
      21             : #include "bgp/extended-community/site_of_origin.h"
      22             : #include "bgp/extended-community/source_as.h"
      23             : #include "bgp/extended-community/sub_cluster.h"
      24             : #include "bgp/extended-community/tag.h"
      25             : #include "bgp/extended-community/vrf_route_import.h"
      26             : #include "bgp/origin-vn/origin_vn.h"
      27             : #include "bgp/routing-instance/routepath_replicator.h"
      28             : #include "bgp/routing-instance/routing_instance.h"
      29             : #include "bgp/security_group/security_group.h"
      30             : #include "bgp/tunnel_encap/tunnel_encap.h"
      31             : #include "bgp/large-community/tag.h"
      32             : 
      33             : using std::string;
      34             : using std::vector;
      35             : using std::ostringstream;
      36             : 
      37     3431970 : BgpRoute::BgpRoute() {
      38     3431391 : }
      39             : 
      40     3431944 : BgpRoute::~BgpRoute() {
      41     3431944 :     assert(GetPathList().empty());
      42     3431736 : }
      43             : 
      44             : //
      45             : // Return the best path for this route.
      46             : // Skip aliased paths.
      47             : //
      48     7404250 : const BgpPath *BgpRoute::BestPath() const {
      49     7404250 :     for (Route::PathList::const_iterator it = GetPathList().begin();
      50    14804221 :          it != GetPathList().end(); ++it) {
      51     7400536 :         const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
      52     7400536 :         if (path->GetFlags() & BgpPath::AliasedPath)
      53          28 :             continue;
      54     7401365 :         return path;
      55             :     }
      56         832 :     return NULL;
      57             : }
      58             : 
      59             : //
      60             : // Insert given path and redo path selection.
      61             : //
      62      966373 : void BgpRoute::InsertPath(BgpPath *path) {
      63      966373 :     assert(!IsDeleted());
      64      966365 :     const Path *prev_front = front();
      65             : 
      66      966272 :     BgpTable *table = static_cast<BgpTable *>(get_table());
      67             :     // 'table' is not expected to be null, suspect it is checked here because of
      68             :     // unit tests.
      69      966313 :     if (table) {
      70             :         // Default Tunnel Encapsulation processing is done if configured for
      71             :         // the address family on the peer.
      72             :         // If routing policy is supported on the table(family)it is handled in
      73             :         // ProcessRoutingPolicy where other changes may be made to the
      74             :         // attributes. Also, when there are routing policy configuration changes
      75             :         // the attributes needs to be re-evaluated using the original attributes
      76             :         // and Default Tunnel Encapsulation also needs to be re-applied, this
      77             :         // will be handled seamlessly since ProcessRoutingPolicy will be called
      78             :         // in that case.
      79             :         // Note that currently routing policies are not supported on VPN address
      80             :         // families, however this is ensuring that it will be handed correctly
      81             :         // in future. Additionally, for labeled inet routes, routing policies
      82             :         // are supported so the Default Tunnel Encapsulation needs to be handled
      83             :         //  in ProcessRoutingPolicy.
      84             :         // If the table(family) does not support routing policies the Default
      85             :         // Tunnel Encapsulation processing is handled here. The original and
      86             :         // modified attributes are saved and are not expected to be modified
      87             :         // further. Note that the configuration is not applied if the path
      88             :         // already has tunnel encapsulation specified.
      89             : 
      90      965527 :         if (table->IsRoutingPolicySupported()) {
      91      451157 :             if (!path->IsReplicated()) {
      92             :                 // Add sub-cluster extended community to all routes
      93             :                 // originated within a sub-cluster
      94       63987 :                 uint32_t subcluster_id = SubClusterId();
      95       63970 :                 if (subcluster_id) {
      96           0 :                     path->AddExtCommunitySubCluster(subcluster_id);
      97             :                 }
      98             :             }
      99      451132 :             RoutingInstance *rtinstance = table->routing_instance();
     100      451136 :             rtinstance->ProcessRoutingPolicy(this, path);
     101             :         } else {
     102      514353 :             IPeer *peer = path->GetPeer();
     103      514441 :             if (peer) {
     104             :                 // Take snapshot of original attribute
     105      262640 :                 BgpAttr *out_attr = new BgpAttr(*(path->GetOriginalAttr()));
     106      262678 :                 peer->ProcessPathTunnelEncapsulation(path, out_attr,
     107             :                     table->server()->extcomm_db(), table);
     108             :                 BgpAttrPtr modified_attr =
     109      262626 :                     table->server()->attr_db()->Locate(out_attr);
     110             :                 // Update the path with new set of attributes
     111      262680 :                 path->SetAttr(modified_attr, path->GetOriginalAttr());
     112      262681 :             }
     113             :         }
     114             :     }
     115      966487 :     insert(path);
     116             : 
     117      966452 :     Sort(&BgpTable::PathSelection, prev_front);
     118             : 
     119             :     // Update counters.
     120      966423 :     if (table)
     121      965638 :         table->UpdatePathCount(path, +1);
     122      966487 :     path->UpdatePeerRefCount(+1, table ? table->family() : Address::UNSPEC);
     123      966499 : }
     124             : 
     125             : //
     126             : // Delete given path and redo path selection.
     127             : //
     128      965896 : void BgpRoute::DeletePath(BgpPath *path) {
     129      965896 :     const Path *prev_front = front();
     130             : 
     131      965741 :     remove(path);
     132      966127 :     Sort(&BgpTable::PathSelection, prev_front);
     133             : 
     134             :     // Update counters.
     135      965728 :     BgpTable *table = static_cast<BgpTable *>(get_table());
     136      965752 :     if (table)
     137      964967 :         table->UpdatePathCount(path, -1);
     138      966279 :     path->UpdatePeerRefCount(-1, table ? table->family() : Address::UNSPEC);
     139             : 
     140      966254 :     delete path;
     141      966336 : }
     142             : 
     143             : //
     144             : // Find first path with given path source.
     145             : // Skips secondary, aliased and resolved paths.
     146             : //
     147        1396 : const BgpPath *BgpRoute::FindPath(BgpPath::PathSource src) const {
     148        1396 :     for (Route::PathList::const_iterator it = GetPathList().begin();
     149        2792 :          it != GetPathList().end(); ++it) {
     150             :         // Skip secondary paths.
     151        1396 :         if (dynamic_cast<const BgpSecondaryPath *>(it.operator->())) {
     152           0 :             continue;
     153             :         }
     154             : 
     155        1396 :         const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
     156        1396 :         if (path->GetFlags() & BgpPath::AliasedPath) {
     157           0 :             continue;
     158             :         }
     159        1396 :         if (path->GetFlags() & BgpPath::ResolvedPath) {
     160           0 :             continue;
     161             :         }
     162        1396 :         if (path->GetSource() == src) {
     163        1396 :             return path;
     164             :         }
     165             :     }
     166           0 :     return NULL;
     167             : }
     168             : 
     169             : //
     170             : // Find path added by BGP_XMPP peer.
     171             : // Skips non BGP_XMPP, secondary, aliased and resolved paths.
     172             : //
     173      446150 : BgpPath *BgpRoute::FindPath(const IPeer *peer, bool include_secondary) {
     174      446150 :     for (Route::PathList::iterator it = GetPathList().begin();
     175     1069385 :          it != GetPathList().end(); ++it) {
     176      283487 :         BgpPath *path = static_cast<BgpPath *>(it.operator->());
     177      283487 :         if (path->GetSource() != BgpPath::BGP_XMPP) {
     178         742 :             continue;
     179             :         }
     180      282756 :         if (path->GetFlags() & BgpPath::AliasedPath) {
     181           0 :             continue;
     182             :         }
     183      282748 :         if (path->GetFlags() & BgpPath::ResolvedPath) {
     184        1302 :             continue;
     185             :         }
     186      562886 :         if (!include_secondary &&
     187      281441 :                 dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
     188         815 :             continue;
     189             :         }
     190      280630 :         if (path->GetPeer() == peer) {
     191      194999 :             return path;
     192             :         }
     193             :     }
     194      251202 :     return NULL;
     195             : }
     196             : 
     197         260 : const BgpPath *BgpRoute::FindPath(const IPeer *peer,
     198             :                                   bool include_secondary) const {
     199         260 :     return const_cast<BgpRoute *>(this)->FindPath(peer, include_secondary);
     200             : }
     201             : 
     202             : //
     203             : // Find path with given nexthop address.
     204             : // Skips non BGP_XMPP, aliased and resolved paths.
     205             : //
     206         103 : BgpPath *BgpRoute::FindPath(const IpAddress &nexthop) {
     207         103 :     for (Route::PathList::iterator it = GetPathList().begin();
     208         430 :          it != GetPathList().end(); ++it) {
     209         157 :         BgpPath *path = static_cast<BgpPath *>(it.operator->());
     210         157 :         if (path->GetSource() != BgpPath::BGP_XMPP) {
     211           0 :             continue;
     212             :         }
     213         157 :         if (path->IsResolved() || path->IsAliased()) {
     214          50 :             continue;
     215             :         }
     216         107 :         if (path->GetAttr()->nexthop() == nexthop) {
     217          45 :             return path;
     218             :         }
     219             :     }
     220          58 :     return NULL;
     221             : }
     222             : 
     223             : //
     224             : // Find path added by peer with given path id and path source.
     225             : // Skips secondary, aliased and resolved paths.
     226             : //
     227       81579 : BgpPath *BgpRoute::FindPath(BgpPath::PathSource src, const IPeer *peer,
     228             :                             uint32_t path_id) {
     229       81579 :     for (Route::PathList::iterator it = GetPathList().begin();
     230      171138 :          it != GetPathList().end(); ++it) {
     231             :         // Skip secondary paths.
     232       59903 :         if (dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
     233          82 :             continue;
     234             :         }
     235             : 
     236       59821 :         BgpPath *path = static_cast<BgpPath *>(it.operator->());
     237       59821 :         if (path->GetFlags() & BgpPath::AliasedPath) {
     238           0 :             continue;
     239             :         }
     240       59821 :         if (path->GetFlags() & BgpPath::ResolvedPath) {
     241         151 :             continue;
     242             :         }
     243      115583 :         if (path->GetPeer() == peer && path->GetPathId() == path_id &&
     244       55913 :             path->GetSource() == src) {
     245       55913 :             return path;
     246             :         }
     247             :     }
     248       25666 :     return NULL;
     249             : }
     250             : 
     251             : //
     252             : // Find path added given source and path id - peer must be NULL.
     253             : // Skips secondary paths and resolved paths.
     254             : //
     255       62510 : BgpPath *BgpRoute::FindPath(BgpPath::PathSource src, uint32_t path_id) {
     256       62510 :     return FindPath(src, NULL, path_id);
     257             : }
     258             : 
     259             : //
     260             : // Remove path added by peer with given path id and source.
     261             : // Skips secondary paths.
     262             : // Return true if the path is found and removed, false otherwise.
     263             : //
     264       64453 : bool BgpRoute::RemovePath(BgpPath::PathSource src, const IPeer *peer,
     265             :                           uint32_t path_id) {
     266      111207 :     for (Route::PathList::iterator it = GetPathList().begin();
     267      222414 :          it != GetPathList().end(); it++) {
     268       93553 :          BgpPath *path = static_cast<BgpPath *>(it.operator->());
     269             : 
     270             :         //
     271             :         // Skip secondary paths.
     272             :         //
     273       93553 :         if (dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
     274          61 :             continue;
     275             :         }
     276             : 
     277      140293 :         if (path->GetPeer() == peer && path->GetPathId() == path_id &&
     278       46801 :             path->GetSource() == src) {
     279       46799 :             DeletePath(path);
     280       46799 :             return true;
     281             :         }
     282             :     }
     283       17654 :     return false;
     284             : }
     285             : 
     286             : //
     287             : // Remove path added given source and path id - peer must be NULL.
     288             : // Skips secondary paths.
     289             : // Return true if the path is found and removed, false otherwise.
     290             : //
     291       45268 : bool BgpRoute::RemovePath(BgpPath::PathSource src, uint32_t path_id) {
     292       45268 :     return RemovePath(src, NULL, path_id);
     293             : }
     294             : 
     295             : //
     296             : // Remove path added by peer with given path id and source.
     297             : // Skips secondary paths.
     298             : // Return true if the path is found and removed, false otherwise.
     299             : //
     300         857 : bool BgpRoute::RemovePath(const IPeer *peer) {
     301         857 :     bool ret = false;
     302             : 
     303        1714 :     for (Route::PathList::iterator it = GetPathList().begin(), next = it;
     304        3290 :          it != GetPathList().end(); it = next) {
     305         788 :         next++;
     306         788 :         BgpPath *path = static_cast<BgpPath *>(it.operator->());
     307             : 
     308             :         //
     309             :         // Skip secondary paths.
     310             :         //
     311         788 :         if (dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
     312           0 :             continue;
     313             :         }
     314             : 
     315         788 :         if (path->GetPeer() == peer) {
     316         777 :             DeletePath(path);
     317         777 :             ret = true;
     318             :         }
     319             :     }
     320         857 :     return ret;
     321             : }
     322             : 
     323             : //
     324             : // Check if the route is usable.
     325             : //
     326     2460845 : bool BgpRoute::IsUsable() const {
     327     2460845 :     if (IsDeleted())
     328      781830 :         return false;
     329             : 
     330     1678976 :     const BgpPath *path = BestPath();
     331     1678771 :     if (!path || !path->IsFeasible())
     332        7531 :         return false;
     333             : 
     334     1671206 :     return true;
     335             : }
     336             : 
     337             : //
     338             : // Check if the route is valid.
     339             : //
     340       82557 : bool BgpRoute::IsValid() const {
     341       82557 :     return IsUsable();
     342             : }
     343             : 
     344             : //
     345             : // Check if there's a better path with the same forwarding information.
     346             : //
     347             : // Return true if we find such a path, false otherwise.
     348             : //
     349             : // The forwarding information we look at is just the next hop. We don't
     350             : // consider the label since there's could be transient cases where we
     351             : // have 2 paths with the same next hop and different labels.  We don't
     352             : // want to treat these as unique paths.
     353             : //
     354       27043 : bool BgpRoute::DuplicateForwardingPath(const BgpPath *in_path) const {
     355       27043 :     for (Route::PathList::const_iterator it = GetPathList().begin();
     356       58507 :          it != GetPathList().end(); ++it) {
     357       29254 :         const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
     358             : 
     359             :         // Bail if we reached the input path since the paths are sorted.
     360       29254 :         if (path == in_path)
     361       27052 :             return false;
     362             : 
     363             :         // Check the forwarding information.
     364        3845 :         if (path->GetAttr()->nexthop() == in_path->GetAttr()->nexthop())
     365        1643 :             return true;
     366             :     }
     367             : 
     368           0 :     return false;
     369             : }
     370             : 
     371             : //
     372             : // Find the secondary path matching secondary replicated info.
     373             : //
     374     1473154 : BgpPath *BgpRoute::FindSecondaryPath(BgpRoute *src_rt,
     375             :         BgpPath::PathSource src, const IPeer *peer, uint32_t path_id) {
     376     1473154 :     for (Route::PathList::iterator it = GetPathList().begin();
     377     3504130 :          it != GetPathList().end(); ++it) {
     378     1234375 :         BgpSecondaryPath *path = dynamic_cast<BgpSecondaryPath *>(
     379     1234375 :             it.operator->());
     380             :         // Skip resolved paths. They'll be taken care of by the path
     381             :         // resolver infrastructure.
     382     2021928 :         if (path && (src_rt->table()->IsVpnTable()) &&
     383      787588 :            (path->GetFlags() & BgpPath::ResolvedPath)) {
     384           8 :             continue;
     385             :         }
     386     2254451 :         if (path && path->src_rt() == src_rt &&
     387     4444254 :             path->GetPeer() == peer && path->GetPathId() == path_id &&
     388      955321 :             path->GetSource() == src) {
     389      955565 :             return path;
     390             :         }
     391             :     }
     392      517657 :     return NULL;
     393             : }
     394             : 
     395             : //
     396             : // Remove the secondary path matching secondary replicated info.
     397             : // Return true if the path is found and removed, false otherwise.
     398             : //
     399      578958 : bool BgpRoute::RemoveSecondaryPath(const BgpRoute *src_rt,
     400             :         BgpPath::PathSource src, const IPeer *peer, uint32_t path_id) {
     401      593441 :     for (Route::PathList::iterator it = GetPathList().begin();
     402     1186781 :          it != GetPathList().end(); it++) {
     403             :         BgpSecondaryPath *path =
     404      593389 :             dynamic_cast<BgpSecondaryPath *>(it.operator->());
     405             :         // Skip resolved paths. They'll be taken care of by the path
     406             :         // resolver infrastructure.
     407      962230 :         if (path && (src_rt->table()->IsVpnTable()) &&
     408      368860 :            (path->GetFlags() & BgpPath::ResolvedPath)) {
     409           0 :             continue;
     410             :         }
     411     1182110 :         if (path && path->src_rt() == src_rt &&
     412     2354373 :             path->GetPeer() == peer && path->GetPathId() == path_id &&
     413      578769 :             path->GetSource() == src) {
     414      578975 :             DeletePath(path);
     415      579315 :             return true;
     416             :         }
     417             :     }
     418             : 
     419           0 :     return false;
     420             : }
     421             : 
     422      538079 : size_t BgpRoute::count() const {
     423      538079 :     return GetPathList().size();
     424             : }
     425             : 
     426     1237434 : BgpTable *BgpRoute::table() {
     427     1237434 :     return dynamic_cast<BgpTable *>(get_table_partition()->parent());
     428             : }
     429             : 
     430     1359789 : const BgpTable *BgpRoute::table() const {
     431     1359789 :     return dynamic_cast<BgpTable *>(get_table_partition()->parent());
     432             : }
     433             : 
     434         148 : void BgpRoute::FillRouteInfo(const BgpTable *table,
     435             :     ShowRouteBrief *show_route) const {
     436         148 :     show_route->set_prefix(ToString());
     437         148 :     vector<ShowRoutePathBrief> show_route_paths;
     438         148 :     for (Route::PathList::const_iterator it = GetPathList().begin();
     439         780 :         it != GetPathList().end(); ++it) {
     440         242 :         const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
     441         242 :         ShowRoutePathBrief srp;
     442         242 :         const IPeer *peer = path->GetPeer();
     443         242 :         if (peer) {
     444          16 :             srp.set_source(peer->ToString());
     445             :         }
     446             : 
     447         242 :         srp.set_protocol(path->GetSourceString());
     448             : 
     449         242 :         const BgpAttr *attr = path->GetAttr();
     450         242 :         srp.set_local_preference(attr->local_pref());
     451         242 :         srp.set_med(attr->med());
     452         242 :         srp.set_next_hop(attr->nexthop().to_string());
     453         242 :         srp.set_label(path->GetLabel());
     454         242 :         show_route_paths.push_back(srp);
     455         242 :     }
     456         148 :     show_route->set_paths(show_route_paths);
     457         148 : }
     458             : 
     459           0 : static void FillRoutePathClusterListInfo(const ClusterList *clist,
     460             :     ShowRoutePath *show_path) {
     461           0 :     const vector<uint32_t> &list = clist->cluster_list().cluster_list;
     462           0 :     vector<string> cluster_list = vector<string>();
     463           0 :     for (vector<uint32_t>::const_iterator it = list.begin(); it != list.end();
     464           0 :          ++it) {
     465           0 :         cluster_list.push_back(Ip4Address(*it).to_string());
     466             :     }
     467           0 :     show_path->set_cluster_list(cluster_list);
     468           0 : }
     469             : 
     470         192 : static void FillRoutePathCommunityInfo(const Community *comm,
     471             :     ShowRoutePath *show_path, vector<string> *communities) {
     472         192 :     comm->BuildStringList(communities);
     473         192 : }
     474             : 
     475         328 : static void FillRoutePathExtCommunityInfo(const BgpTable *table,
     476             :     const ExtCommunity *extcomm,
     477             :     ShowRoutePath *show_path, vector<string> *communities) {
     478         328 :     const RoutingInstance *ri = table->routing_instance();
     479         328 :     const RoutingInstanceMgr *ri_mgr = ri->manager();
     480         328 :     vector<string> tunnel_encap = vector<string>();
     481             : 
     482         328 :     const ExtCommunity::ExtCommunityList &v = extcomm->communities();
     483         328 :     for (ExtCommunity::ExtCommunityList::const_iterator it = v.begin();
     484         871 :         it != v.end(); ++it) {
     485         543 :         if (ExtCommunity::is_route_target(*it)) {
     486         111 :             RouteTarget rt(*it);
     487         111 :             communities->push_back(rt.ToString());
     488         432 :         } else if (ExtCommunity::is_default_gateway(*it)) {
     489           0 :             DefaultGateway dgw(*it);
     490           0 :             communities->push_back(dgw.ToString());
     491         432 :         } else if (ExtCommunity::is_es_import(*it)) {
     492           0 :             EsImport es_import(*it);
     493           0 :             communities->push_back(es_import.ToString());
     494         432 :         } else if (ExtCommunity::is_esi_label(*it)) {
     495           0 :             EsiLabel esi_label(*it);
     496           0 :             communities->push_back(esi_label.ToString());
     497         432 :         } else if (ExtCommunity::is_mac_mobility(*it)) {
     498           0 :             MacMobility mm(*it);
     499           0 :             communities->push_back(mm.ToString());
     500           0 :             show_path->set_sequence_no(integerToString(mm.sequence_number()));
     501         432 :         } else if (ExtCommunity::is_local_sequence_number(*it)) {
     502           0 :             LocalSequenceNumber lsn(*it);
     503           0 :             communities->push_back(lsn.ToString());
     504         432 :         } else if (ExtCommunity::is_etree(*it)) {
     505           2 :             ETree etree(*it);
     506           2 :             communities->push_back(etree.ToString());
     507         430 :         } else if (ExtCommunity::is_router_mac(*it)) {
     508           0 :             RouterMac router_mac(*it);
     509           0 :             communities->push_back(router_mac.ToString());
     510         430 :         } else if (ExtCommunity::is_origin_vn(*it)) {
     511         287 :             OriginVn origin_vn(*it);
     512         287 :             communities->push_back(origin_vn.ToString());
     513         287 :             int vn_index = origin_vn.vn_index();
     514         287 :             show_path->set_origin_vn(
     515         574 :                 ri_mgr->GetVirtualNetworkByVnIndex(vn_index));
     516         143 :         } else if (ExtCommunity::is_security_group(*it)) {
     517          19 :             SecurityGroup sg(*it);
     518          19 :             communities->push_back(sg.ToString());
     519         124 :         } else if (ExtCommunity::is_security_group4(*it)) {
     520           0 :             SecurityGroup4ByteAs sg(*it);
     521           0 :             communities->push_back(sg.ToString());
     522         124 :         } else if (ExtCommunity::is_site_of_origin(*it)) {
     523           0 :             SiteOfOrigin soo(*it);
     524           0 :             communities->push_back(soo.ToString());
     525         124 :         } else if (ExtCommunity::is_tunnel_encap(*it)) {
     526         124 :             TunnelEncap encap(*it);
     527         124 :             communities->push_back(encap.ToString());
     528         124 :             TunnelEncapType::Encap id = encap.tunnel_encap();
     529         124 :             tunnel_encap.push_back(TunnelEncapType::TunnelEncapToString(id));
     530           0 :         } else if (ExtCommunity::is_load_balance(*it)) {
     531           0 :             LoadBalance load_balance(*it);
     532           0 :             communities->push_back(load_balance.ToString());
     533             : 
     534           0 :             ShowLoadBalance show_load_balance;
     535           0 :             load_balance.ShowAttribute(&show_load_balance);
     536           0 :             show_path->set_load_balance(show_load_balance);
     537           0 :         } else if (ExtCommunity::is_tag(*it)) {
     538           0 :             Tag tag(*it);
     539           0 :             communities->push_back(tag.ToString());
     540           0 :         } else if (ExtCommunity::is_tag4(*it)) {
     541           0 :             Tag4ByteAs tag(*it);
     542           0 :             communities->push_back(tag.ToString());
     543           0 :         } else if (ExtCommunity::is_source_as(*it)) {
     544           0 :             SourceAs sas(*it);
     545           0 :             communities->push_back(sas.ToString());
     546           0 :         } else if (ExtCommunity::is_sub_cluster(*it)) {
     547           0 :             SubCluster sc(*it);
     548           0 :             communities->push_back(sc.ToString());
     549           0 :         } else if (ExtCommunity::is_vrf_route_import(*it)) {
     550           0 :             VrfRouteImport rt_import(*it);
     551           0 :             communities->push_back(rt_import.ToString());
     552           0 :         } else if (ExtCommunity::is_multicast_flags(*it)) {
     553           0 :             MulticastFlags mf(*it);
     554           0 :             communities->push_back(mf.ToString());
     555             :         } else {
     556             :             char temp[50];
     557           0 :             int len = snprintf(temp, sizeof(temp), "ext community: ");
     558           0 :             for (size_t i = 0; i < it->size(); i++) {
     559           0 :                 len += snprintf(temp+len, sizeof(temp) - len, "%02x", (*it)[i]);
     560             :             }
     561           0 :             communities->push_back(string(temp));
     562             :         }
     563             :     }
     564         328 :     show_path->set_tunnel_encap(tunnel_encap);
     565         328 : }
     566             : 
     567         314 : static void FillRoutePathLargeCommunityInfo(const LargeCommunity *largecomm,
     568             :     ShowRoutePath *show_path, vector<string> *communities) {
     569             : 
     570         314 :     const LargeCommunity::LargeCommunityList &v = largecomm->communities();
     571         314 :     for (const auto &lc : v) {
     572           0 :         if (LargeCommunity::is_tag(lc)) {
     573           0 :             TagLC tag(lc);
     574           0 :             communities->push_back(tag.ToString());
     575             :         } else {
     576             :             char temp[50];
     577           0 :             int len = snprintf(temp, sizeof(temp), "large community: ");
     578           0 :             for (size_t i = 0; i < lc.size(); i++) {
     579           0 :                 len += snprintf(temp + len, sizeof(temp) - len, "%02x",
     580           0 :                                 lc[i]);
     581             :             }
     582           0 :             communities->push_back(string(temp));
     583             :         }
     584             :     }
     585         314 : }
     586             : 
     587           8 : static void FillEdgeForwardingInfo(const EdgeForwarding *edge_forwarding,
     588             :     ShowRoutePath *show_path) {
     589           8 :     vector<ShowEdgeForwarding> show_ef_list;
     590             :     vector<EdgeForwardingSpec::Edge *> edge_list =
     591           8 :         edge_forwarding->edge_forwarding().edge_list;
     592           8 :     for (vector<EdgeForwardingSpec::Edge *>::const_iterator it =
     593           8 :             edge_list.begin(); it != edge_list.end(); ++it) {
     594           0 :         const EdgeForwardingSpec::Edge *edge = *it;
     595           0 :         ShowEdgeForwarding show_ef;
     596           0 :         ostringstream oss;
     597           0 :         oss << edge->GetInboundIp4Address() << ":" << edge->inbound_label;
     598           0 :         show_ef.set_in_address_label(oss.str());
     599           0 :         oss.str("");
     600           0 :         oss.clear();
     601           0 :         oss << edge->GetOutboundIp4Address() << ":" << edge->outbound_label;
     602           0 :         show_ef.set_out_address_label(oss.str());
     603           0 :         show_ef_list.push_back(show_ef);
     604           0 :     }
     605           8 :     show_path->set_edge_forwarding(show_ef_list);
     606           8 : }
     607             : 
     608           8 : static void FillEdgeDiscoveryInfo(const EdgeDiscovery *edge_discovery,
     609             :     ShowRoutePath *show_path) {
     610           8 :     vector<ShowEdgeDiscovery> show_ed_list;
     611             :     vector<EdgeDiscoverySpec::Edge *> edge_list =
     612           8 :         edge_discovery->edge_discovery().edge_list;
     613           8 :     int idx = 0;
     614           8 :     for (vector<EdgeDiscoverySpec::Edge *>::const_iterator it =
     615           8 :             edge_list.begin();
     616          32 :          it != edge_list.end(); ++it, ++idx) {
     617          24 :         const EdgeDiscoverySpec::Edge *edge = *it;
     618          24 :         ShowEdgeDiscovery show_ed;
     619          24 :         ostringstream oss;
     620             :         uint32_t first_label, last_label;
     621          24 :         oss << edge->GetIp4Address();
     622          24 :         show_ed.set_address(oss.str());
     623          24 :         oss.str("");
     624          24 :         oss.clear();
     625          24 :         edge->GetLabels(&first_label, &last_label);
     626          24 :         oss << first_label << "-" << last_label;
     627          24 :         show_ed.set_labels(oss.str());
     628          24 :         show_ed_list.push_back(show_ed);
     629          24 :     }
     630           8 :     show_path->set_edge_discovery(show_ed_list);
     631           8 : }
     632             : 
     633         192 : static void FillOriginVnPathInfo(const OriginVnPath *ovnpath,
     634             :     ShowRoutePath *show_path) {
     635         192 :     const OriginVnPath::OriginVnList &v = ovnpath->origin_vns();
     636         192 :     vector<string> origin_vn_path = vector<string>();
     637         192 :     for (OriginVnPath::OriginVnList::const_iterator it = v.begin();
     638         384 :          it != v.end(); ++it) {
     639         192 :         OriginVn origin_vn(*it);
     640         192 :         origin_vn_path.push_back(origin_vn.ToString());
     641             :     }
     642         192 :     show_path->set_origin_vn_path(origin_vn_path);
     643         192 : }
     644             : 
     645           0 : static void FillPmsiTunnelInfo(const PmsiTunnel *pmsi_tunnel,
     646             :     const ExtCommunity *ext, ShowRoutePath *show_path) {
     647           0 :     ShowPmsiTunnel spt;
     648           0 :     spt.set_type(pmsi_tunnel->pmsi_tunnel().GetTunnelTypeString());
     649           0 :     spt.set_ar_type(pmsi_tunnel->pmsi_tunnel().GetTunnelArTypeString());
     650           0 :     spt.set_identifier(pmsi_tunnel->identifier().to_string());
     651           0 :     spt.set_label(pmsi_tunnel->GetLabel(ext));
     652           0 :     spt.set_flags(pmsi_tunnel->pmsi_tunnel().GetTunnelFlagsStrings());
     653           0 :     show_path->set_pmsi_tunnel(spt);
     654           0 : }
     655             : 
     656        6322 : void BgpRoute::FillRouteInfo(const BgpTable *table,
     657             :     ShowRoute *show_route, const string &source, const string &protocol) const {
     658        6322 :     const RoutingInstance *ri = table->routing_instance();
     659             : 
     660        6322 :     show_route->set_prefix(ToString());
     661        6344 :     show_route->set_last_modified(
     662       12684 :         integerToString(UTCUsecToPTime(last_change_at())));
     663             : 
     664        6345 :     vector<ShowRoutePath> show_route_paths;
     665        6341 :     for (Route::PathList::const_iterator it = GetPathList().begin();
     666       25461 :          it != GetPathList().end(); ++it) {
     667        6394 :         const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
     668        6394 :         ShowRoutePath srp;
     669        6396 :         const IPeer *peer = path->GetPeer();
     670             : 
     671             :         // Filter against peer source, if specified.
     672        6395 :         if (!source.empty() && (!peer || source != peer->ToString()))
     673         597 :             continue;
     674             : 
     675             :         // Filter against path protocol, if specified.
     676        5799 :         if (!protocol.empty() && protocol != path->GetSourceString())
     677         195 :             continue;
     678             : 
     679        5604 :         if (peer) {
     680        5254 :             srp.set_source(peer->ToString());
     681             :         }
     682             : 
     683        5607 :         const BgpPeer *bgp_peer = dynamic_cast<const BgpPeer *>(peer);
     684        5607 :         if (bgp_peer) {
     685        5198 :             srp.set_local_as(bgp_peer->local_as());
     686        5197 :             srp.set_peer_as(bgp_peer->peer_as());
     687        5196 :             srp.set_peer_router_id(bgp_peer->bgp_identifier_string());
     688             :         }
     689             : 
     690        5603 :         const BgpAttr *attr = path->GetAttr();
     691        5605 :         if (attr->edge_forwarding()) {
     692           8 :             FillEdgeForwardingInfo(attr->edge_forwarding(), &srp);
     693             :         }
     694        5605 :         if (attr->edge_discovery()) {
     695           8 :             FillEdgeDiscoveryInfo(attr->edge_discovery(), &srp);
     696             :         }
     697        5603 :         if (attr->sub_protocol().empty()) {
     698        5591 :             srp.set_protocol(path->GetSourceString());
     699             :         } else {
     700          12 :             const string sbp = attr->sub_protocol();
     701          12 :             srp.set_protocol(path->GetSourceString() + " (" + sbp + ")");
     702          12 :         }
     703        5600 :         srp.set_origin(attr->origin_string());
     704        5603 :         if (attr->as_path() != NULL)
     705        5233 :             srp.set_as_path(attr->as_path()->path().ToString());
     706         367 :         else if (attr->aspath_4byte() != NULL)
     707           0 :             srp.set_as_path(attr->aspath_4byte()->path().ToString());
     708        5607 :         if (attr->as4_path() != NULL)
     709           8 :             srp.set_as4_path(attr->as4_path()->path().ToString());
     710        5608 :         srp.set_local_preference(attr->local_pref());
     711        5606 :         srp.set_med(attr->med());
     712        5604 :         srp.set_next_hop(attr->nexthop().to_string());
     713        5605 :         srp.set_label(path->GetLabel());
     714        5604 :         srp.set_flags(path->GetFlagsStringList());
     715        5607 :         srp.set_last_modified(
     716       11203 :             integerToString(UTCUsecToPTime(path->time_stamp_usecs())));
     717        5609 :         if (path->IsReplicated()) {
     718             :             const BgpSecondaryPath *replicated;
     719         101 :             replicated = static_cast<const BgpSecondaryPath *>(path);
     720         101 :             srp.set_replicated(true);
     721         101 :             srp.set_primary_table(replicated->src_table()->name());
     722             :         } else {
     723        5506 :             srp.set_replicated(false);
     724             :             Address::Family vpn_family =
     725        5507 :                 Address::VpnFamilyFromFamily(table->family());
     726             :             const RoutePathReplicator *replicator =
     727        5506 :                 table->server()->replicator(vpn_family);
     728        5504 :             if (replicator) {
     729        5421 :                 srp.set_secondary_tables(
     730       10850 :                     replicator->GetReplicatedTableNameList(table, this, path));
     731             :             }
     732             :         }
     733        5595 :         if (attr->cluster_list()) {
     734           0 :             FillRoutePathClusterListInfo(attr->cluster_list(), &srp);
     735             :         }
     736        5594 :         vector<string> communities;
     737        5595 :         if (attr->community()) {
     738         192 :             FillRoutePathCommunityInfo(attr->community(), &srp, &communities);
     739             :         }
     740        5595 :         if (attr->ext_community()) {
     741         328 :             FillRoutePathExtCommunityInfo(table, attr->ext_community(), &srp,
     742             :                     &communities);
     743             :         }
     744        5595 :         if (attr->large_community()) {
     745         314 :             FillRoutePathLargeCommunityInfo(attr->large_community(), &srp,
     746             :                     &communities);
     747             :         }
     748        5595 :         if (!communities.empty()){
     749         304 :             srp.set_communities(communities);
     750             :         }
     751        5595 :         if (srp.get_origin_vn().empty() &&
     752        5595 :             !table->IsVpnTable() && path->IsVrfOriginated()) {
     753        5287 :             srp.set_origin_vn(ri->GetVirtualNetworkName());
     754             :         }
     755        5596 :         if (attr->origin_vn_path()) {
     756         192 :             FillOriginVnPathInfo(attr->origin_vn_path(), &srp);
     757             :         }
     758        5595 :         if (attr->pmsi_tunnel()) {
     759           0 :             const ExtCommunity *extcomm = attr->ext_community();
     760           0 :             if (extcomm) {
     761           0 :                 FillPmsiTunnelInfo(attr->pmsi_tunnel(), extcomm, &srp);
     762             :             }
     763             :         }
     764        5598 :         if (attr->originator_id().to_ulong()) {
     765           0 :             srp.set_originator_id(attr->originator_id().to_string());
     766             :         }
     767             : 
     768        5596 :         show_route_paths.push_back(srp);
     769        6381 :     }
     770        6332 :     show_route->set_paths(show_route_paths);
     771        6327 : }
     772             : 
     773       51738 : void BgpRoute::NotifyOrDelete() {
     774       51738 :     if (!front()) {
     775       48076 :         Delete();
     776             :     } else {
     777        3662 :         Notify();
     778             :     }
     779       51738 : }
     780             : 
     781       63990 : uint32_t BgpRoute::SubClusterId() const {
     782       63990 :     BgpTable *table = static_cast<BgpTable *>(get_table());
     783       63990 :     const BgpConfigManager *config_manager_ = table->server()->config_manager();
     784       63988 :     if (!config_manager_) {
     785           0 :         return 0;
     786             :     }
     787             :     const BgpProtocolConfig *proto =
     788       63988 :         config_manager_->GetProtocolConfig(BgpConfigManager::kMasterInstance);
     789       63972 :     if (!proto) {
     790        2638 :         return 0;
     791             :     }
     792       61334 :     return proto->subcluster_id();
     793             : }

Generated by: LCOV version 1.14