LCOV - code coverage report
Current view: top level - bgp/inet6 - inet6_table.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 89 101 88.1 %
Date: 2026-11-09 02:10:49 Functions: 12 12 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include "bgp/inet6/inet6_table.h"
       7             : 
       8             : #include "bgp/bgp_server.h"
       9             : #include "bgp/bgp_update.h"
      10             : #include "bgp/inet6vpn/inet6vpn_route.h"
      11             : #include "bgp/routing-instance/path_resolver.h"
      12             : #include "bgp/routing-instance/routing_instance.h"
      13             : 
      14       51137 : Inet6Table::Inet6Table(DB *db, const std::string &name)
      15       51137 :     : BgpTable(db, name) {
      16       51137 : }
      17             : 
      18     5080849 : size_t Inet6Table::HashFunction(const Inet6Prefix &prefix) {
      19     5080849 :     const Ip6Address::bytes_type &addr_bytes = prefix.ToBytes();
      20    10155925 :     return boost::hash_range(addr_bytes.begin(), addr_bytes.end());
      21             : }
      22             : 
      23      196088 : std::unique_ptr<DBEntry> Inet6Table::AllocEntry(const DBRequestKey *key) const {
      24      196088 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      25      196088 :     return std::unique_ptr<DBEntry> (new Inet6Route(rkey->prefix));
      26             : }
      27             : 
      28          20 : std::unique_ptr<DBEntry> Inet6Table::AllocEntryStr(
      29             :         const std::string &key_str) const {
      30          20 :     Inet6Prefix prefix = Inet6Prefix::FromString(key_str);
      31          40 :     return std::unique_ptr<DBEntry> (new Inet6Route(prefix));
      32             : }
      33             : 
      34     3502613 : size_t Inet6Table::Hash(const DBEntry *entry) const {
      35     3502613 :     const Inet6Route *route = static_cast<const Inet6Route *>(entry);
      36     3502613 :     size_t value = HashFunction(route->GetPrefix());
      37     3499485 :     return value % DB::PartitionCount();
      38             : }
      39             : 
      40       38116 : size_t Inet6Table::Hash(const DBRequestKey *key) const {
      41       38116 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      42       38116 :     size_t value = HashFunction(rkey->prefix);
      43       38115 :     return value % DB::PartitionCount();
      44             : }
      45             : 
      46       26980 : BgpRoute *Inet6Table::TableFind(DBTablePartition *partition,
      47             :                                 const DBRequestKey *key) {
      48       26980 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      49       26980 :     Inet6Route route(rkey->prefix);
      50       54007 :     return static_cast<BgpRoute *>(partition->Find(&route));
      51       27009 : }
      52             : 
      53       51135 : DBTableBase *Inet6Table::CreateTable(DB *db, const std::string &name) {
      54       51135 :     Inet6Table *table = new Inet6Table(db, name);
      55       51137 :     table->Init();
      56       51136 :     return table;
      57             : }
      58             : 
      59      289534 : BgpRoute *Inet6Table::RouteReplicate(BgpServer *server, BgpTable *src_table,
      60             :         BgpRoute *src_rt, const BgpPath *path, ExtCommunityPtr community) {
      61      289534 :     assert((src_table->family()  == Address::INET6) ||
      62             :            (src_table->family()  == Address::INET6VPN));
      63             : 
      64      289530 :     Inet6Route *source = dynamic_cast<Inet6Route *>(src_rt);
      65             : 
      66      289530 :     RouteDistinguisher rd;
      67             : 
      68      289541 :     boost::scoped_ptr<Inet6Prefix> prefix;
      69      289537 :     if (source) {
      70       56741 :         prefix.reset(new Inet6Prefix(source->GetPrefix().ip6_addr(),
      71       28370 :                                      source->GetPrefix().prefixlen()));
      72             :     } else {
      73      261166 :         Inet6VpnRoute *vpn_route = dynamic_cast<Inet6VpnRoute *> (src_rt);
      74      261166 :         assert(vpn_route);
      75      261166 :         rd = vpn_route->GetPrefix().route_distinguisher();
      76      522297 :         prefix.reset(new Inet6Prefix(vpn_route->GetPrefix().addr(),
      77      261154 :                                      vpn_route->GetPrefix().prefixlen()));
      78             :     }
      79             : 
      80      289505 :     Inet6Route route(*prefix);
      81             :     DBTablePartition *partition =
      82      289528 :         static_cast<DBTablePartition *>(GetTablePartition(&route));
      83      289458 :     BgpRoute *dest_route = static_cast<BgpRoute *>(partition->Find(&route));
      84      289530 :     if (dest_route == NULL) {
      85      167897 :         dest_route = new Inet6Route(route.GetPrefix());
      86      167902 :         partition->Add(dest_route);
      87             :     } else {
      88      121633 :         dest_route->ClearDelete();
      89             :     }
      90             : 
      91             :     // Replace the extended community with the one provided.
      92      289520 :     BgpAttrDB *attr_db = server->attr_db();
      93             :     BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(path->GetAttr(),
      94      289511 :                                                                 community);
      95             : 
      96      289546 :     if (!source) {
      97      261176 :         new_attr = attr_db->ReplaceSourceRdAndLocate(new_attr.get(), rd);
      98             :     }
      99             : 
     100             :     // Check whether there's already a path with the given peer and path id.
     101             :     BgpPath *dest_path =
     102      289550 :         dest_route->FindSecondaryPath(src_rt, path->GetSource(),
     103             :                                       path->GetPeer(), path->GetPathId());
     104      289536 :     if (dest_path != NULL) {
     105      233251 :         if ((new_attr != dest_path->GetOriginalAttr()) ||
     106      233249 :             (path->GetFlags() != dest_path->GetFlags()) ||
     107      100625 :             (path->GetLabel() != dest_path->GetLabel())) {
     108             :             // Update Attributes and notify (if needed)
     109       19038 :             if (dest_path->NeedsResolution()) {
     110           0 :                 path_resolver()->StopPathResolution(partition->index(),
     111             :                                                     dest_path);
     112             :             }
     113       19038 :             assert(dest_route->RemoveSecondaryPath(src_rt, path->GetSource(),
     114             :                 path->GetPeer(), path->GetPathId()));
     115             :         } else {
     116      100604 :             return dest_route;
     117             :         }
     118             :     }
     119             : 
     120             :     BgpSecondaryPath *replicated_path =
     121      188931 :         new BgpSecondaryPath(path->GetPeer(), path->GetPathId(),
     122      188931 :             path->GetSource(), new_attr, path->GetFlags(), path->GetLabel());
     123      188933 :     replicated_path->SetReplicateInfo(src_table, src_rt);
     124             : 
     125             :     // For VPN to VRF replication, start path resolution if fast convergence is
     126             :     // enabled and update path flag to indicate need for resolution.
     127      188931 :     if (!source && (server->IsNextHopCheckEnabled()) &&
     128           0 :         (replicated_path->GetSource() == BgpPath::BGP_XMPP)) {
     129           0 :         Address::Family family = replicated_path->GetAttr()->nexthop_family();
     130           0 :         RoutingInstanceMgr *mgr = server->routing_instance_mgr();
     131           0 :         RoutingInstance *master_ri = mgr->GetDefaultRoutingInstance();
     132           0 :         BgpTable *table = master_ri->GetTable(family);
     133           0 :         replicated_path->SetResolveNextHop();
     134           0 :         path_resolver()->StartPathResolution(dest_route, replicated_path,
     135             :                                              table);
     136             :     }
     137             : 
     138      188930 :     dest_route->InsertPath(replicated_path);
     139             : 
     140             :     // Notify the route even if the best path may not have changed. For XMPP
     141             :     // peers, we support sending multiple ECMP next-hops for a single route.
     142             :     //
     143             :     // TODO(ananth): Can be optimized for changes that does not result in
     144             :     // any change to ECMP list
     145      188929 :     partition->Notify(dest_route);
     146             : 
     147      188932 :     return dest_route;
     148      289536 : }
     149             : 
     150      217806 : bool Inet6Table::Export(RibOut *ribout, Route *route, const RibPeerSet &peerset,
     151             :         UpdateInfoSList &uinfo_slist) {
     152      217806 :     BgpRoute *bgp_route = static_cast<BgpRoute *> (route);
     153      217806 :     UpdateInfo *uinfo = GetUpdateInfo(ribout, bgp_route, peerset);
     154      217843 :     if (!uinfo) {
     155        4502 :         return false;
     156             :     }
     157             : 
     158      213341 :     if (ribout->ExportPolicy().encoding == RibExportPolicy::BGP) {
     159        4543 :         BgpAttrDB *attr_db = routing_instance()->server()->attr_db();
     160             :         // Strip ExtCommunity.
     161        4543 :         if (uinfo->roattr.attr()->ext_community()) {
     162             :             BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(
     163        1672 :                 uinfo->roattr.attr(), NULL);
     164        1672 :             uinfo->roattr.set_attr(this, new_attr);
     165        1672 :         }
     166             : 
     167             :         // Strip OriginVnPath.
     168        4543 :         if (uinfo->roattr.attr()->origin_vn_path()) {
     169             :             BgpAttrPtr new_attr = attr_db->ReplaceOriginVnPathAndLocate(
     170           0 :                 uinfo->roattr.attr(), NULL);
     171           0 :             uinfo->roattr.set_attr(this, new_attr);
     172           0 :         }
     173             :     }
     174      213338 :     uinfo_slist->push_front(*uinfo);
     175             : 
     176      213334 :     return true;
     177             : }
     178             : 
     179       42909 : PathResolver *Inet6Table::CreatePathResolver() {
     180       42909 :     if (routing_instance()->IsMasterRoutingInstance())
     181           0 :         return NULL;
     182       42909 :     return (new PathResolver(this));
     183             : }
     184             : 
     185         159 : static void RegisterFactory() {
     186         159 :     DB::RegisterFactory("inet6.0", &Inet6Table::CreateTable);
     187         159 : }
     188             : MODULE_INITIALIZER(RegisterFactory);

Generated by: LCOV version 1.14