LCOV - code coverage report
Current view: top level - bgp/inet6vpn - inet6vpn_route.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 130 136 95.6 %
Date: 2026-06-18 01:51:13 Functions: 18 18 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/inet6vpn/inet6vpn_route.h"
       6             : 
       7             : #include <algorithm>
       8             : 
       9             : #include "bgp/inet6vpn/inet6vpn_table.h"
      10             : #include "bgp/inet6/inet6_route.h"
      11             : 
      12             : using std::copy;
      13             : using std::string;
      14             : using std::vector;
      15             : 
      16       64942 : Inet6VpnPrefix::Inet6VpnPrefix() : prefixlen_(0) {
      17       64942 : }
      18             : 
      19       49755 : int Inet6VpnPrefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
      20             :                                     Inet6VpnPrefix *prefix, uint32_t *label) {
      21       49755 :     size_t nlri_size = proto_prefix.prefix.size();
      22       49755 :     size_t expected_min_nlri_size =
      23       49755 :         BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize;
      24             : 
      25       49755 :     if (nlri_size < expected_min_nlri_size)
      26           1 :         return -1;
      27       49754 :     if (nlri_size > expected_min_nlri_size + Address::kMaxV6Bytes)
      28           1 :         return -1;
      29             : 
      30       49753 :     size_t label_offset = 0;
      31       49753 :     *label = proto_prefix.ReadLabel(label_offset);
      32       49753 :     size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
      33       49753 :     prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
      34             : 
      35       49752 :     size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
      36       49752 :     prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8;
      37       49752 :     Ip6Address::bytes_type bt = { { 0 } };
      38       49752 :     copy(proto_prefix.prefix.begin() + prefix_offset,
      39             :         proto_prefix.prefix.end(), bt.begin());
      40       49752 :     prefix->addr_ = Ip6Address(bt);
      41             : 
      42       49752 :     return 0;
      43             : }
      44             : 
      45       49750 : int Inet6VpnPrefix::FromProtoPrefix(BgpServer *server,
      46             :                                     const BgpProtoPrefix &proto_prefix,
      47             :                                     const BgpAttr *attr,
      48             :                                     const Address::Family family,
      49             :                                     Inet6VpnPrefix *prefix,
      50             :                                     BgpAttrPtr *new_attr, uint32_t *label,
      51             :                                     uint32_t *l3_label) {
      52       49750 :     return FromProtoPrefix(proto_prefix, prefix, label);
      53             : }
      54             : 
      55       56585 : void Inet6VpnPrefix::BuildProtoPrefix(uint32_t label,
      56             :                                       BgpProtoPrefix *proto_prefix) const {
      57       56585 :     proto_prefix->prefix.clear();
      58       56585 :     size_t prefix_size = (prefixlen_ + 7) / 8;
      59       56585 :     size_t nlri_size =
      60       56585 :         BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize + prefix_size;
      61             : 
      62       56585 :     proto_prefix->prefix.resize(nlri_size, 0);
      63       56585 :     size_t label_offset = 0;
      64       56585 :     proto_prefix->WriteLabel(label_offset, label);
      65       56585 :     size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
      66       56585 :     copy(rd_.GetData(), rd_.GetData() + RouteDistinguisher::kSize,
      67       56585 :         proto_prefix->prefix.begin() + rd_offset);
      68             : 
      69       56585 :     size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
      70       56585 :     proto_prefix->prefixlen = prefix_offset * 8 + prefixlen_;
      71       56585 :     const Ip6Address::bytes_type &addr_bytes = addr_.to_bytes();
      72       56585 :     copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
      73       56585 :         proto_prefix->prefix.begin() + prefix_offset);
      74       56585 : }
      75             : 
      76             : // RD:inet6-prefix
      77       15186 : Inet6VpnPrefix Inet6VpnPrefix::FromString(const string &str,
      78             :                                           boost::system::error_code *errorp) {
      79       15186 :     Inet6VpnPrefix prefix;
      80             : 
      81       15186 :     size_t pos = str.find(':');
      82       15186 :     if (pos == string::npos) {
      83           1 :         if (errorp != NULL) {
      84           1 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      85             :         }
      86           1 :         return prefix;
      87             :     }
      88       15185 :     pos = str.find(':', (pos + 1));
      89       15185 :     if (pos == string::npos) {
      90           1 :         if (errorp != NULL) {
      91           1 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      92             :         }
      93           1 :         return prefix;
      94             :     }
      95       15184 :     string rdstr = str.substr(0, pos);
      96       15184 :     boost::system::error_code rderr;
      97       15184 :     prefix.rd_ = RouteDistinguisher::FromString(rdstr, &rderr);
      98       15184 :     if (rderr.failed()) {
      99           7 :         if (errorp != NULL) {
     100           5 :             *errorp = rderr;
     101             :         }
     102           7 :         return prefix;
     103             :     }
     104             : 
     105       15177 :     string ip6pstr(str, pos + 1);
     106       15177 :     boost::system::error_code pfxerr = Inet6SubnetParse(ip6pstr, &prefix.addr_,
     107             :                                                         &prefix.prefixlen_);
     108       15177 :     if (errorp != NULL) {
     109        1611 :         *errorp = pfxerr;
     110             :     }
     111       15177 :     return prefix;
     112       15184 : }
     113             : 
     114           9 : string Inet6VpnPrefix::ToString() const {
     115           9 :     Inet6Prefix prefix(addr_, prefixlen_);
     116          18 :     return (rd_.ToString() + ":" + prefix.ToString());
     117             : }
     118             : 
     119             : // Check whether 'this' is more specific than rhs.
     120          35 : bool Inet6VpnPrefix::IsMoreSpecific(const Inet6VpnPrefix &rhs) const {
     121          35 :     Inet6Prefix this_prefix(addr_, prefixlen_);
     122          35 :     Inet6Prefix match_prefix(rhs.addr(), rhs.prefixlen());
     123             : 
     124          70 :     return this_prefix.IsMoreSpecific(match_prefix);
     125             : }
     126             : 
     127     1495424 : int Inet6VpnPrefix::CompareTo(const Inet6VpnPrefix &other) const {
     128     1495424 :     int res = route_distinguisher().CompareTo(other.route_distinguisher());
     129     1495107 :     if (res != 0) {
     130      886288 :         return res;
     131             :     }
     132      608819 :     Ip6Address laddr = addr();
     133      609190 :     Ip6Address raddr = other.addr();
     134      609156 :     if (laddr < raddr) {
     135      215122 :         return -1;
     136             :     }
     137      394521 :     if (laddr > raddr) {
     138      172209 :         return 1;
     139             :     }
     140      222281 :     if (prefixlen() < other.prefixlen()) {
     141          16 :         return -1;
     142             :     }
     143      222275 :     if (prefixlen() > other.prefixlen()) {
     144           8 :         return 1;
     145             :     }
     146      222256 :     return 0;
     147             : }
     148             : 
     149           9 : bool Inet6VpnPrefix::operator==(const Inet6VpnPrefix &rhs) const {
     150          18 :     return (rd_ == rhs.rd_ && addr_ == rhs.addr_ &&
     151          18 :             prefixlen_ == rhs.prefixlen_);
     152             : }
     153             : 
     154      195854 : Inet6VpnRoute::Inet6VpnRoute(const Inet6VpnPrefix &prefix) : prefix_(prefix) {
     155      195824 : }
     156             : 
     157     1495499 : int Inet6VpnRoute::CompareTo(const Route &rhs) const {
     158     1495499 :     const Inet6VpnRoute &other = static_cast<const Inet6VpnRoute &>(rhs);
     159     1495499 :     return prefix_.CompareTo(other.GetPrefix());
     160             : }
     161             : 
     162      437457 : string Inet6VpnRoute::ToString() const {
     163      437457 :     string repr = prefix_.route_distinguisher().ToString() + ":";
     164      437478 :     repr += prefix_.addr().to_string();
     165             :     char strplen[5];
     166      437476 :     snprintf(strplen, sizeof(strplen), "/%d", prefix_.prefixlen());
     167      437475 :     repr.append(strplen);
     168             : 
     169      874962 :     return repr;
     170           0 : }
     171             : 
     172           2 : void Inet6VpnRoute::SetKey(const DBRequestKey *reqkey) {
     173           2 :     const Inet6VpnTable::RequestKey *key =
     174             :         static_cast<const Inet6VpnTable::RequestKey *>(reqkey);
     175           2 :     prefix_ = key->prefix;
     176           2 : }
     177             : 
     178       56584 : void Inet6VpnRoute::BuildProtoPrefix(BgpProtoPrefix *prefix,
     179             :                                      const BgpAttr*,
     180             :                                     uint32_t label,
     181             :                                     uint32_t l3_label) const {
     182       56584 :     prefix_.BuildProtoPrefix(label, prefix);
     183       56585 : }
     184             : 
     185             : // XXX dest_nh should have been pointer. See if can change
     186       30029 : void Inet6VpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &dest_nh,
     187             :                                          IpAddress src_nh) const {
     188       30029 :     dest_nh.resize(sizeof(Ip6Address::bytes_type) + RouteDistinguisher::kSize,
     189       30029 :                    0);
     190       30022 :     Ip6Address source_addr;
     191       30022 :     if (src_nh.is_v4()) {
     192       30022 :         source_addr = Ip6Address::v4_mapped(src_nh.to_v4());
     193           0 :     } else if (src_nh.is_v6()) {
     194           0 :         source_addr = src_nh.to_v6();
     195             :     } else {
     196           0 :         assert(0);
     197             :     }
     198             : 
     199       30028 :     Ip6Address::bytes_type addr_bytes = source_addr.to_bytes();
     200       30025 :     copy(addr_bytes.begin(), addr_bytes.end(),
     201       30025 :               dest_nh.begin() + RouteDistinguisher::kSize);
     202       30024 : }
     203             : 
     204       58958 : DBEntryBase::KeyPtr Inet6VpnRoute::GetDBRequestKey() const {
     205             :     Inet6VpnTable::RequestKey *key =
     206       58958 :         new Inet6VpnTable::RequestKey(GetPrefix(), NULL);
     207       58955 :     return KeyPtr(key);
     208             : }
     209             : 
     210             : // Check whether 'this' is more specific than rhs.
     211          22 : bool Inet6VpnRoute::IsMoreSpecific(const string &other) const {
     212          22 :     boost::system::error_code ec;
     213             : 
     214          22 :     Inet6VpnPrefix other_prefix = Inet6VpnPrefix::FromString(other, &ec);
     215          22 :     if (!ec) {
     216          22 :         return GetPrefix().IsMoreSpecific(other_prefix);
     217             :     }
     218             : 
     219           0 :     return false;
     220             : }
     221             : 
     222             : // Check whether 'this' is less specific than rhs.
     223          10 : bool Inet6VpnRoute::IsLessSpecific(const string &other) const {
     224          10 :     boost::system::error_code ec;
     225             : 
     226          10 :     Inet6VpnPrefix other_prefix = Inet6VpnPrefix::FromString(other, &ec);
     227          10 :     if (!ec) {
     228          10 :         return other_prefix.IsMoreSpecific(GetPrefix());
     229             :     }
     230             : 
     231           0 :     return false;
     232             : }

Generated by: LCOV version 1.14