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-04 02:06:09 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       64931 : Inet6VpnPrefix::Inet6VpnPrefix() : prefixlen_(0) {
      17       64931 : }
      18             : 
      19       49740 : int Inet6VpnPrefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
      20             :                                     Inet6VpnPrefix *prefix, uint32_t *label) {
      21       49740 :     size_t nlri_size = proto_prefix.prefix.size();
      22       49740 :     size_t expected_min_nlri_size =
      23       49740 :         BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize;
      24             : 
      25       49740 :     if (nlri_size < expected_min_nlri_size)
      26           1 :         return -1;
      27       49739 :     if (nlri_size > expected_min_nlri_size + Address::kMaxV6Bytes)
      28           1 :         return -1;
      29             : 
      30       49738 :     size_t label_offset = 0;
      31       49738 :     *label = proto_prefix.ReadLabel(label_offset);
      32       49738 :     size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
      33       49738 :     prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
      34             : 
      35       49738 :     size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
      36       49738 :     prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8;
      37       49738 :     Ip6Address::bytes_type bt = { { 0 } };
      38       49738 :     copy(proto_prefix.prefix.begin() + prefix_offset,
      39             :         proto_prefix.prefix.end(), bt.begin());
      40       49738 :     prefix->addr_ = Ip6Address(bt);
      41             : 
      42       49738 :     return 0;
      43             : }
      44             : 
      45       49735 : 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       49735 :     return FromProtoPrefix(proto_prefix, prefix, label);
      53             : }
      54             : 
      55       56226 : void Inet6VpnPrefix::BuildProtoPrefix(uint32_t label,
      56             :                                       BgpProtoPrefix *proto_prefix) const {
      57       56226 :     proto_prefix->prefix.clear();
      58       56228 :     size_t prefix_size = (prefixlen_ + 7) / 8;
      59       56228 :     size_t nlri_size =
      60       56228 :         BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize + prefix_size;
      61             : 
      62       56228 :     proto_prefix->prefix.resize(nlri_size, 0);
      63       56226 :     size_t label_offset = 0;
      64       56226 :     proto_prefix->WriteLabel(label_offset, label);
      65       56226 :     size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
      66       56226 :     copy(rd_.GetData(), rd_.GetData() + RouteDistinguisher::kSize,
      67       56226 :         proto_prefix->prefix.begin() + rd_offset);
      68             : 
      69       56226 :     size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
      70       56226 :     proto_prefix->prefixlen = prefix_offset * 8 + prefixlen_;
      71       56226 :     const Ip6Address::bytes_type &addr_bytes = addr_.to_bytes();
      72       56226 :     copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
      73       56227 :         proto_prefix->prefix.begin() + prefix_offset);
      74       56224 : }
      75             : 
      76             : // RD:inet6-prefix
      77       15189 : Inet6VpnPrefix Inet6VpnPrefix::FromString(const string &str,
      78             :                                           boost::system::error_code *errorp) {
      79       15189 :     Inet6VpnPrefix prefix;
      80             : 
      81       15189 :     size_t pos = str.find(':');
      82       15189 :     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       15188 :     pos = str.find(':', (pos + 1));
      89       15188 :     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       15187 :     string rdstr = str.substr(0, pos);
      96       15187 :     boost::system::error_code rderr;
      97       15187 :     prefix.rd_ = RouteDistinguisher::FromString(rdstr, &rderr);
      98       15187 :     if (rderr.failed()) {
      99           7 :         if (errorp != NULL) {
     100           5 :             *errorp = rderr;
     101             :         }
     102           7 :         return prefix;
     103             :     }
     104             : 
     105       15180 :     string ip6pstr(str, pos + 1);
     106       15180 :     boost::system::error_code pfxerr = Inet6SubnetParse(ip6pstr, &prefix.addr_,
     107             :                                                         &prefix.prefixlen_);
     108       15180 :     if (errorp != NULL) {
     109        1608 :         *errorp = pfxerr;
     110             :     }
     111       15180 :     return prefix;
     112       15187 : }
     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     1498105 : int Inet6VpnPrefix::CompareTo(const Inet6VpnPrefix &other) const {
     128     1498105 :     int res = route_distinguisher().CompareTo(other.route_distinguisher());
     129     1498173 :     if (res != 0) {
     130      888152 :         return res;
     131             :     }
     132      610021 :     Ip6Address laddr = addr();
     133      609980 :     Ip6Address raddr = other.addr();
     134      609937 :     if (laddr < raddr) {
     135      215494 :         return -1;
     136             :     }
     137      394906 :     if (laddr > raddr) {
     138      172333 :         return 1;
     139             :     }
     140      222546 :     if (prefixlen() < other.prefixlen()) {
     141          16 :         return -1;
     142             :     }
     143      222542 :     if (prefixlen() > other.prefixlen()) {
     144           8 :         return 1;
     145             :     }
     146      222516 :     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      196149 : Inet6VpnRoute::Inet6VpnRoute(const Inet6VpnPrefix &prefix) : prefix_(prefix) {
     155      196107 : }
     156             : 
     157     1498153 : int Inet6VpnRoute::CompareTo(const Route &rhs) const {
     158     1498153 :     const Inet6VpnRoute &other = static_cast<const Inet6VpnRoute &>(rhs);
     159     1498153 :     return prefix_.CompareTo(other.GetPrefix());
     160             : }
     161             : 
     162      439668 : string Inet6VpnRoute::ToString() const {
     163      439668 :     string repr = prefix_.route_distinguisher().ToString() + ":";
     164      439670 :     repr += prefix_.addr().to_string();
     165             :     char strplen[5];
     166      439673 :     snprintf(strplen, sizeof(strplen), "/%d", prefix_.prefixlen());
     167      439669 :     repr.append(strplen);
     168             : 
     169      879342 :     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       56226 : void Inet6VpnRoute::BuildProtoPrefix(BgpProtoPrefix *prefix,
     179             :                                      const BgpAttr*,
     180             :                                     uint32_t label,
     181             :                                     uint32_t l3_label) const {
     182       56226 :     prefix_.BuildProtoPrefix(label, prefix);
     183       56224 : }
     184             : 
     185             : // XXX dest_nh should have been pointer. See if can change
     186       30180 : void Inet6VpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &dest_nh,
     187             :                                          IpAddress src_nh) const {
     188       30180 :     dest_nh.resize(sizeof(Ip6Address::bytes_type) + RouteDistinguisher::kSize,
     189       30180 :                    0);
     190       30178 :     Ip6Address source_addr;
     191       30177 :     if (src_nh.is_v4()) {
     192       30177 :         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       30184 :     Ip6Address::bytes_type addr_bytes = source_addr.to_bytes();
     200       30184 :     copy(addr_bytes.begin(), addr_bytes.end(),
     201       30184 :               dest_nh.begin() + RouteDistinguisher::kSize);
     202       30183 : }
     203             : 
     204       59235 : DBEntryBase::KeyPtr Inet6VpnRoute::GetDBRequestKey() const {
     205             :     Inet6VpnTable::RequestKey *key =
     206       59235 :         new Inet6VpnTable::RequestKey(GetPrefix(), NULL);
     207       59231 :     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