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

Generated by: LCOV version 1.14