LCOV - code coverage report
Current view: top level - bgp/inet6vpn - inet6vpn_table.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 92 92 100.0 %
Date: 2026-11-09 02:10:49 Functions: 11 11 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/inet6vpn/inet6vpn_table.h"
       7             : 
       8             : #include "bgp/ipeer.h"
       9             : #include "bgp/bgp_server.h"
      10             : #include "bgp/bgp_peer.h"
      11             : #include "bgp/bgp_update.h"
      12             : #include "bgp/inet6/inet6_table.h"
      13             : #include "bgp/routing-instance/routing_instance.h"
      14             : #include "net/rd.h"
      15             : 
      16        8228 : Inet6VpnTable::Inet6VpnTable(DB *db, const std::string &name)
      17        8228 :     : BgpTable(db, name) {
      18        8228 : }
      19             : 
      20             : std::unique_ptr<DBEntry>
      21      100589 : Inet6VpnTable::AllocEntry(const DBRequestKey *key) const {
      22      100589 :     const RequestKey *pfxkey = static_cast<const RequestKey *>(key);
      23      100589 :     return std::unique_ptr<DBEntry>(new Inet6VpnRoute(pfxkey->prefix));
      24             : }
      25             : 
      26             : std::unique_ptr<DBEntry>
      27          20 : Inet6VpnTable::AllocEntryStr(const std::string &key_str) const {
      28          20 :     Inet6VpnPrefix vpn_prefix = Inet6VpnPrefix::FromString(key_str);
      29          40 :     return std::unique_ptr<DBEntry> (new Inet6VpnRoute(vpn_prefix));
      30             : }
      31             : 
      32     1293471 : size_t Inet6VpnTable::Hash(const DBEntry *entry) const {
      33     1293471 :     const Inet6VpnRoute *vpn_route = static_cast<const Inet6VpnRoute *>(entry);
      34     1293471 :     const Inet6VpnPrefix &vpn_prefix = vpn_route->GetPrefix();
      35     1293400 :     Inet6Prefix prefix(vpn_prefix.addr(), vpn_prefix.prefixlen());
      36     1293078 :     size_t value = Inet6Table::HashFunction(prefix);
      37     1292541 :     return value % DB::PartitionCount();
      38             : }
      39             : 
      40       64870 : size_t Inet6VpnTable::Hash(const DBRequestKey *key) const {
      41       64870 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      42       64870 :     Inet6Prefix prefix(rkey->prefix.addr(), rkey->prefix.prefixlen());
      43       64870 :     size_t value = Inet6Table::HashFunction(prefix);
      44       64870 :     return value % DB::PartitionCount();
      45             : }
      46             : 
      47       63141 : BgpRoute *Inet6VpnTable::TableFind(DBTablePartition *rtp,
      48             :                                    const DBRequestKey *prefix) {
      49       63141 :     const RequestKey *pfxkey = static_cast<const RequestKey *>(prefix);
      50       63141 :     Inet6VpnRoute vpn_route(pfxkey->prefix);
      51      126286 :     return static_cast<BgpRoute *>(rtp->Find(&vpn_route));
      52       63160 : }
      53             : 
      54        8228 : DBTableBase *Inet6VpnTable::CreateTable(DB *db, const std::string &name) {
      55        8228 :     Inet6VpnTable *table = new Inet6VpnTable(db, name);
      56        8228 :     table->Init();
      57        8228 :     return table;
      58             : }
      59             : 
      60       20393 : static RouteDistinguisher GenerateDistinguisher(
      61             :         const BgpTable *src_table, const BgpPath *src_path) {
      62       20393 :     const RouteDistinguisher &source_rd = src_path->GetAttr()->source_rd();
      63       20392 :     if (!src_path->GetPeer() || !(src_path->GetPeer()->IsRouterTypeBGPaaS())){
      64       19145 :         if (!source_rd.IsZero())
      65       11484 :         return source_rd;
      66             : 
      67        7659 :         assert(!src_path->GetPeer() || !src_path->GetPeer()->IsXmppPeer());
      68        7659 :         const RoutingInstance *src_instance = src_table->routing_instance();
      69        7659 :         return *src_instance->GetRD();
      70             :     }
      71        1247 :     uint16_t peer_port_id = 0;
      72        1247 :     as_t asn_num = src_path->GetAttr()->neighbor_as();
      73             : 
      74        1247 :     std::string ri_name = src_table->routing_instance()->name();
      75        2494 :     for (const BgpPeer *peer = src_path->GetPeer()->server()->FindNextPeer(); peer != NULL;
      76        1247 :          peer = src_path->GetPeer()->server()->FindNextPeer(peer->peer_name())) {
      77        3741 :             if ((peer->peer_name().find(ri_name)!= std::string::npos)&&
      78        3741 :             (peer->peer_address_string().find(src_path->GetPeer()->ToString())!= std::string::npos)){
      79        1247 :                 peer_port_id = peer->peer_port();
      80        1247 :                 asn_num = peer->peer_as();
      81        1247 :                 break;
      82             :             }
      83             :     }
      84        1247 :     RouteDistinguisher new_source_rd = RouteDistinguisher(true, asn_num, peer_port_id);
      85        1247 :     return new_source_rd;
      86        1247 : }
      87             : 
      88       20393 : BgpRoute *Inet6VpnTable::RouteReplicate(BgpServer *server, BgpTable *src_table,
      89             :         BgpRoute *source_rt, const BgpPath *src_path,
      90             :         ExtCommunityPtr community) {
      91       20393 :     assert(src_table->family()  == Address::INET6);
      92             : 
      93       20393 :     Inet6Route *src_rt = dynamic_cast<Inet6Route *>(source_rt);
      94       20393 :     assert(src_rt);
      95             : 
      96       20393 :     const RouteDistinguisher &rd = GenerateDistinguisher(src_table, src_path);
      97       20390 :     Inet6VpnPrefix vpn_prefix(rd, src_rt->GetPrefix().ip6_addr(),
      98       40780 :                               src_rt->GetPrefix().prefixlen());
      99             : 
     100       20390 :     Inet6VpnRoute vpn_route(vpn_prefix);
     101             :     DBTablePartition *partition =
     102       20393 :         static_cast<DBTablePartition *>(GetTablePartition(&vpn_route));
     103       20390 :     BgpRoute *dest_route = static_cast<BgpRoute *>(partition->Find(&vpn_route));
     104       20393 :     if (dest_route == NULL) {
     105       12218 :         dest_route = new Inet6VpnRoute(vpn_prefix);
     106       12218 :         partition->Add(dest_route);
     107             :     } else {
     108        8175 :         dest_route->ClearDelete();
     109             :     }
     110             : 
     111       20393 :     BgpAttrDB *attr_db = server->attr_db();
     112             : 
     113             :     BgpAttrPtr new_attr =
     114             :         server->attr_db()->ReplaceExtCommunityAndLocate(src_path->GetAttr(),
     115       20392 :                                                         community);
     116       20393 :     new_attr = attr_db->ReplaceSourceRdAndLocate(new_attr.get(), rd);
     117             : 
     118             :     // Check whether there's already a path with the given peer and path id.
     119             :     BgpPath *dest_path =
     120       20393 :         dest_route->FindSecondaryPath(source_rt, src_path->GetSource(),
     121             :                                       src_path->GetPeer(),
     122             :                                       src_path->GetPathId());
     123       20393 :     if (dest_path != NULL) {
     124       14218 :         if ((new_attr != dest_path->GetOriginalAttr()) ||
     125       14218 :             (src_path->GetFlags() != dest_path->GetFlags()) ||
     126        3849 :             (src_path->GetLabel() != dest_path->GetLabel())) {
     127             :             // Update Attributes and notify (if needed)
     128        4045 :             assert(dest_route->RemoveSecondaryPath(source_rt,
     129             :                                 src_path->GetSource(), src_path->GetPeer(),
     130             :                                 src_path->GetPathId()));
     131             :         } else {
     132        3790 :             return dest_route;
     133             :         }
     134             :     }
     135             : 
     136             :     // Create replicated path and insert it on the route
     137             :     BgpSecondaryPath *replicated_path =
     138       16603 :         new BgpSecondaryPath(src_path->GetPeer(), src_path->GetPathId(),
     139       16603 :                              src_path->GetSource(), new_attr,
     140       16603 :                              src_path->GetFlags(), src_path->GetLabel());
     141       16603 :     replicated_path->SetReplicateInfo(src_table, source_rt);
     142       16603 :     dest_route->InsertPath(replicated_path);
     143             : 
     144             :     // Always trigger notification.
     145       16603 :     partition->Notify(dest_route);
     146             : 
     147       16603 :     return dest_route;
     148       20393 : }
     149             : 
     150      119436 : bool Inet6VpnTable::Export(RibOut *ribout, Route *route,
     151             :         const RibPeerSet &peerset, UpdateInfoSList &uinfo_slist) {
     152      119436 :     BgpRoute *bgp_route = static_cast<BgpRoute *> (route);
     153      119436 :     UpdateInfo *uinfo = GetUpdateInfo(ribout, bgp_route, peerset);
     154      119494 :     if (!uinfo) {
     155       53467 :         return false;
     156             :     }
     157       66027 :     uinfo_slist->push_front(*uinfo);
     158             : 
     159       66030 :     return true;
     160             : }
     161             : 
     162         159 : static void RegisterFactory() {
     163         159 :     DB::RegisterFactory("bgp.l3vpn-inet6.0", &Inet6VpnTable::CreateTable);
     164         159 : }
     165             : MODULE_INITIALIZER(RegisterFactory);

Generated by: LCOV version 1.14