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: 128 459 27.9 %
Date: 2026-09-21 02:11:39 Functions: 18 35 51.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        2132 : BgpRoute::BgpRoute() {
      37        2132 : }
      38             : 
      39        2132 : BgpRoute::~BgpRoute() {
      40        2132 :     assert(GetPathList().empty());
      41        2132 : }
      42             : 
      43             : //
      44             : // Return the best path for this route.
      45             : // Skip aliased paths.
      46             : //
      47        4484 : const BgpPath *BgpRoute::BestPath() const {
      48        4484 :     for (Route::PathList::const_iterator it = GetPathList().begin();
      49        8968 :          it != GetPathList().end(); ++it) {
      50        4484 :         const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
      51        4484 :         if (path->GetFlags() & BgpPath::AliasedPath)
      52           0 :             continue;
      53        4484 :         return path;
      54             :     }
      55           0 :     return NULL;
      56             : }
      57             : 
      58             : //
      59             : // Insert given path and redo path selection.
      60             : //
      61         596 : void BgpRoute::InsertPath(BgpPath *path) {
      62         596 :     assert(!IsDeleted());
      63         596 :     const Path *prev_front = front();
      64             : 
      65         596 :     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         596 :     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         596 :         if (table->IsRoutingPolicySupported()) {
      90          92 :             if (!path->IsReplicated()) {
      91             :                 // Add sub-cluster extended community to all routes
      92             :                 // originated within a sub-cluster
      93          52 :                 uint32_t subcluster_id = SubClusterId();
      94          52 :                 if (subcluster_id) {
      95           0 :                     path->AddExtCommunitySubCluster(subcluster_id);
      96             :                 }
      97             :             }
      98          92 :             RoutingInstance *rtinstance = table->routing_instance();
      99          92 :             rtinstance->ProcessRoutingPolicy(this, path);
     100             :         } else {
     101         504 :             IPeer *peer = path->GetPeer();
     102         504 :             if (peer) {
     103             :                 // Take snapshot of original attribute
     104         280 :                 BgpAttr *out_attr = new BgpAttr(*(path->GetOriginalAttr()));
     105         280 :                 peer->ProcessPathTunnelEncapsulation(path, out_attr,
     106             :                     table->server()->extcomm_db(), table);
     107             :                 BgpAttrPtr modified_attr =
     108         280 :                     table->server()->attr_db()->Locate(out_attr);
     109             :                 // Update the path with new set of attributes
     110         280 :                 path->SetAttr(modified_attr, path->GetOriginalAttr());
     111         280 :             }
     112             :         }
     113             :     }
     114         596 :     insert(path);
     115             : 
     116         596 :     Sort(&BgpTable::PathSelection, prev_front);
     117             : 
     118             :     // Update counters.
     119         596 :     if (table)
     120         596 :         table->UpdatePathCount(path, +1);
     121         596 :     path->UpdatePeerRefCount(+1, table ? table->family() : Address::UNSPEC);
     122         596 : }
     123             : 
     124             : //
     125             : // Delete given path and redo path selection.
     126             : //
     127         596 : void BgpRoute::DeletePath(BgpPath *path) {
     128         596 :     const Path *prev_front = front();
     129             : 
     130         596 :     remove(path);
     131         596 :     Sort(&BgpTable::PathSelection, prev_front);
     132             : 
     133             :     // Update counters.
     134         596 :     BgpTable *table = static_cast<BgpTable *>(get_table());
     135         596 :     if (table)
     136         596 :         table->UpdatePathCount(path, -1);
     137         596 :     path->UpdatePeerRefCount(-1, table ? table->family() : Address::UNSPEC);
     138             : 
     139         596 :     delete path;
     140         596 : }
     141             : 
     142             : //
     143             : // Find first path with given path source.
     144             : // Skips secondary, aliased and resolved paths.
     145             : //
     146           0 : const BgpPath *BgpRoute::FindPath(BgpPath::PathSource src) const {
     147           0 :     for (Route::PathList::const_iterator it = GetPathList().begin();
     148           0 :          it != GetPathList().end(); ++it) {
     149             :         // Skip secondary paths.
     150           0 :         if (dynamic_cast<const BgpSecondaryPath *>(it.operator->())) {
     151           0 :             continue;
     152             :         }
     153             : 
     154           0 :         const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
     155           0 :         if (path->GetFlags() & BgpPath::AliasedPath) {
     156           0 :             continue;
     157             :         }
     158           0 :         if (path->GetFlags() & BgpPath::ResolvedPath) {
     159           0 :             continue;
     160             :         }
     161           0 :         if (path->GetSource() == src) {
     162           0 :             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         261 : BgpPath *BgpRoute::FindPath(const IPeer *peer, bool include_secondary) {
     173         261 :     for (Route::PathList::iterator it = GetPathList().begin();
     174         522 :          it != GetPathList().end(); ++it) {
     175         101 :         BgpPath *path = static_cast<BgpPath *>(it.operator->());
     176         101 :         if (path->GetSource() != BgpPath::BGP_XMPP) {
     177           0 :             continue;
     178             :         }
     179         101 :         if (path->GetFlags() & BgpPath::AliasedPath) {
     180           0 :             continue;
     181             :         }
     182         101 :         if (path->GetFlags() & BgpPath::ResolvedPath) {
     183           0 :             continue;
     184             :         }
     185         202 :         if (!include_secondary &&
     186         101 :                 dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
     187           0 :             continue;
     188             :         }
     189         101 :         if (path->GetPeer() == peer) {
     190         101 :             return path;
     191             :         }
     192             :     }
     193         160 :     return NULL;
     194             : }
     195             : 
     196           0 : const BgpPath *BgpRoute::FindPath(const IPeer *peer,
     197             :                                   bool include_secondary) const {
     198           0 :     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           0 : BgpPath *BgpRoute::FindPath(const IpAddress &nexthop) {
     206           0 :     for (Route::PathList::iterator it = GetPathList().begin();
     207           0 :          it != GetPathList().end(); ++it) {
     208           0 :         BgpPath *path = static_cast<BgpPath *>(it.operator->());
     209           0 :         if (path->GetSource() != BgpPath::BGP_XMPP) {
     210           0 :             continue;
     211             :         }
     212           0 :         if (path->IsResolved() || path->IsAliased()) {
     213           0 :             continue;
     214             :         }
     215           0 :         if (path->GetAttr()->nexthop() == nexthop) {
     216           0 :             return path;
     217             :         }
     218             :     }
     219           0 :     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         164 : BgpPath *BgpRoute::FindPath(BgpPath::PathSource src, const IPeer *peer,
     227             :                             uint32_t path_id) {
     228         164 :     for (Route::PathList::iterator it = GetPathList().begin();
     229         328 :          it != GetPathList().end(); ++it) {
     230             :         // Skip secondary paths.
     231         132 :         if (dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
     232           0 :             continue;
     233             :         }
     234             : 
     235         132 :         BgpPath *path = static_cast<BgpPath *>(it.operator->());
     236         132 :         if (path->GetFlags() & BgpPath::AliasedPath) {
     237           0 :             continue;
     238             :         }
     239         132 :         if (path->GetFlags() & BgpPath::ResolvedPath) {
     240           0 :             continue;
     241             :         }
     242         264 :         if (path->GetPeer() == peer && path->GetPathId() == path_id &&
     243         132 :             path->GetSource() == src) {
     244         132 :             return path;
     245             :         }
     246             :     }
     247          32 :     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         128 : BgpPath *BgpRoute::FindPath(BgpPath::PathSource src, uint32_t path_id) {
     255         128 :     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          32 : bool BgpRoute::RemovePath(BgpPath::PathSource src, const IPeer *peer,
     264             :                           uint32_t path_id) {
     265          32 :     for (Route::PathList::iterator it = GetPathList().begin();
     266          64 :          it != GetPathList().end(); it++) {
     267          32 :          BgpPath *path = static_cast<BgpPath *>(it.operator->());
     268             : 
     269             :         //
     270             :         // Skip secondary paths.
     271             :         //
     272          32 :         if (dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
     273           0 :             continue;
     274             :         }
     275             : 
     276          64 :         if (path->GetPeer() == peer && path->GetPathId() == path_id &&
     277          32 :             path->GetSource() == src) {
     278          32 :             DeletePath(path);
     279          32 :             return true;
     280             :         }
     281             :     }
     282           0 :     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          32 : bool BgpRoute::RemovePath(BgpPath::PathSource src, uint32_t path_id) {
     291          32 :     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           0 : bool BgpRoute::RemovePath(const IPeer *peer) {
     300           0 :     bool ret = false;
     301             : 
     302           0 :     for (Route::PathList::iterator it = GetPathList().begin(), next = it;
     303           0 :          it != GetPathList().end(); it = next) {
     304           0 :         next++;
     305           0 :         BgpPath *path = static_cast<BgpPath *>(it.operator->());
     306             : 
     307             :         //
     308             :         // Skip secondary paths.
     309             :         //
     310           0 :         if (dynamic_cast<BgpSecondaryPath *>(it.operator->())) {
     311           0 :             continue;
     312             :         }
     313             : 
     314           0 :         if (path->GetPeer() == peer) {
     315           0 :             DeletePath(path);
     316           0 :             ret = true;
     317             :         }
     318             :     }
     319           0 :     return ret;
     320             : }
     321             : 
     322             : //
     323             : // Check if the route is usable.
     324             : //
     325        1737 : bool BgpRoute::IsUsable() const {
     326        1737 :     if (IsDeleted())
     327         493 :         return false;
     328             : 
     329        1244 :     const BgpPath *path = BestPath();
     330        1244 :     if (!path || !path->IsFeasible())
     331           4 :         return false;
     332             : 
     333        1240 :     return true;
     334             : }
     335             : 
     336             : //
     337             : // Check if the route is valid.
     338             : //
     339           0 : bool BgpRoute::IsValid() const {
     340           0 :     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           0 : bool BgpRoute::DuplicateForwardingPath(const BgpPath *in_path) const {
     354           0 :     for (Route::PathList::const_iterator it = GetPathList().begin();
     355           0 :          it != GetPathList().end(); ++it) {
     356           0 :         const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
     357             : 
     358             :         // Bail if we reached the input path since the paths are sorted.
     359           0 :         if (path == in_path)
     360           0 :             return false;
     361             : 
     362             :         // Check the forwarding information.
     363           0 :         if (path->GetAttr()->nexthop() == in_path->GetAttr()->nexthop())
     364           0 :             return true;
     365             :     }
     366             : 
     367           0 :     return false;
     368             : }
     369             : 
     370             : //
     371             : // Find the secondary path matching secondary replicated info.
     372             : //
     373         644 : BgpPath *BgpRoute::FindSecondaryPath(BgpRoute *src_rt,
     374             :         BgpPath::PathSource src, const IPeer *peer, uint32_t path_id) {
     375         644 :     for (Route::PathList::iterator it = GetPathList().begin();
     376        1288 :          it != GetPathList().end(); ++it) {
     377         380 :         BgpSecondaryPath *path = dynamic_cast<BgpSecondaryPath *>(
     378         380 :             it.operator->());
     379             :         // Skip resolved paths. They'll be taken care of by the path
     380             :         // resolver infrastructure.
     381         512 :         if (path && (src_rt->table()->IsVpnTable()) &&
     382         132 :            (path->GetFlags() & BgpPath::ResolvedPath)) {
     383           0 :             continue;
     384             :         }
     385         760 :         if (path && path->src_rt() == src_rt &&
     386        1520 :             path->GetPeer() == peer && path->GetPathId() == path_id &&
     387         380 :             path->GetSource() == src) {
     388         380 :             return path;
     389             :         }
     390             :     }
     391         264 :     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         284 : bool BgpRoute::RemoveSecondaryPath(const BgpRoute *src_rt,
     399             :         BgpPath::PathSource src, const IPeer *peer, uint32_t path_id) {
     400         284 :     for (Route::PathList::iterator it = GetPathList().begin();
     401         568 :          it != GetPathList().end(); it++) {
     402             :         BgpSecondaryPath *path =
     403         284 :             dynamic_cast<BgpSecondaryPath *>(it.operator->());
     404             :         // Skip resolved paths. They'll be taken care of by the path
     405             :         // resolver infrastructure.
     406         416 :         if (path && (src_rt->table()->IsVpnTable()) &&
     407         132 :            (path->GetFlags() & BgpPath::ResolvedPath)) {
     408           0 :             continue;
     409             :         }
     410         568 :         if (path && path->src_rt() == src_rt &&
     411        1136 :             path->GetPeer() == peer && path->GetPathId() == path_id &&
     412         284 :             path->GetSource() == src) {
     413         284 :             DeletePath(path);
     414         284 :             return true;
     415             :         }
     416             :     }
     417             : 
     418           0 :     return false;
     419             : }
     420             : 
     421         264 : size_t BgpRoute::count() const {
     422         264 :     return GetPathList().size();
     423             : }
     424             : 
     425         380 : BgpTable *BgpRoute::table() {
     426         380 :     return dynamic_cast<BgpTable *>(get_table_partition()->parent());
     427             : }
     428             : 
     429         416 : const BgpTable *BgpRoute::table() const {
     430         416 :     return dynamic_cast<BgpTable *>(get_table_partition()->parent());
     431             : }
     432             : 
     433           0 : void BgpRoute::FillRouteInfo(const BgpTable *table,
     434             :     ShowRouteBrief *show_route) const {
     435           0 :     show_route->set_prefix(ToString());
     436           0 :     vector<ShowRoutePathBrief> show_route_paths;
     437           0 :     for (Route::PathList::const_iterator it = GetPathList().begin();
     438           0 :         it != GetPathList().end(); ++it) {
     439           0 :         const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
     440           0 :         ShowRoutePathBrief srp;
     441           0 :         const IPeer *peer = path->GetPeer();
     442           0 :         if (peer) {
     443           0 :             srp.set_source(peer->ToString());
     444             :         }
     445             : 
     446           0 :         srp.set_protocol(path->GetSourceString());
     447             : 
     448           0 :         const BgpAttr *attr = path->GetAttr();
     449           0 :         srp.set_local_preference(attr->local_pref());
     450           0 :         srp.set_med(attr->med());
     451           0 :         srp.set_next_hop(attr->nexthop().to_string());
     452           0 :         srp.set_label(path->GetLabel());
     453           0 :         show_route_paths.push_back(srp);
     454           0 :     }
     455           0 :     show_route->set_paths(show_route_paths);
     456           0 : }
     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           0 : static void FillRoutePathCommunityInfo(const Community *comm,
     470             :     ShowRoutePath *show_path, vector<string> *communities) {
     471           0 :     comm->BuildStringList(communities);
     472           0 : }
     473             : 
     474           0 : static void FillRoutePathExtCommunityInfo(const BgpTable *table,
     475             :     const ExtCommunity *extcomm,
     476             :     ShowRoutePath *show_path, vector<string> *communities) {
     477           0 :     const RoutingInstance *ri = table->routing_instance();
     478           0 :     const RoutingInstanceMgr *ri_mgr = ri->manager();
     479           0 :     vector<string> tunnel_encap = vector<string>();
     480             : 
     481           0 :     const ExtCommunity::ExtCommunityList &v = extcomm->communities();
     482           0 :     for (ExtCommunity::ExtCommunityList::const_iterator it = v.begin();
     483           0 :         it != v.end(); ++it) {
     484           0 :         if (ExtCommunity::is_route_target(*it)) {
     485           0 :             RouteTarget rt(*it);
     486           0 :             communities->push_back(rt.ToString());
     487           0 :         } else if (ExtCommunity::is_default_gateway(*it)) {
     488           0 :             DefaultGateway dgw(*it);
     489           0 :             communities->push_back(dgw.ToString());
     490           0 :         } else if (ExtCommunity::is_es_import(*it)) {
     491           0 :             EsImport es_import(*it);
     492           0 :             communities->push_back(es_import.ToString());
     493           0 :         } else if (ExtCommunity::is_esi_label(*it)) {
     494           0 :             EsiLabel esi_label(*it);
     495           0 :             communities->push_back(esi_label.ToString());
     496           0 :         } 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           0 :         } else if (ExtCommunity::is_local_sequence_number(*it)) {
     501           0 :             LocalSequenceNumber lsn(*it);
     502           0 :             communities->push_back(lsn.ToString());
     503           0 :         } else if (ExtCommunity::is_etree(*it)) {
     504           0 :             ETree etree(*it);
     505           0 :             communities->push_back(etree.ToString());
     506           0 :         } else if (ExtCommunity::is_router_mac(*it)) {
     507           0 :             RouterMac router_mac(*it);
     508           0 :             communities->push_back(router_mac.ToString());
     509           0 :         } else if (ExtCommunity::is_origin_vn(*it)) {
     510           0 :             OriginVn origin_vn(*it);
     511           0 :             communities->push_back(origin_vn.ToString());
     512           0 :             int vn_index = origin_vn.vn_index();
     513           0 :             show_path->set_origin_vn(
     514           0 :                 ri_mgr->GetVirtualNetworkByVnIndex(vn_index));
     515           0 :         } else if (ExtCommunity::is_security_group(*it)) {
     516           0 :             SecurityGroup sg(*it);
     517           0 :             communities->push_back(sg.ToString());
     518           0 :         } else if (ExtCommunity::is_security_group4(*it)) {
     519           0 :             SecurityGroup4ByteAs sg(*it);
     520           0 :             communities->push_back(sg.ToString());
     521           0 :         } else if (ExtCommunity::is_site_of_origin(*it)) {
     522           0 :             SiteOfOrigin soo(*it);
     523           0 :             communities->push_back(soo.ToString());
     524           0 :         } else if (ExtCommunity::is_tunnel_encap(*it)) {
     525           0 :             TunnelEncap encap(*it);
     526           0 :             communities->push_back(encap.ToString());
     527           0 :             TunnelEncapType::Encap id = encap.tunnel_encap();
     528           0 :             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           0 :     show_path->set_tunnel_encap(tunnel_encap);
     564           0 : }
     565             : 
     566           0 : static void FillRoutePathLargeCommunityInfo(const LargeCommunity *largecomm,
     567             :     ShowRoutePath *show_path, vector<string> *communities) {
     568             : 
     569           0 :     const LargeCommunity::LargeCommunityList &v = largecomm->communities();
     570           0 :     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           0 : }
     585             : 
     586           0 : static void FillEdgeForwardingInfo(const EdgeForwarding *edge_forwarding,
     587             :     ShowRoutePath *show_path) {
     588           0 :     vector<ShowEdgeForwarding> show_ef_list;
     589             :     vector<EdgeForwardingSpec::Edge *> edge_list =
     590           0 :         edge_forwarding->edge_forwarding().edge_list;
     591           0 :     for (vector<EdgeForwardingSpec::Edge *>::const_iterator it =
     592           0 :             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           0 :     show_path->set_edge_forwarding(show_ef_list);
     605           0 : }
     606             : 
     607           0 : static void FillEdgeDiscoveryInfo(const EdgeDiscovery *edge_discovery,
     608             :     ShowRoutePath *show_path) {
     609           0 :     vector<ShowEdgeDiscovery> show_ed_list;
     610             :     vector<EdgeDiscoverySpec::Edge *> edge_list =
     611           0 :         edge_discovery->edge_discovery().edge_list;
     612           0 :     int idx = 0;
     613           0 :     for (vector<EdgeDiscoverySpec::Edge *>::const_iterator it =
     614           0 :             edge_list.begin();
     615           0 :          it != edge_list.end(); ++it, ++idx) {
     616           0 :         const EdgeDiscoverySpec::Edge *edge = *it;
     617           0 :         ShowEdgeDiscovery show_ed;
     618           0 :         ostringstream oss;
     619             :         uint32_t first_label, last_label;
     620           0 :         oss << edge->GetIp4Address();
     621           0 :         show_ed.set_address(oss.str());
     622           0 :         oss.str("");
     623           0 :         oss.clear();
     624           0 :         edge->GetLabels(&first_label, &last_label);
     625           0 :         oss << first_label << "-" << last_label;
     626           0 :         show_ed.set_labels(oss.str());
     627           0 :         show_ed_list.push_back(show_ed);
     628           0 :     }
     629           0 :     show_path->set_edge_discovery(show_ed_list);
     630           0 : }
     631             : 
     632           0 : static void FillOriginVnPathInfo(const OriginVnPath *ovnpath,
     633             :     ShowRoutePath *show_path) {
     634           0 :     const OriginVnPath::OriginVnList &v = ovnpath->origin_vns();
     635           0 :     vector<string> origin_vn_path = vector<string>();
     636           0 :     for (OriginVnPath::OriginVnList::const_iterator it = v.begin();
     637           0 :          it != v.end(); ++it) {
     638           0 :         OriginVn origin_vn(*it);
     639           0 :         origin_vn_path.push_back(origin_vn.ToString());
     640             :     }
     641           0 :     show_path->set_origin_vn_path(origin_vn_path);
     642           0 : }
     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           0 : void BgpRoute::FillRouteInfo(const BgpTable *table,
     656             :     ShowRoute *show_route, const string &source, const string &protocol) const {
     657           0 :     const RoutingInstance *ri = table->routing_instance();
     658             : 
     659           0 :     show_route->set_prefix(ToString());
     660           0 :     show_route->set_last_modified(
     661           0 :         integerToString(UTCUsecToPTime(last_change_at())));
     662             : 
     663           0 :     vector<ShowRoutePath> show_route_paths;
     664           0 :     for (Route::PathList::const_iterator it = GetPathList().begin();
     665           0 :          it != GetPathList().end(); ++it) {
     666           0 :         const BgpPath *path = static_cast<const BgpPath *>(it.operator->());
     667           0 :         ShowRoutePath srp;
     668           0 :         const IPeer *peer = path->GetPeer();
     669             : 
     670             :         // Filter against peer source, if specified.
     671           0 :         if (!source.empty() && (!peer || source != peer->ToString()))
     672           0 :             continue;
     673             : 
     674             :         // Filter against path protocol, if specified.
     675           0 :         if (!protocol.empty() && protocol != path->GetSourceString())
     676           0 :             continue;
     677             : 
     678           0 :         if (peer) {
     679           0 :             srp.set_source(peer->ToString());
     680             :         }
     681             : 
     682           0 :         const BgpPeer *bgp_peer = dynamic_cast<const BgpPeer *>(peer);
     683           0 :         if (bgp_peer) {
     684           0 :             srp.set_local_as(bgp_peer->local_as());
     685           0 :             srp.set_peer_as(bgp_peer->peer_as());
     686           0 :             srp.set_peer_router_id(bgp_peer->bgp_identifier_string());
     687             :         }
     688             : 
     689           0 :         const BgpAttr *attr = path->GetAttr();
     690           0 :         if (attr->edge_forwarding()) {
     691           0 :             FillEdgeForwardingInfo(attr->edge_forwarding(), &srp);
     692             :         }
     693           0 :         if (attr->edge_discovery()) {
     694           0 :             FillEdgeDiscoveryInfo(attr->edge_discovery(), &srp);
     695             :         }
     696           0 :         if (attr->sub_protocol().empty()) {
     697           0 :             srp.set_protocol(path->GetSourceString());
     698             :         } else {
     699           0 :             const string sbp = attr->sub_protocol();
     700           0 :             srp.set_protocol(path->GetSourceString() + " (" + sbp + ")");
     701           0 :         }
     702           0 :         srp.set_origin(attr->origin_string());
     703           0 :         if (attr->as_path() != NULL)
     704           0 :             srp.set_as_path(attr->as_path()->path().ToString());
     705           0 :         else if (attr->aspath_4byte() != NULL)
     706           0 :             srp.set_as_path(attr->aspath_4byte()->path().ToString());
     707           0 :         if (attr->as4_path() != NULL)
     708           0 :             srp.set_as4_path(attr->as4_path()->path().ToString());
     709           0 :         srp.set_local_preference(attr->local_pref());
     710           0 :         srp.set_med(attr->med());
     711           0 :         srp.set_next_hop(attr->nexthop().to_string());
     712           0 :         srp.set_label(path->GetLabel());
     713           0 :         srp.set_flags(path->GetFlagsStringList());
     714           0 :         srp.set_last_modified(
     715           0 :             integerToString(UTCUsecToPTime(path->time_stamp_usecs())));
     716           0 :         if (path->IsReplicated()) {
     717             :             const BgpSecondaryPath *replicated;
     718           0 :             replicated = static_cast<const BgpSecondaryPath *>(path);
     719           0 :             srp.set_replicated(true);
     720           0 :             srp.set_primary_table(replicated->src_table()->name());
     721             :         } else {
     722           0 :             srp.set_replicated(false);
     723             :             Address::Family vpn_family =
     724           0 :                 Address::VpnFamilyFromFamily(table->family());
     725             :             const RoutePathReplicator *replicator =
     726           0 :                 table->server()->replicator(vpn_family);
     727           0 :             if (replicator) {
     728           0 :                 srp.set_secondary_tables(
     729           0 :                     replicator->GetReplicatedTableNameList(table, this, path));
     730             :             }
     731             :         }
     732           0 :         if (attr->cluster_list()) {
     733           0 :             FillRoutePathClusterListInfo(attr->cluster_list(), &srp);
     734             :         }
     735           0 :         vector<string> communities;
     736           0 :         if (attr->community()) {
     737           0 :             FillRoutePathCommunityInfo(attr->community(), &srp, &communities);
     738             :         }
     739           0 :         if (attr->ext_community()) {
     740           0 :             FillRoutePathExtCommunityInfo(table, attr->ext_community(), &srp,
     741             :                     &communities);
     742             :         }
     743           0 :         if (attr->large_community()) {
     744           0 :             FillRoutePathLargeCommunityInfo(attr->large_community(), &srp,
     745             :                     &communities);
     746             :         }
     747           0 :         if (!communities.empty()){
     748           0 :             srp.set_communities(communities);
     749             :         }
     750           0 :         if (srp.get_origin_vn().empty() &&
     751           0 :             !table->IsVpnTable() && path->IsVrfOriginated()) {
     752           0 :             srp.set_origin_vn(ri->GetVirtualNetworkName());
     753             :         }
     754           0 :         if (attr->origin_vn_path()) {
     755           0 :             FillOriginVnPathInfo(attr->origin_vn_path(), &srp);
     756             :         }
     757           0 :         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           0 :         if (attr->originator_id().to_ulong()) {
     764           0 :             srp.set_originator_id(attr->originator_id().to_string());
     765             :         }
     766             : 
     767           0 :         show_route_paths.push_back(srp);
     768           0 :     }
     769           0 :     show_route->set_paths(show_route_paths);
     770           0 : }
     771             : 
     772          96 : void BgpRoute::NotifyOrDelete() {
     773          96 :     if (!front()) {
     774          96 :         Delete();
     775             :     } else {
     776           0 :         Notify();
     777             :     }
     778          96 : }
     779             : 
     780          52 : uint32_t BgpRoute::SubClusterId() const {
     781          52 :     BgpTable *table = static_cast<BgpTable *>(get_table());
     782          52 :     const BgpConfigManager *config_manager_ = table->server()->config_manager();
     783          52 :     if (!config_manager_) {
     784           0 :         return 0;
     785             :     }
     786             :     const BgpProtocolConfig *proto =
     787          52 :         config_manager_->GetProtocolConfig(BgpConfigManager::kMasterInstance);
     788          52 :     if (!proto) {
     789           0 :         return 0;
     790             :     }
     791          52 :     return proto->subcluster_id();
     792             : }

Generated by: LCOV version 1.14