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-18 01:51:13 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       51134 : }
      16             : 
      17     5014945 : size_t Inet6Table::HashFunction(const Inet6Prefix &prefix) {
      18     5014945 :     const Ip6Address::bytes_type &addr_bytes = prefix.ToBytes();
      19    10023246 :     return boost::hash_range(addr_bytes.begin(), addr_bytes.end());
      20             : }
      21             : 
      22      196848 : std::unique_ptr<DBEntry> Inet6Table::AllocEntry(const DBRequestKey *key) const {
      23      196848 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      24      196848 :     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     3495072 : size_t Inet6Table::Hash(const DBEntry *entry) const {
      34     3495072 :     const Inet6Route *route = static_cast<const Inet6Route *>(entry);
      35     3495072 :     size_t value = HashFunction(route->GetPrefix());
      36     3492098 :     return value % DB::PartitionCount();
      37             : }
      38             : 
      39       37993 : size_t Inet6Table::Hash(const DBRequestKey *key) const {
      40       37993 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      41       37993 :     size_t value = HashFunction(rkey->prefix);
      42       37993 :     return value % DB::PartitionCount();
      43             : }
      44             : 
      45       26996 : BgpRoute *Inet6Table::TableFind(DBTablePartition *partition,
      46             :                                 const DBRequestKey *key) {
      47       26996 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      48       26996 :     Inet6Route route(rkey->prefix);
      49       54013 :     return static_cast<BgpRoute *>(partition->Find(&route));
      50       27008 : }
      51             : 
      52       51133 : DBTableBase *Inet6Table::CreateTable(DB *db, const std::string &name) {
      53       51133 :     Inet6Table *table = new Inet6Table(db, name);
      54       51134 :     table->Init();
      55       51132 :     return table;
      56             : }
      57             : 
      58      286376 : BgpRoute *Inet6Table::RouteReplicate(BgpServer *server, BgpTable *src_table,
      59             :         BgpRoute *src_rt, const BgpPath *path, ExtCommunityPtr community) {
      60      286376 :     assert((src_table->family()  == Address::INET6) ||
      61             :            (src_table->family()  == Address::INET6VPN));
      62             : 
      63      286368 :     Inet6Route *source = dynamic_cast<Inet6Route *>(src_rt);
      64             : 
      65      286368 :     RouteDistinguisher rd;
      66             : 
      67      286374 :     boost::scoped_ptr<Inet6Prefix> prefix;
      68      286374 :     if (source) {
      69       56601 :         prefix.reset(new Inet6Prefix(source->GetPrefix().ip6_addr(),
      70       28299 :                                      source->GetPrefix().prefixlen()));
      71             :     } else {
      72      258072 :         Inet6VpnRoute *vpn_route = dynamic_cast<Inet6VpnRoute *> (src_rt);
      73      258072 :         assert(vpn_route);
      74      258072 :         rd = vpn_route->GetPrefix().route_distinguisher();
      75      516128 :         prefix.reset(new Inet6Prefix(vpn_route->GetPrefix().addr(),
      76      258065 :                                      vpn_route->GetPrefix().prefixlen()));
      77             :     }
      78             : 
      79      286353 :     Inet6Route route(*prefix);
      80             :     DBTablePartition *partition =
      81      286367 :         static_cast<DBTablePartition *>(GetTablePartition(&route));
      82      286325 :     BgpRoute *dest_route = static_cast<BgpRoute *>(partition->Find(&route));
      83      286364 :     if (dest_route == NULL) {
      84      167753 :         dest_route = new Inet6Route(route.GetPrefix());
      85      167757 :         partition->Add(dest_route);
      86             :     } else {
      87      118611 :         dest_route->ClearDelete();
      88             :     }
      89             : 
      90             :     // Replace the extended community with the one provided.
      91      286349 :     BgpAttrDB *attr_db = server->attr_db();
      92             :     BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(path->GetAttr(),
      93      286348 :                                                                 community);
      94             : 
      95      286377 :     if (!source) {
      96      258078 :         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      286376 :         dest_route->FindSecondaryPath(src_rt, path->GetSource(),
     102             :                                       path->GetPeer(), path->GetPathId());
     103      286368 :     if (dest_path != NULL) {
     104      227254 :         if ((new_attr != dest_path->GetOriginalAttr()) ||
     105      227252 :             (path->GetFlags() != dest_path->GetFlags()) ||
     106       97654 :             (path->GetLabel() != dest_path->GetLabel())) {
     107             :             // Update Attributes and notify (if needed)
     108       18994 :             if (dest_path->NeedsResolution()) {
     109           0 :                 path_resolver()->StopPathResolution(partition->index(),
     110             :                                                     dest_path);
     111             :             }
     112       18994 :             assert(dest_route->RemoveSecondaryPath(src_rt, path->GetSource(),
     113             :                 path->GetPeer(), path->GetPathId()));
     114             :         } else {
     115       97633 :             return dest_route;
     116             :         }
     117             :     }
     118             : 
     119             :     BgpSecondaryPath *replicated_path =
     120      188732 :         new BgpSecondaryPath(path->GetPeer(), path->GetPathId(),
     121      188732 :             path->GetSource(), new_attr, path->GetFlags(), path->GetLabel());
     122      188736 :     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      188734 :     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      188731 :     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      188731 :     partition->Notify(dest_route);
     145             : 
     146      188732 :     return dest_route;
     147      286365 : }
     148             : 
     149      217753 : bool Inet6Table::Export(RibOut *ribout, Route *route, const RibPeerSet &peerset,
     150             :         UpdateInfoSList &uinfo_slist) {
     151      217753 :     BgpRoute *bgp_route = static_cast<BgpRoute *> (route);
     152      217753 :     UpdateInfo *uinfo = GetUpdateInfo(ribout, bgp_route, peerset);
     153      217790 :     if (!uinfo) {
     154        4532 :         return false;
     155             :     }
     156             : 
     157      213258 :     if (ribout->ExportPolicy().encoding == RibExportPolicy::BGP) {
     158        4510 :         BgpAttrDB *attr_db = routing_instance()->server()->attr_db();
     159             :         // Strip ExtCommunity.
     160        4510 :         if (uinfo->roattr.attr()->ext_community()) {
     161             :             BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(
     162        1656 :                 uinfo->roattr.attr(), NULL);
     163        1656 :             uinfo->roattr.set_attr(this, new_attr);
     164        1656 :         }
     165             : 
     166             :         // Strip OriginVnPath.
     167        4510 :         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      213272 :     uinfo_slist->push_front(*uinfo);
     174             : 
     175      213271 :     return true;
     176             : }
     177             : 
     178       42907 : PathResolver *Inet6Table::CreatePathResolver() {
     179       42907 :     if (routing_instance()->IsMasterRoutingInstance())
     180           0 :         return NULL;
     181       42907 :     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