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-09-07 02:14:47 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       64833 : Inet6VpnPrefix::Inet6VpnPrefix() : prefixlen_(0) {
      17       64833 : }
      18             : 
      19       49626 : int Inet6VpnPrefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
      20             :                                     Inet6VpnPrefix *prefix, uint32_t *label) {
      21       49626 :     size_t nlri_size = proto_prefix.prefix.size();
      22       49626 :     size_t expected_min_nlri_size =
      23       49626 :         BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize;
      24             : 
      25       49626 :     if (nlri_size < expected_min_nlri_size)
      26           1 :         return -1;
      27       49625 :     if (nlri_size > expected_min_nlri_size + Address::kMaxV6Bytes)
      28           1 :         return -1;
      29             : 
      30       49624 :     size_t label_offset = 0;
      31       49624 :     *label = proto_prefix.ReadLabel(label_offset);
      32       49624 :     size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
      33       49624 :     prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
      34             : 
      35       49624 :     size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
      36       49624 :     prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8;
      37       49624 :     Ip6Address::bytes_type bt = { { 0 } };
      38       49624 :     copy(proto_prefix.prefix.begin() + prefix_offset,
      39             :         proto_prefix.prefix.end(), bt.begin());
      40       49624 :     prefix->addr_ = Ip6Address(bt);
      41             : 
      42       49624 :     return 0;
      43             : }
      44             : 
      45       49621 : 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       49621 :     return FromProtoPrefix(proto_prefix, prefix, label);
      53             : }
      54             : 
      55       56436 : void Inet6VpnPrefix::BuildProtoPrefix(uint32_t label,
      56             :                                       BgpProtoPrefix *proto_prefix) const {
      57       56436 :     proto_prefix->prefix.clear();
      58       56435 :     size_t prefix_size = (prefixlen_ + 7) / 8;
      59       56435 :     size_t nlri_size =
      60       56435 :         BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize + prefix_size;
      61             : 
      62       56435 :     proto_prefix->prefix.resize(nlri_size, 0);
      63       56429 :     size_t label_offset = 0;
      64       56429 :     proto_prefix->WriteLabel(label_offset, label);
      65       56428 :     size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
      66       56428 :     copy(rd_.GetData(), rd_.GetData() + RouteDistinguisher::kSize,
      67       56428 :         proto_prefix->prefix.begin() + rd_offset);
      68             : 
      69       56419 :     size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
      70       56419 :     proto_prefix->prefixlen = prefix_offset * 8 + prefixlen_;
      71       56419 :     const Ip6Address::bytes_type &addr_bytes = addr_.to_bytes();
      72       56418 :     copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
      73       56419 :         proto_prefix->prefix.begin() + prefix_offset);
      74       56417 : }
      75             : 
      76             : // RD:inet6-prefix
      77       15205 : Inet6VpnPrefix Inet6VpnPrefix::FromString(const string &str,
      78             :                                           boost::system::error_code *errorp) {
      79       15205 :     Inet6VpnPrefix prefix;
      80             : 
      81       15205 :     size_t pos = str.find(':');
      82       15205 :     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       15204 :     pos = str.find(':', (pos + 1));
      89       15204 :     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       15203 :     string rdstr = str.substr(0, pos);
      96       15203 :     boost::system::error_code rderr;
      97       15203 :     prefix.rd_ = RouteDistinguisher::FromString(rdstr, &rderr);
      98       15203 :     if (rderr.failed()) {
      99           7 :         if (errorp != NULL) {
     100           5 :             *errorp = rderr;
     101             :         }
     102           7 :         return prefix;
     103             :     }
     104             : 
     105       15196 :     string ip6pstr(str, pos + 1);
     106       15196 :     boost::system::error_code pfxerr = Inet6SubnetParse(ip6pstr, &prefix.addr_,
     107             :                                                         &prefix.prefixlen_);
     108       15196 :     if (errorp != NULL) {
     109        1610 :         *errorp = pfxerr;
     110             :     }
     111       15196 :     return prefix;
     112       15203 : }
     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     1494097 : int Inet6VpnPrefix::CompareTo(const Inet6VpnPrefix &other) const {
     128     1494097 :     int res = route_distinguisher().CompareTo(other.route_distinguisher());
     129     1494285 :     if (res != 0) {
     130      885594 :         return res;
     131             :     }
     132      608691 :     Ip6Address laddr = addr();
     133      608640 :     Ip6Address raddr = other.addr();
     134      608594 :     if (laddr < raddr) {
     135      215004 :         return -1;
     136             :     }
     137      394043 :     if (laddr > raddr) {
     138      172360 :         return 1;
     139             :     }
     140      221652 :     if (prefixlen() < other.prefixlen()) {
     141          16 :         return -1;
     142             :     }
     143      221670 :     if (prefixlen() > other.prefixlen()) {
     144           8 :         return 1;
     145             :     }
     146      221657 :     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      195407 : Inet6VpnRoute::Inet6VpnRoute(const Inet6VpnPrefix &prefix) : prefix_(prefix) {
     155      195363 : }
     156             : 
     157     1494199 : int Inet6VpnRoute::CompareTo(const Route &rhs) const {
     158     1494199 :     const Inet6VpnRoute &other = static_cast<const Inet6VpnRoute &>(rhs);
     159     1494199 :     return prefix_.CompareTo(other.GetPrefix());
     160             : }
     161             : 
     162      446534 : string Inet6VpnRoute::ToString() const {
     163      446534 :     string repr = prefix_.route_distinguisher().ToString() + ":";
     164      446544 :     repr += prefix_.addr().to_string();
     165             :     char strplen[5];
     166      446527 :     snprintf(strplen, sizeof(strplen), "/%d", prefix_.prefixlen());
     167      446467 :     repr.append(strplen);
     168             : 
     169      893082 :     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       56434 : void Inet6VpnRoute::BuildProtoPrefix(BgpProtoPrefix *prefix,
     179             :                                      const BgpAttr*,
     180             :                                     uint32_t label,
     181             :                                     uint32_t l3_label) const {
     182       56434 :     prefix_.BuildProtoPrefix(label, prefix);
     183       56417 : }
     184             : 
     185             : // XXX dest_nh should have been pointer. See if can change
     186       30209 : void Inet6VpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &dest_nh,
     187             :                                          IpAddress src_nh) const {
     188       30209 :     dest_nh.resize(sizeof(Ip6Address::bytes_type) + RouteDistinguisher::kSize,
     189       30209 :                    0);
     190       30205 :     Ip6Address source_addr;
     191       30205 :     if (src_nh.is_v4()) {
     192       30205 :         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       30213 :     Ip6Address::bytes_type addr_bytes = source_addr.to_bytes();
     200       30212 :     copy(addr_bytes.begin(), addr_bytes.end(),
     201       30212 :               dest_nh.begin() + RouteDistinguisher::kSize);
     202       30211 : }
     203             : 
     204       58686 : DBEntryBase::KeyPtr Inet6VpnRoute::GetDBRequestKey() const {
     205             :     Inet6VpnTable::RequestKey *key =
     206       58686 :         new Inet6VpnTable::RequestKey(GetPrefix(), NULL);
     207       58674 :     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