LCOV - code coverage report
Current view: top level - bgp/l3vpn - inetvpn_table.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 87 92 94.6 %
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) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include "bgp/l3vpn/inetvpn_table.h"
       7             : 
       8             : #include "bgp/ipeer.h"
       9             : #include "bgp/bgp_server.h"
      10             : #include "bgp/bgp_update.h"
      11             : #include "bgp/inet/inet_table.h"
      12             : #include "bgp/bgp_peer.h"
      13             : #include "bgp/routing-instance/routing_instance.h"
      14             : #include "net/rd.h"
      15             : 
      16             : using std::unique_ptr;
      17             : using std::string;
      18             : 
      19        8236 : InetVpnTable::InetVpnTable(DB *db, const string &name)
      20        8236 :         : BgpTable(db, name) {
      21        8236 : }
      22             : 
      23      105720 : unique_ptr<DBEntry> InetVpnTable::AllocEntry(const DBRequestKey *key) const {
      24      105720 :     const RequestKey *pfxkey = static_cast<const RequestKey *>(key);
      25      105720 :     return unique_ptr<DBEntry> (new InetVpnRoute(pfxkey->prefix));
      26             : }
      27             : 
      28             : 
      29          61 : unique_ptr<DBEntry> InetVpnTable::AllocEntryStr(const string &key_str) const {
      30          61 :     InetVpnPrefix prefix = InetVpnPrefix::FromString(key_str);
      31         122 :     return unique_ptr<DBEntry> (new InetVpnRoute(prefix));
      32             : }
      33             : 
      34     1602788 : size_t InetVpnTable::Hash(const DBEntry *entry) const {
      35     1602788 :     const InetVpnRoute *rt_entry = static_cast<const InetVpnRoute *>(entry);
      36     1602788 :     const InetVpnPrefix &inetvpnprefix = rt_entry->GetPrefix();
      37     1603037 :     Ip4Prefix prefix(inetvpnprefix.addr(), inetvpnprefix.prefixlen());
      38     1602608 :     size_t value = InetTable::HashFunction(prefix);
      39     1602314 :     return value % DB::PartitionCount();
      40             : }
      41             : 
      42      108820 : size_t InetVpnTable::Hash(const DBRequestKey *key) const {
      43      108820 :     const RequestKey *rkey = static_cast<const RequestKey *>(key);
      44      108820 :     Ip4Prefix prefix(rkey->prefix.addr(), rkey->prefix.prefixlen());
      45      108819 :     size_t value = InetTable::HashFunction(prefix);
      46      108818 :     return value % DB::PartitionCount();
      47             : }
      48             : 
      49       78607 : BgpRoute *InetVpnTable::TableFind(DBTablePartition *rtp,
      50             :                                   const DBRequestKey *prefix) {
      51       78607 :     const RequestKey *pfxkey = static_cast<const RequestKey *>(prefix);
      52       78607 :     InetVpnRoute rt_key(pfxkey->prefix);
      53      157187 :     return static_cast<BgpRoute *>(rtp->Find(&rt_key));
      54       78612 : }
      55             : 
      56        8234 : DBTableBase *InetVpnTable::CreateTable(DB *db, const string &name) {
      57        8234 :     InetVpnTable *table = new InetVpnTable(db, name);
      58        8234 :     table->Init();
      59        8234 :     return table;
      60             : }
      61             : 
      62       33702 : static RouteDistinguisher GenerateDistinguisher(
      63             :         const BgpTable *src_table, const BgpPath *src_path) {
      64       33702 :     const RouteDistinguisher &source_rd = src_path->GetAttr()->source_rd();
      65       33703 :     if (!src_path->GetPeer() || !(src_path->GetPeer()->IsRouterTypeBGPaaS())){
      66       32516 :         if (!source_rd.IsZero())
      67       22548 :         return source_rd;
      68             : 
      69        9968 :         assert(!src_path->GetPeer() || !src_path->GetPeer()->IsXmppPeer());
      70        9968 :         const RoutingInstance *src_instance = src_table->routing_instance();
      71        9967 :         return *src_instance->GetRD();
      72             :     }
      73        1187 :     boost::system::error_code ec;
      74        1187 :     Ip4Address addr = Ip4Address::from_string(src_path->GetPeer()->ToString(), ec);
      75        1187 :     if ((ec.value() != 0)) {
      76           0 :         if (!source_rd.IsZero())
      77           0 :         return source_rd;
      78             : 
      79           0 :         assert(!src_path->GetPeer() || !src_path->GetPeer()->IsXmppPeer());
      80           0 :         const RoutingInstance *src_instance = src_table->routing_instance();
      81           0 :         return *src_instance->GetRD();
      82             :     } else {
      83        1187 :         int vrf_id = 0;
      84        1187 :         RouteDistinguisher new_source_rd = RouteDistinguisher(addr.to_ulong(), vrf_id);
      85        1187 :         return new_source_rd;
      86             :     }
      87             : }
      88             : 
      89       33703 : BgpRoute *InetVpnTable::RouteReplicate(BgpServer *server,
      90             :         BgpTable *src_table, BgpRoute *src_rt, const BgpPath *src_path,
      91             :         ExtCommunityPtr community) {
      92       33703 :     assert(src_table->family() == Address::INET);
      93             : 
      94       33703 :     InetRoute *inet = dynamic_cast<InetRoute *> (src_rt);
      95       33703 :     assert(inet);
      96             : 
      97       33703 :     const RouteDistinguisher &rd = GenerateDistinguisher(src_table, src_path);
      98             : 
      99       33699 :     InetVpnPrefix vpn(rd, inet->GetPrefix().ip4_addr(),
     100       67399 :                       inet->GetPrefix().prefixlen());
     101             : 
     102       33699 :     InetVpnRoute rt_key(vpn);
     103             : 
     104             :     DBTablePartition *rtp =
     105       33699 :         static_cast<DBTablePartition *>(GetTablePartition(&rt_key));
     106       33697 :     BgpRoute *dest_route = static_cast<BgpRoute *>(rtp->Find(&rt_key));
     107       33705 :     if (dest_route == NULL) {
     108       23188 :         dest_route = new InetVpnRoute(vpn);
     109       23185 :         rtp->Add(dest_route);
     110             :     } else {
     111       10517 :         dest_route->ClearDelete();
     112             :     }
     113             : 
     114       33700 :     BgpAttrDB *attr_db = server->attr_db();
     115             : 
     116             :     BgpAttrPtr new_attr =
     117             :         server->attr_db()->ReplaceExtCommunityAndLocate(src_path->GetAttr(),
     118       33698 :                                                         community);
     119       33705 :     new_attr = attr_db->ReplaceSourceRdAndLocate(new_attr.get(), rd);
     120             :     // Check whether there's already a path with the given peer and path id.
     121             :     BgpPath *dest_path =
     122       33705 :         dest_route->FindSecondaryPath(src_rt, src_path->GetSource(),
     123             :                                       src_path->GetPeer(),
     124             :                                       src_path->GetPathId());
     125       33705 :     if (dest_path != NULL) {
     126       16754 :         if ((new_attr != dest_path->GetOriginalAttr()) ||
     127       16754 :             (src_path->GetFlags() != dest_path->GetFlags()) ||
     128        4084 :             (src_path->GetLabel() != dest_path->GetLabel())) {
     129             :             // Update Attributes and notify (if needed)
     130        6220 :             assert(dest_route->RemoveSecondaryPath(src_rt,
     131             :                                 src_path->GetSource(), src_path->GetPeer(),
     132             :                                 src_path->GetPathId()));
     133             :         } else {
     134        3950 :             return dest_route;
     135             :         }
     136             :     }
     137             : 
     138             :     // Create replicated path and insert it on the route
     139             :     BgpSecondaryPath *replicated_path =
     140       29755 :         new BgpSecondaryPath(src_path->GetPeer(), src_path->GetPathId(),
     141       29755 :                             src_path->GetSource(), new_attr,
     142       29755 :                             src_path->GetFlags(), src_path->GetLabel());
     143       29755 :     replicated_path->SetReplicateInfo(src_table, src_rt);
     144       29754 :     dest_route->InsertPath(replicated_path);
     145             : 
     146             :     // Always trigger notification.
     147       29755 :     rtp->Notify(dest_route);
     148             : 
     149             :     // Update corresponding route's extended communities in inet.0 table.
     150             :     InetTable *inet_table =
     151       29755 :         dynamic_cast<InetTable *>(routing_instance()->GetTable(Address::INET));
     152       29754 :     InetVpnRoute *inetvpn_route = dynamic_cast<InetVpnRoute *>(dest_route);
     153       29754 :     inet_table->UpdateRoute(inetvpn_route->GetPrefix(), src_path->GetPeer(),
     154             :                             new_attr);
     155       29754 :     return dest_route;
     156       33704 : }
     157             : 
     158      144858 : bool InetVpnTable::Export(RibOut *ribout, Route *route,
     159             :         const RibPeerSet &peerset, UpdateInfoSList &uinfo_slist) {
     160      144858 :     BgpRoute *bgp_route = static_cast<BgpRoute *> (route);
     161      144858 :     UpdateInfo *uinfo = GetUpdateInfo(ribout, bgp_route, peerset);
     162      144925 :     if (!uinfo) return false;
     163       78609 :     uinfo_slist->push_front(*uinfo);
     164             : 
     165       78612 :     return true;
     166             : }
     167             : 
     168         159 : static void RegisterFactory() {
     169         159 :     DB::RegisterFactory("bgp.l3vpn.0", &InetVpnTable::CreateTable);
     170         159 : }
     171             : MODULE_INITIALIZER(RegisterFactory);

Generated by: LCOV version 1.14