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-06-08 02:02:55 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             :  */
       4             : 
       5             : #include "bgp/inet6/inet6_table.h"
       6             : 
       7             : #include "bgp/bgp_server.h"
       8             : #include "bgp/bgp_update.h"
       9             : #include "bgp/inet6vpn/inet6vpn_route.h"
      10             : #include "bgp/routing-instance/path_resolver.h"
      11             : #include "bgp/routing-instance/routing_instance.h"
      12             : 
      13       51133 : Inet6Table::Inet6Table(DB *db, const std::string &name)
      14       51133 :     : BgpTable(db, name) {
      15       51133 : }
      16             : 
      17     5028084 : size_t Inet6Table::HashFunction(const Inet6Prefix &prefix) {
      18     5028084 :     const Ip6Address::bytes_type &addr_bytes = prefix.ToBytes();
      19    10049487 :     return boost::hash_range(addr_bytes.begin(), addr_bytes.end());
      20             : }
      21             : 
      22      196239 : std::unique_ptr<DBEntry> Inet6Table::AllocEntry(const DBRequestKey *key) const {
      23      196239 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      24      196239 :     return std::unique_ptr<DBEntry> (new Inet6Route(rkey->prefix));
      25             : }
      26             : 
      27          12 : std::unique_ptr<DBEntry> Inet6Table::AllocEntryStr(
      28             :         const std::string &key_str) const {
      29          12 :     Inet6Prefix prefix = Inet6Prefix::FromString(key_str);
      30          24 :     return std::unique_ptr<DBEntry> (new Inet6Route(prefix));
      31             : }
      32             : 
      33     3496761 : size_t Inet6Table::Hash(const DBEntry *entry) const {
      34     3496761 :     const Inet6Route *route = static_cast<const Inet6Route *>(entry);
      35     3496761 :     size_t value = HashFunction(route->GetPrefix());
      36     3493785 :     return value % DB::PartitionCount();
      37             : }
      38             : 
      39       38003 : size_t Inet6Table::Hash(const DBRequestKey *key) const {
      40       38003 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      41       38003 :     size_t value = HashFunction(rkey->prefix);
      42       38003 :     return value % DB::PartitionCount();
      43             : }
      44             : 
      45       26928 : BgpRoute *Inet6Table::TableFind(DBTablePartition *partition,
      46             :                                 const DBRequestKey *key) {
      47       26928 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      48       26928 :     Inet6Route route(rkey->prefix);
      49       53966 :     return static_cast<BgpRoute *>(partition->Find(&route));
      50       27000 : }
      51             : 
      52       51132 : DBTableBase *Inet6Table::CreateTable(DB *db, const std::string &name) {
      53       51132 :     Inet6Table *table = new Inet6Table(db, name);
      54       51133 :     table->Init();
      55       51132 :     return table;
      56             : }
      57             : 
      58      285238 : BgpRoute *Inet6Table::RouteReplicate(BgpServer *server, BgpTable *src_table,
      59             :         BgpRoute *src_rt, const BgpPath *path, ExtCommunityPtr community) {
      60      285238 :     assert((src_table->family()  == Address::INET6) ||
      61             :            (src_table->family()  == Address::INET6VPN));
      62             : 
      63      285238 :     Inet6Route *source = dynamic_cast<Inet6Route *>(src_rt);
      64             : 
      65      285238 :     RouteDistinguisher rd;
      66             : 
      67      285237 :     boost::scoped_ptr<Inet6Prefix> prefix;
      68      285236 :     if (source) {
      69       56697 :         prefix.reset(new Inet6Prefix(source->GetPrefix().ip6_addr(),
      70       28348 :                                      source->GetPrefix().prefixlen()));
      71             :     } else {
      72      256887 :         Inet6VpnRoute *vpn_route = dynamic_cast<Inet6VpnRoute *> (src_rt);
      73      256887 :         assert(vpn_route);
      74      256887 :         rd = vpn_route->GetPrefix().route_distinguisher();
      75      513744 :         prefix.reset(new Inet6Prefix(vpn_route->GetPrefix().addr(),
      76      256862 :                                      vpn_route->GetPrefix().prefixlen()));
      77             :     }
      78             : 
      79      285210 :     Inet6Route route(*prefix);
      80             :     DBTablePartition *partition =
      81      285237 :         static_cast<DBTablePartition *>(GetTablePartition(&route));
      82      285169 :     BgpRoute *dest_route = static_cast<BgpRoute *>(partition->Find(&route));
      83      285240 :     if (dest_route == NULL) {
      84      167927 :         dest_route = new Inet6Route(route.GetPrefix());
      85      167928 :         partition->Add(dest_route);
      86             :     } else {
      87      117313 :         dest_route->ClearDelete();
      88             :     }
      89             : 
      90             :     // Replace the extended community with the one provided.
      91      285235 :     BgpAttrDB *attr_db = server->attr_db();
      92             :     BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(path->GetAttr(),
      93      285230 :                                                                 community);
      94             : 
      95      285248 :     if (!source) {
      96      256901 :         new_attr = attr_db->ReplaceSourceRdAndLocate(new_attr.get(), rd);
      97             :     }
      98             : 
      99             :     // Check whether there's already a path with the given peer and path id.
     100             :     BgpPath *dest_path =
     101      285250 :         dest_route->FindSecondaryPath(src_rt, path->GetSource(),
     102             :                                       path->GetPeer(), path->GetPathId());
     103      285238 :     if (dest_path != NULL) {
     104      224629 :         if ((new_attr != dest_path->GetOriginalAttr()) ||
     105      224626 :             (path->GetFlags() != dest_path->GetFlags()) ||
     106       96325 :             (path->GetLabel() != dest_path->GetLabel())) {
     107             :             // Update Attributes and notify (if needed)
     108       19042 :             if (dest_path->NeedsResolution()) {
     109           0 :                 path_resolver()->StopPathResolution(partition->index(),
     110             :                                                     dest_path);
     111             :             }
     112       19042 :             assert(dest_route->RemoveSecondaryPath(src_rt, path->GetSource(),
     113             :                 path->GetPeer(), path->GetPathId()));
     114             :         } else {
     115       96304 :             return dest_route;
     116             :         }
     117             :     }
     118             : 
     119             :     BgpSecondaryPath *replicated_path =
     120      188932 :         new BgpSecondaryPath(path->GetPeer(), path->GetPathId(),
     121      188932 :             path->GetSource(), new_attr, path->GetFlags(), path->GetLabel());
     122      188934 :     replicated_path->SetReplicateInfo(src_table, src_rt);
     123             : 
     124             :     // For VPN to VRF replication, start path resolution if fast convergence is
     125             :     // enabled and update path flag to indicate need for resolution.
     126      188933 :     if (!source && (server->IsNextHopCheckEnabled()) &&
     127           0 :         (replicated_path->GetSource() == BgpPath::BGP_XMPP)) {
     128           0 :         Address::Family family = replicated_path->GetAttr()->nexthop_family();
     129           0 :         RoutingInstanceMgr *mgr = server->routing_instance_mgr();
     130           0 :         RoutingInstance *master_ri = mgr->GetDefaultRoutingInstance();
     131           0 :         BgpTable *table = master_ri->GetTable(family);
     132           0 :         replicated_path->SetResolveNextHop();
     133           0 :         path_resolver()->StartPathResolution(dest_route, replicated_path,
     134             :                                              table);
     135             :     }
     136             : 
     137      188928 :     dest_route->InsertPath(replicated_path);
     138             : 
     139             :     // Notify the route even if the best path may not have changed. For XMPP
     140             :     // peers, we support sending multiple ECMP next-hops for a single route.
     141             :     //
     142             :     // TODO(ananth): Can be optimized for changes that does not result in
     143             :     // any change to ECMP list
     144      188931 :     partition->Notify(dest_route);
     145             : 
     146      188931 :     return dest_route;
     147      285235 : }
     148             : 
     149      217755 : bool Inet6Table::Export(RibOut *ribout, Route *route, const RibPeerSet &peerset,
     150             :         UpdateInfoSList &uinfo_slist) {
     151      217755 :     BgpRoute *bgp_route = static_cast<BgpRoute *> (route);
     152      217755 :     UpdateInfo *uinfo = GetUpdateInfo(ribout, bgp_route, peerset);
     153      217799 :     if (!uinfo) {
     154        4526 :         return false;
     155             :     }
     156             : 
     157      213273 :     if (ribout->ExportPolicy().encoding == RibExportPolicy::BGP) {
     158        4557 :         BgpAttrDB *attr_db = routing_instance()->server()->attr_db();
     159             :         // Strip ExtCommunity.
     160        4557 :         if (uinfo->roattr.attr()->ext_community()) {
     161             :             BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(
     162        1686 :                 uinfo->roattr.attr(), NULL);
     163        1686 :             uinfo->roattr.set_attr(this, new_attr);
     164        1686 :         }
     165             : 
     166             :         // Strip OriginVnPath.
     167        4557 :         if (uinfo->roattr.attr()->origin_vn_path()) {
     168             :             BgpAttrPtr new_attr = attr_db->ReplaceOriginVnPathAndLocate(
     169           0 :                 uinfo->roattr.attr(), NULL);
     170           0 :             uinfo->roattr.set_attr(this, new_attr);
     171           0 :         }
     172             :     }
     173      213275 :     uinfo_slist->push_front(*uinfo);
     174             : 
     175      213276 :     return true;
     176             : }
     177             : 
     178       42903 : PathResolver *Inet6Table::CreatePathResolver() {
     179       42903 :     if (routing_instance()->IsMasterRoutingInstance())
     180           0 :         return NULL;
     181       42906 :     return (new PathResolver(this));
     182             : }
     183             : 
     184         159 : static void RegisterFactory() {
     185         159 :     DB::RegisterFactory("inet6.0", &Inet6Table::CreateTable);
     186         159 : }
     187             : MODULE_INITIALIZER(RegisterFactory);

Generated by: LCOV version 1.14