LCOV - code coverage report
Current view: top level - bgp/inet6 - inet6_route.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 107 115 93.0 %
Date: 2026-11-09 02:10:49 Functions: 19 20 95.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 "base/misc_utils.h"
       7             : #include "base/string_util.h"
       8             : #include "bgp/inet6/inet6_route.h"
       9             : #include "bgp/inet6/inet6_table.h"
      10             : 
      11             : using boost::system::error_code;
      12             : using std::copy;
      13             : using std::string;
      14             : using std::vector;
      15             : 
      16        5892 : int Inet6Prefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
      17             :                                  Inet6Prefix *prefix) {
      18        5892 :     if (proto_prefix.prefix.size() > Address::kMaxV6Bytes)
      19           0 :         return -1;
      20        5892 :     prefix->prefixlen_ = proto_prefix.prefixlen;
      21        5892 :     Ip6Address::bytes_type bt = { { 0 } };
      22        5892 :     copy(proto_prefix.prefix.begin(), proto_prefix.prefix.end(), bt.begin());
      23        5892 :     prefix->ip6_addr_ = Ip6Address(bt);
      24             : 
      25        5892 :     return 0;
      26             : }
      27             : 
      28        5890 : int Inet6Prefix::FromProtoPrefix(BgpServer *server,
      29             :                                  const BgpProtoPrefix &proto_prefix,
      30             :                                  const BgpAttr *attr,
      31             :                                  const Address::Family family,
      32             :                                  Inet6Prefix *prefix, BgpAttrPtr *new_attr,
      33             :                                  uint32_t *label, uint32_t *l3_label) {
      34        5890 :     return FromProtoPrefix(proto_prefix, prefix);
      35             : }
      36             : 
      37      711852 : string Inet6Prefix::ToString() const {
      38      711852 :     string repr(ip6_addr().to_string());
      39      711994 :     repr.append("/" + integerToString(prefixlen()));
      40      712123 :     return repr;
      41           0 : }
      42             : 
      43     5415438 : int Inet6Prefix::CompareTo(const Inet6Prefix &rhs) const {
      44     5415438 :     if (ip6_addr_ < rhs.ip6_addr_) {
      45     2691100 :         return -1;
      46             :     }
      47     2724007 :     if (ip6_addr_ > rhs.ip6_addr_) {
      48     1883958 :         return 1;
      49             :     }
      50      843069 :     if (prefixlen_ < rhs.prefixlen_) {
      51         102 :         return -1;
      52             :     }
      53      842967 :     if (prefixlen_ > rhs.prefixlen_) {
      54          55 :         return 1;
      55             :     }
      56      842912 :     return 0;
      57             : }
      58             : 
      59       59726 : Inet6Prefix Inet6Prefix::FromString(const string &str, error_code *error) {
      60       59726 :     Inet6Prefix prefix;
      61       59726 :     error_code pfxerr = Inet6SubnetParse(str, &prefix.ip6_addr_,
      62             :                                        &prefix.prefixlen_);
      63       59726 :     if (error != NULL) {
      64       52553 :         *error = pfxerr;
      65             :     }
      66      119452 :     return prefix;
      67             : }
      68             : 
      69             : // Check whether 'this' is more specific than rhs.
      70       20646 : bool Inet6Prefix::IsMoreSpecific(const Inet6Prefix &rhs) const {
      71             :     // My prefixlen must be longer in order to be more specific.
      72       20646 :     if (prefixlen_ < rhs.prefixlen()) {
      73          87 :         return false;
      74             :     }
      75       20554 :     Inet6Prefix mask = Inet6Masks::PrefixlenToMask(rhs.prefixlen());
      76       20551 :     Inet6Prefix left = operator&(mask);
      77       20601 :     Inet6Prefix right = rhs.operator&(mask);
      78             : 
      79       20581 :     return (left.ToBytes() == right.ToBytes());
      80             : }
      81             : 
      82       41129 : Inet6Prefix Inet6Prefix::operator&(const Inet6Prefix& right) const {
      83             :     Ip6Address::bytes_type addr_bytes;
      84       41129 :     ARRAYBYTES_FILL(addr_bytes,0);
      85             : 
      86       41114 :     Ip6Address::bytes_type lhs = ToBytes();
      87       41105 :     Ip6Address::bytes_type rhs = right.ToBytes();
      88             : 
      89       41129 :     int plen = (prefixlen_ <= right.prefixlen_ ? prefixlen() : right.prefixlen());
      90             : 
      91      696043 :     for (size_t i = 0; i < sizeof(Ip6Address::bytes_type); ++i) {
      92      654949 :         addr_bytes[i] = lhs[i] & rhs[i];
      93             :     }
      94             : 
      95       41094 :     return Inet6Prefix(Ip6Address(addr_bytes), plen);
      96             : }
      97             : 
      98             : // Routines for class Inet6Route
      99             : 
     100      695340 : Inet6Route::Inet6Route(const Inet6Prefix &prefix)
     101      695264 :     : prefix_(prefix),
     102      695340 :       prefix_str_(prefix.ToString()) {
     103      695458 : }
     104             : 
     105     5372696 : int Inet6Route::CompareTo(const Route &rhs) const {
     106     5372696 :     const Inet6Route &rt_other = static_cast<const Inet6Route &>(rhs);
     107     5372696 :     return prefix_.CompareTo(rt_other.prefix_);
     108             : }
     109             : 
     110             : // Check whether 'this' is more specific than rhs.
     111           5 : bool Inet6Route::IsMoreSpecific(const string &match) const {
     112           5 :     error_code ec;
     113             : 
     114           5 :     Inet6Prefix prefix = Inet6Prefix::FromString(match, &ec);
     115           5 :     if (!ec) {
     116           5 :         return GetPrefix().IsMoreSpecific(prefix);
     117             :     }
     118             : 
     119           0 :     return false;
     120             : }
     121             : 
     122             : // Check whether 'this' is less specific than rhs.
     123           3 : bool Inet6Route::IsLessSpecific(const string &match) const {
     124           3 :     error_code ec;
     125             : 
     126           3 :     Inet6Prefix prefix = Inet6Prefix::FromString(match, &ec);
     127           3 :     if (!ec) {
     128           3 :         return prefix.IsMoreSpecific(GetPrefix());
     129             :     }
     130             : 
     131           0 :     return false;
     132             : }
     133             : 
     134      172427 : DBEntryBase::KeyPtr Inet6Route::GetDBRequestKey() const {
     135      172427 :     Inet6Table::RequestKey *key = new Inet6Table::RequestKey(prefix_, NULL);
     136      172381 :     return KeyPtr(key);
     137             : }
     138             : 
     139           1 : void Inet6Route::SetKey(const DBRequestKey *reqkey) {
     140           1 :     const Inet6Table::RequestKey *key =
     141             :         static_cast<const Inet6Table::RequestKey *>(reqkey);
     142           1 :     prefix_ = key->prefix;
     143           1 : }
     144             : 
     145        5211 : void Inet6Route::BuildProtoPrefix(BgpProtoPrefix *prefix,
     146             :                                   const BgpAttr *attr,
     147             :                                   uint32_t label,
     148             :                                   uint32_t l3_label) const {
     149        5211 :     prefix->prefixlen = prefix_.prefixlen();
     150        5211 :     prefix->prefix.clear();
     151        5212 :     const Ip6Address::bytes_type &addr_bytes = prefix_.ip6_addr().to_bytes();
     152        5212 :     int num_bytes = (prefix->prefixlen + 7) / 8;
     153        5212 :     copy(addr_bytes.begin(), addr_bytes.begin() + num_bytes,
     154        5212 :          back_inserter(prefix->prefix));
     155        5210 : }
     156             : 
     157             : //
     158             : // Fill in the vector based on the supplied nexthop.
     159             : //
     160        2470 : void Inet6Route::BuildBgpProtoNextHop(vector<uint8_t> &nh,
     161             :                                       IpAddress nexthop) const {
     162        2470 :     nh.resize(Address::kMaxV6Bytes);
     163        2469 :     Ip6Address address;
     164        2469 :     if (nexthop.is_v4()) {
     165         743 :         address = Ip6Address::v4_mapped(nexthop.to_v4());
     166             :     } else {
     167        1726 :         address = nexthop.to_v6();
     168             :     }
     169             : 
     170        2469 :     const Ip6Address::bytes_type &addr_bytes = address.to_bytes();
     171        2469 :     copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
     172        2469 : }
     173             : 
     174             : // Routines for class Inet6Masks
     175             : 
     176             : // Definitions of the static members
     177             : bool Inet6Masks::initialized_ = false;
     178             : vector<Inet6Prefix> Inet6Masks::masks_;
     179             : 
     180       20681 : const Inet6Prefix& Inet6Masks::PrefixlenToMask(uint8_t prefix_len) {
     181       20681 :     assert(prefix_len <= Inet6Prefix::kMaxV6PrefixLen);
     182       20681 :     return masks_.at(prefix_len);
     183             : }
     184             : 
     185         159 : void Inet6Masks::Init() {
     186         159 :     assert(initialized_ == false);
     187       20670 :     for (int i = 0; i <= Inet6Prefix::kMaxV6PrefixLen; ++i) {
     188       20511 :         masks_.push_back(CalculateMaskFromPrefixlen(i));
     189             :     }
     190         159 :     initialized_ = true;
     191         159 : }
     192             : 
     193           0 : void Inet6Masks::Clear() {
     194           0 :     masks_.clear();
     195           0 :     initialized_ = false;
     196           0 : }
     197             : 
     198       20511 : Inet6Prefix Inet6Masks::CalculateMaskFromPrefixlen(int prefixlen) {
     199       20511 :     int num_bytes = prefixlen / 8;
     200       20511 :     int num_bits = prefixlen % 8;
     201             : 
     202             :     Ip6Address::bytes_type addr_bytes;
     203       20511 :     ARRAYBYTES_FILL(addr_bytes,0);
     204             : 
     205      175695 :     for (int i = 0; i < num_bytes; ++i) {
     206      155184 :         addr_bytes[i] = 0xff;
     207             :     }
     208       20511 :     if (num_bits) {
     209       17808 :         uint8_t hex_val = 0xff << (8 - num_bits);
     210       17808 :         addr_bytes[num_bytes] = hex_val;
     211             :     }
     212       20511 :     return Inet6Prefix(Ip6Address(addr_bytes), prefixlen);
     213             : }
     214             : 
     215         159 : static void Inet6InitRoutines() {
     216         159 :     Inet6Masks::Init();
     217         159 : }
     218             : MODULE_INITIALIZER(Inet6InitRoutines);

Generated by: LCOV version 1.14