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-11 01:56:02 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       51135 : Inet6Table::Inet6Table(DB *db, const std::string &name)
      14       51135 :     : BgpTable(db, name) {
      15       51135 : }
      16             : 
      17     4981305 : size_t Inet6Table::HashFunction(const Inet6Prefix &prefix) {
      18     4981305 :     const Ip6Address::bytes_type &addr_bytes = prefix.ToBytes();
      19     9957639 :     return boost::hash_range(addr_bytes.begin(), addr_bytes.end());
      20             : }
      21             : 
      22      195788 : std::unique_ptr<DBEntry> Inet6Table::AllocEntry(const DBRequestKey *key) const {
      23      195788 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      24      195788 :     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     3487036 : size_t Inet6Table::Hash(const DBEntry *entry) const {
      34     3487036 :     const Inet6Route *route = static_cast<const Inet6Route *>(entry);
      35     3487036 :     size_t value = HashFunction(route->GetPrefix());
      36     3484023 :     return value % DB::PartitionCount();
      37             : }
      38             : 
      39       38012 : size_t Inet6Table::Hash(const DBRequestKey *key) const {
      40       38012 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      41       38012 :     size_t value = HashFunction(rkey->prefix);
      42       38012 :     return value % DB::PartitionCount();
      43             : }
      44             : 
      45       26982 : BgpRoute *Inet6Table::TableFind(DBTablePartition *partition,
      46             :                                 const DBRequestKey *key) {
      47       26982 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      48       26982 :     Inet6Route route(rkey->prefix);
      49       53984 :     return static_cast<BgpRoute *>(partition->Find(&route));
      50       26996 : }
      51             : 
      52       51131 : DBTableBase *Inet6Table::CreateTable(DB *db, const std::string &name) {
      53       51131 :     Inet6Table *table = new Inet6Table(db, name);
      54       51135 :     table->Init();
      55       51133 :     return table;
      56             : }
      57             : 
      58      280630 : BgpRoute *Inet6Table::RouteReplicate(BgpServer *server, BgpTable *src_table,
      59             :         BgpRoute *src_rt, const BgpPath *path, ExtCommunityPtr community) {
      60      280630 :     assert((src_table->family()  == Address::INET6) ||
      61             :            (src_table->family()  == Address::INET6VPN));
      62             : 
      63      280626 :     Inet6Route *source = dynamic_cast<Inet6Route *>(src_rt);
      64             : 
      65      280626 :     RouteDistinguisher rd;
      66             : 
      67      280626 :     boost::scoped_ptr<Inet6Prefix> prefix;
      68      280627 :     if (source) {
      69       56634 :         prefix.reset(new Inet6Prefix(source->GetPrefix().ip6_addr(),
      70       28315 :                                      source->GetPrefix().prefixlen()));
      71             :     } else {
      72      252308 :         Inet6VpnRoute *vpn_route = dynamic_cast<Inet6VpnRoute *> (src_rt);
      73      252308 :         assert(vpn_route);
      74      252308 :         rd = vpn_route->GetPrefix().route_distinguisher();
      75      504589 :         prefix.reset(new Inet6Prefix(vpn_route->GetPrefix().addr(),
      76      252297 :                                      vpn_route->GetPrefix().prefixlen()));
      77             :     }
      78             : 
      79      280585 :     Inet6Route route(*prefix);
      80             :     DBTablePartition *partition =
      81      280633 :         static_cast<DBTablePartition *>(GetTablePartition(&route));
      82      280581 :     BgpRoute *dest_route = static_cast<BgpRoute *>(partition->Find(&route));
      83      280622 :     if (dest_route == NULL) {
      84      167459 :         dest_route = new Inet6Route(route.GetPrefix());
      85      167456 :         partition->Add(dest_route);
      86             :     } else {
      87      113163 :         dest_route->ClearDelete();
      88             :     }
      89             : 
      90             :     // Replace the extended community with the one provided.
      91      280622 :     BgpAttrDB *attr_db = server->attr_db();
      92             :     BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(path->GetAttr(),
      93      280600 :                                                                 community);
      94             : 
      95      280650 :     if (!source) {
      96      252333 :         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      280644 :         dest_route->FindSecondaryPath(src_rt, path->GetSource(),
     102             :                                       path->GetPeer(), path->GetPathId());
     103      280618 :     if (dest_path != NULL) {
     104      216216 :         if ((new_attr != dest_path->GetOriginalAttr()) ||
     105      216215 :             (path->GetFlags() != dest_path->GetFlags()) ||
     106       92070 :             (path->GetLabel() != dest_path->GetLabel())) {
     107             :             // Update Attributes and notify (if needed)
     108       19124 :             if (dest_path->NeedsResolution()) {
     109           0 :                 path_resolver()->StopPathResolution(partition->index(),
     110             :                                                     dest_path);
     111             :             }
     112       19124 :             assert(dest_route->RemoveSecondaryPath(src_rt, path->GetSource(),
     113             :                 path->GetPeer(), path->GetPathId()));
     114             :         } else {
     115       92049 :             return dest_route;
     116             :         }
     117             :     }
     118             : 
     119             :     BgpSecondaryPath *replicated_path =
     120      188568 :         new BgpSecondaryPath(path->GetPeer(), path->GetPathId(),
     121      188568 :             path->GetSource(), new_attr, path->GetFlags(), path->GetLabel());
     122      188578 :     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      188570 :     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      188568 :     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      188558 :     partition->Notify(dest_route);
     145             : 
     146      188576 :     return dest_route;
     147      280625 : }
     148             : 
     149      217626 : bool Inet6Table::Export(RibOut *ribout, Route *route, const RibPeerSet &peerset,
     150             :         UpdateInfoSList &uinfo_slist) {
     151      217626 :     BgpRoute *bgp_route = static_cast<BgpRoute *> (route);
     152      217626 :     UpdateInfo *uinfo = GetUpdateInfo(ribout, bgp_route, peerset);
     153      217667 :     if (!uinfo) {
     154        4534 :         return false;
     155             :     }
     156             : 
     157      213133 :     if (ribout->ExportPolicy().encoding == RibExportPolicy::BGP) {
     158        4538 :         BgpAttrDB *attr_db = routing_instance()->server()->attr_db();
     159             :         // Strip ExtCommunity.
     160        4538 :         if (uinfo->roattr.attr()->ext_community()) {
     161             :             BgpAttrPtr new_attr = attr_db->ReplaceExtCommunityAndLocate(
     162        1673 :                 uinfo->roattr.attr(), NULL);
     163        1673 :             uinfo->roattr.set_attr(this, new_attr);
     164        1673 :         }
     165             : 
     166             :         // Strip OriginVnPath.
     167        4538 :         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      213136 :     uinfo_slist->push_front(*uinfo);
     174             : 
     175      213131 :     return true;
     176             : }
     177             : 
     178       42906 : PathResolver *Inet6Table::CreatePathResolver() {
     179       42906 :     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