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-06-11 01:56:02 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             :  */
       4             : 
       5             : #include "base/misc_utils.h"
       6             : #include "base/string_util.h"
       7             : #include "bgp/inet6/inet6_route.h"
       8             : #include "bgp/inet6/inet6_table.h"
       9             : 
      10             : using boost::system::error_code;
      11             : using std::copy;
      12             : using std::string;
      13             : using std::vector;
      14             : 
      15        5878 : int Inet6Prefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
      16             :                                  Inet6Prefix *prefix) {
      17        5878 :     if (proto_prefix.prefix.size() > Address::kMaxV6Bytes)
      18           0 :         return -1;
      19        5878 :     prefix->prefixlen_ = proto_prefix.prefixlen;
      20        5878 :     Ip6Address::bytes_type bt = { { 0 } };
      21        5878 :     copy(proto_prefix.prefix.begin(), proto_prefix.prefix.end(), bt.begin());
      22        5878 :     prefix->ip6_addr_ = Ip6Address(bt);
      23             : 
      24        5878 :     return 0;
      25             : }
      26             : 
      27        5876 : int Inet6Prefix::FromProtoPrefix(BgpServer *server,
      28             :                                  const BgpProtoPrefix &proto_prefix,
      29             :                                  const BgpAttr *attr,
      30             :                                  const Address::Family family,
      31             :                                  Inet6Prefix *prefix, BgpAttrPtr *new_attr,
      32             :                                  uint32_t *label, uint32_t *l3_label) {
      33        5876 :     return FromProtoPrefix(proto_prefix, prefix);
      34             : }
      35             : 
      36      702123 : string Inet6Prefix::ToString() const {
      37      702123 :     string repr(ip6_addr().to_string());
      38      702218 :     repr.append("/" + integerToString(prefixlen()));
      39      702331 :     return repr;
      40           0 : }
      41             : 
      42     5365929 : int Inet6Prefix::CompareTo(const Inet6Prefix &rhs) const {
      43     5365929 :     if (ip6_addr_ < rhs.ip6_addr_) {
      44     2663358 :         return -1;
      45             :     }
      46     2702782 :     if (ip6_addr_ > rhs.ip6_addr_) {
      47     1880156 :         return 1;
      48             :     }
      49      824951 :     if (prefixlen_ < rhs.prefixlen_) {
      50         102 :         return -1;
      51             :     }
      52      824849 :     if (prefixlen_ > rhs.prefixlen_) {
      53          55 :         return 1;
      54             :     }
      55      824794 :     return 0;
      56             : }
      57             : 
      58       59636 : Inet6Prefix Inet6Prefix::FromString(const string &str, error_code *error) {
      59       59636 :     Inet6Prefix prefix;
      60       59636 :     error_code pfxerr = Inet6SubnetParse(str, &prefix.ip6_addr_,
      61             :                                        &prefix.prefixlen_);
      62       59636 :     if (error != NULL) {
      63       52471 :         *error = pfxerr;
      64             :     }
      65      119272 :     return prefix;
      66             : }
      67             : 
      68             : // Check whether 'this' is more specific than rhs.
      69       20634 : bool Inet6Prefix::IsMoreSpecific(const Inet6Prefix &rhs) const {
      70             :     // My prefixlen must be longer in order to be more specific.
      71       20634 :     if (prefixlen_ < rhs.prefixlen()) {
      72          87 :         return false;
      73             :     }
      74       20545 :     Inet6Prefix mask = Inet6Masks::PrefixlenToMask(rhs.prefixlen());
      75       20548 :     Inet6Prefix left = operator&(mask);
      76       20589 :     Inet6Prefix right = rhs.operator&(mask);
      77             : 
      78       20581 :     return (left.ToBytes() == right.ToBytes());
      79             : }
      80             : 
      81       41112 : Inet6Prefix Inet6Prefix::operator&(const Inet6Prefix& right) const {
      82             :     Ip6Address::bytes_type addr_bytes;
      83       41112 :     ARRAYBYTES_FILL(addr_bytes,0);
      84             : 
      85       41092 :     Ip6Address::bytes_type lhs = ToBytes();
      86       41089 :     Ip6Address::bytes_type rhs = right.ToBytes();
      87             : 
      88       41131 :     int plen = (prefixlen_ <= right.prefixlen_ ? prefixlen() : right.prefixlen());
      89             : 
      90      696045 :     for (size_t i = 0; i < sizeof(Ip6Address::bytes_type); ++i) {
      91      654987 :         addr_bytes[i] = lhs[i] & rhs[i];
      92             :     }
      93             : 
      94       41058 :     return Inet6Prefix(Ip6Address(addr_bytes), plen);
      95             : }
      96             : 
      97             : // Routines for class Inet6Route
      98             : 
      99      685608 : Inet6Route::Inet6Route(const Inet6Prefix &prefix)
     100      685538 :     : prefix_(prefix),
     101      685608 :       prefix_str_(prefix.ToString()) {
     102      685681 : }
     103             : 
     104     5323284 : int Inet6Route::CompareTo(const Route &rhs) const {
     105     5323284 :     const Inet6Route &rt_other = static_cast<const Inet6Route &>(rhs);
     106     5323284 :     return prefix_.CompareTo(rt_other.prefix_);
     107             : }
     108             : 
     109             : // Check whether 'this' is more specific than rhs.
     110           5 : bool Inet6Route::IsMoreSpecific(const string &match) const {
     111           5 :     error_code ec;
     112             : 
     113           5 :     Inet6Prefix prefix = Inet6Prefix::FromString(match, &ec);
     114           5 :     if (!ec) {
     115           5 :         return GetPrefix().IsMoreSpecific(prefix);
     116             :     }
     117             : 
     118           0 :     return false;
     119             : }
     120             : 
     121             : // Check whether 'this' is less specific than rhs.
     122           3 : bool Inet6Route::IsLessSpecific(const string &match) const {
     123           3 :     error_code ec;
     124             : 
     125           3 :     Inet6Prefix prefix = Inet6Prefix::FromString(match, &ec);
     126           3 :     if (!ec) {
     127           3 :         return prefix.IsMoreSpecific(GetPrefix());
     128             :     }
     129             : 
     130           0 :     return false;
     131             : }
     132             : 
     133      172176 : DBEntryBase::KeyPtr Inet6Route::GetDBRequestKey() const {
     134      172176 :     Inet6Table::RequestKey *key = new Inet6Table::RequestKey(prefix_, NULL);
     135      172144 :     return KeyPtr(key);
     136             : }
     137             : 
     138           1 : void Inet6Route::SetKey(const DBRequestKey *reqkey) {
     139           1 :     const Inet6Table::RequestKey *key =
     140             :         static_cast<const Inet6Table::RequestKey *>(reqkey);
     141           1 :     prefix_ = key->prefix;
     142           1 : }
     143             : 
     144        5202 : void Inet6Route::BuildProtoPrefix(BgpProtoPrefix *prefix,
     145             :                                   const BgpAttr *attr,
     146             :                                   uint32_t label,
     147             :                                   uint32_t l3_label) const {
     148        5202 :     prefix->prefixlen = prefix_.prefixlen();
     149        5202 :     prefix->prefix.clear();
     150        5202 :     const Ip6Address::bytes_type &addr_bytes = prefix_.ip6_addr().to_bytes();
     151        5202 :     int num_bytes = (prefix->prefixlen + 7) / 8;
     152        5202 :     copy(addr_bytes.begin(), addr_bytes.begin() + num_bytes,
     153        5202 :          back_inserter(prefix->prefix));
     154        5202 : }
     155             : 
     156             : //
     157             : // Fill in the vector based on the supplied nexthop.
     158             : //
     159        2638 : void Inet6Route::BuildBgpProtoNextHop(vector<uint8_t> &nh,
     160             :                                       IpAddress nexthop) const {
     161        2638 :     nh.resize(Address::kMaxV6Bytes);
     162        2638 :     Ip6Address address;
     163        2638 :     if (nexthop.is_v4()) {
     164         748 :         address = Ip6Address::v4_mapped(nexthop.to_v4());
     165             :     } else {
     166        1890 :         address = nexthop.to_v6();
     167             :     }
     168             : 
     169        2638 :     const Ip6Address::bytes_type &addr_bytes = address.to_bytes();
     170        2638 :     copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
     171        2638 : }
     172             : 
     173             : // Routines for class Inet6Masks
     174             : 
     175             : // Definitions of the static members
     176             : bool Inet6Masks::initialized_ = false;
     177             : vector<Inet6Prefix> Inet6Masks::masks_;
     178             : 
     179       20673 : const Inet6Prefix& Inet6Masks::PrefixlenToMask(uint8_t prefix_len) {
     180       20673 :     assert(prefix_len <= Inet6Prefix::kMaxV6PrefixLen);
     181       20673 :     return masks_.at(prefix_len);
     182             : }
     183             : 
     184         159 : void Inet6Masks::Init() {
     185         159 :     assert(initialized_ == false);
     186       20670 :     for (int i = 0; i <= Inet6Prefix::kMaxV6PrefixLen; ++i) {
     187       20511 :         masks_.push_back(CalculateMaskFromPrefixlen(i));
     188             :     }
     189         159 :     initialized_ = true;
     190         159 : }
     191             : 
     192           0 : void Inet6Masks::Clear() {
     193           0 :     masks_.clear();
     194           0 :     initialized_ = false;
     195           0 : }
     196             : 
     197       20511 : Inet6Prefix Inet6Masks::CalculateMaskFromPrefixlen(int prefixlen) {
     198       20511 :     int num_bytes = prefixlen / 8;
     199       20511 :     int num_bits = prefixlen % 8;
     200             : 
     201             :     Ip6Address::bytes_type addr_bytes;
     202       20511 :     ARRAYBYTES_FILL(addr_bytes,0);
     203             : 
     204      175695 :     for (int i = 0; i < num_bytes; ++i) {
     205      155184 :         addr_bytes[i] = 0xff;
     206             :     }
     207       20511 :     if (num_bits) {
     208       17808 :         uint8_t hex_val = 0xff << (8 - num_bits);
     209       17808 :         addr_bytes[num_bytes] = hex_val;
     210             :     }
     211       20511 :     return Inet6Prefix(Ip6Address(addr_bytes), prefixlen);
     212             : }
     213             : 
     214         159 : static void Inet6InitRoutines() {
     215         159 :     Inet6Masks::Init();
     216         159 : }
     217             : MODULE_INITIALIZER(Inet6InitRoutines);

Generated by: LCOV version 1.14