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: 92 136 67.6 %
Date: 2026-10-05 02:12:29 Functions: 12 18 66.7 %
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        8064 : Inet6VpnPrefix::Inet6VpnPrefix() : prefixlen_(0) {
      17        8064 : }
      18             : 
      19        6528 : int Inet6VpnPrefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
      20             :                                     Inet6VpnPrefix *prefix, uint32_t *label) {
      21        6528 :     size_t nlri_size = proto_prefix.prefix.size();
      22        6528 :     size_t expected_min_nlri_size =
      23        6528 :         BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize;
      24             : 
      25        6528 :     if (nlri_size < expected_min_nlri_size)
      26           0 :         return -1;
      27        6528 :     if (nlri_size > expected_min_nlri_size + Address::kMaxV6Bytes)
      28           0 :         return -1;
      29             : 
      30        6528 :     size_t label_offset = 0;
      31        6528 :     *label = proto_prefix.ReadLabel(label_offset);
      32        6528 :     size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
      33        6528 :     prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
      34             : 
      35        6528 :     size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
      36        6528 :     prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8;
      37        6528 :     Ip6Address::bytes_type bt = { { 0 } };
      38        6528 :     copy(proto_prefix.prefix.begin() + prefix_offset,
      39             :         proto_prefix.prefix.end(), bt.begin());
      40        6528 :     prefix->addr_ = Ip6Address(bt);
      41             : 
      42        6528 :     return 0;
      43             : }
      44             : 
      45        6528 : 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        6528 :     return FromProtoPrefix(proto_prefix, prefix, label);
      53             : }
      54             : 
      55        7495 : void Inet6VpnPrefix::BuildProtoPrefix(uint32_t label,
      56             :                                       BgpProtoPrefix *proto_prefix) const {
      57        7495 :     proto_prefix->prefix.clear();
      58        7495 :     size_t prefix_size = (prefixlen_ + 7) / 8;
      59        7495 :     size_t nlri_size =
      60        7495 :         BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize + prefix_size;
      61             : 
      62        7495 :     proto_prefix->prefix.resize(nlri_size, 0);
      63        7495 :     size_t label_offset = 0;
      64        7495 :     proto_prefix->WriteLabel(label_offset, label);
      65        7495 :     size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
      66        7495 :     copy(rd_.GetData(), rd_.GetData() + RouteDistinguisher::kSize,
      67        7495 :         proto_prefix->prefix.begin() + rd_offset);
      68             : 
      69        7494 :     size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
      70        7494 :     proto_prefix->prefixlen = prefix_offset * 8 + prefixlen_;
      71        7494 :     const Ip6Address::bytes_type &addr_bytes = addr_.to_bytes();
      72        7493 :     copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
      73        7494 :         proto_prefix->prefix.begin() + prefix_offset);
      74        7492 : }
      75             : 
      76             : // RD:inet6-prefix
      77        1536 : Inet6VpnPrefix Inet6VpnPrefix::FromString(const string &str,
      78             :                                           boost::system::error_code *errorp) {
      79        1536 :     Inet6VpnPrefix prefix;
      80             : 
      81        1536 :     size_t pos = str.find(':');
      82        1536 :     if (pos == string::npos) {
      83           0 :         if (errorp != NULL) {
      84           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      85             :         }
      86           0 :         return prefix;
      87             :     }
      88        1536 :     pos = str.find(':', (pos + 1));
      89        1536 :     if (pos == string::npos) {
      90           0 :         if (errorp != NULL) {
      91           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      92             :         }
      93           0 :         return prefix;
      94             :     }
      95        1536 :     string rdstr = str.substr(0, pos);
      96        1536 :     boost::system::error_code rderr;
      97        1536 :     prefix.rd_ = RouteDistinguisher::FromString(rdstr, &rderr);
      98        1536 :     if (rderr.failed()) {
      99           0 :         if (errorp != NULL) {
     100           0 :             *errorp = rderr;
     101             :         }
     102           0 :         return prefix;
     103             :     }
     104             : 
     105        1536 :     string ip6pstr(str, pos + 1);
     106        1536 :     boost::system::error_code pfxerr = Inet6SubnetParse(ip6pstr, &prefix.addr_,
     107             :                                                         &prefix.prefixlen_);
     108        1536 :     if (errorp != NULL) {
     109           0 :         *errorp = pfxerr;
     110             :     }
     111        1536 :     return prefix;
     112        1536 : }
     113             : 
     114           0 : string Inet6VpnPrefix::ToString() const {
     115           0 :     Inet6Prefix prefix(addr_, prefixlen_);
     116           0 :     return (rd_.ToString() + ":" + prefix.ToString());
     117             : }
     118             : 
     119             : // Check whether 'this' is more specific than rhs.
     120           0 : bool Inet6VpnPrefix::IsMoreSpecific(const Inet6VpnPrefix &rhs) const {
     121           0 :     Inet6Prefix this_prefix(addr_, prefixlen_);
     122           0 :     Inet6Prefix match_prefix(rhs.addr(), rhs.prefixlen());
     123             : 
     124           0 :     return this_prefix.IsMoreSpecific(match_prefix);
     125             : }
     126             : 
     127      193467 : int Inet6VpnPrefix::CompareTo(const Inet6VpnPrefix &other) const {
     128      193467 :     int res = route_distinguisher().CompareTo(other.route_distinguisher());
     129      193490 :     if (res != 0) {
     130      127210 :         return res;
     131             :     }
     132       66280 :     Ip6Address laddr = addr();
     133       66274 :     Ip6Address raddr = other.addr();
     134       66267 :     if (laddr < raddr) {
     135       21242 :         return -1;
     136             :     }
     137       45076 :     if (laddr > raddr) {
     138       15922 :         return 1;
     139             :     }
     140       29149 :     if (prefixlen() < other.prefixlen()) {
     141           0 :         return -1;
     142             :     }
     143       29150 :     if (prefixlen() > other.prefixlen()) {
     144           0 :         return 1;
     145             :     }
     146       29149 :     return 0;
     147             : }
     148             : 
     149           0 : bool Inet6VpnPrefix::operator==(const Inet6VpnPrefix &rhs) const {
     150           0 :     return (rd_ == rhs.rd_ && addr_ == rhs.addr_ &&
     151           0 :             prefixlen_ == rhs.prefixlen_);
     152             : }
     153             : 
     154       27430 : Inet6VpnRoute::Inet6VpnRoute(const Inet6VpnPrefix &prefix) : prefix_(prefix) {
     155       27424 : }
     156             : 
     157      193462 : int Inet6VpnRoute::CompareTo(const Route &rhs) const {
     158      193462 :     const Inet6VpnRoute &other = static_cast<const Inet6VpnRoute &>(rhs);
     159      193462 :     return prefix_.CompareTo(other.GetPrefix());
     160             : }
     161             : 
     162       67068 : string Inet6VpnRoute::ToString() const {
     163       67068 :     string repr = prefix_.route_distinguisher().ToString() + ":";
     164       67074 :     repr += prefix_.addr().to_string();
     165             :     char strplen[5];
     166       67071 :     snprintf(strplen, sizeof(strplen), "/%d", prefix_.prefixlen());
     167       67071 :     repr.append(strplen);
     168             : 
     169      134152 :     return repr;
     170           0 : }
     171             : 
     172           0 : void Inet6VpnRoute::SetKey(const DBRequestKey *reqkey) {
     173           0 :     const Inet6VpnTable::RequestKey *key =
     174             :         static_cast<const Inet6VpnTable::RequestKey *>(reqkey);
     175           0 :     prefix_ = key->prefix;
     176           0 : }
     177             : 
     178        7494 : void Inet6VpnRoute::BuildProtoPrefix(BgpProtoPrefix *prefix,
     179             :                                      const BgpAttr*,
     180             :                                     uint32_t label,
     181             :                                     uint32_t l3_label) const {
     182        7494 :     prefix_.BuildProtoPrefix(label, prefix);
     183        7492 : }
     184             : 
     185             : // XXX dest_nh should have been pointer. See if can change
     186        4522 : void Inet6VpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &dest_nh,
     187             :                                          IpAddress src_nh) const {
     188        4522 :     dest_nh.resize(sizeof(Ip6Address::bytes_type) + RouteDistinguisher::kSize,
     189        4522 :                    0);
     190        4521 :     Ip6Address source_addr;
     191        4521 :     if (src_nh.is_v4()) {
     192        4521 :         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        4521 :     Ip6Address::bytes_type addr_bytes = source_addr.to_bytes();
     200        4521 :     copy(addr_bytes.begin(), addr_bytes.end(),
     201        4521 :               dest_nh.begin() + RouteDistinguisher::kSize);
     202        4521 : }
     203             : 
     204       12008 : DBEntryBase::KeyPtr Inet6VpnRoute::GetDBRequestKey() const {
     205             :     Inet6VpnTable::RequestKey *key =
     206       12008 :         new Inet6VpnTable::RequestKey(GetPrefix(), NULL);
     207       12006 :     return KeyPtr(key);
     208             : }
     209             : 
     210             : // Check whether 'this' is more specific than rhs.
     211           0 : bool Inet6VpnRoute::IsMoreSpecific(const string &other) const {
     212           0 :     boost::system::error_code ec;
     213             : 
     214           0 :     Inet6VpnPrefix other_prefix = Inet6VpnPrefix::FromString(other, &ec);
     215           0 :     if (!ec) {
     216           0 :         return GetPrefix().IsMoreSpecific(other_prefix);
     217             :     }
     218             : 
     219           0 :     return false;
     220             : }
     221             : 
     222             : // Check whether 'this' is less specific than rhs.
     223           0 : bool Inet6VpnRoute::IsLessSpecific(const string &other) const {
     224           0 :     boost::system::error_code ec;
     225             : 
     226           0 :     Inet6VpnPrefix other_prefix = Inet6VpnPrefix::FromString(other, &ec);
     227           0 :     if (!ec) {
     228           0 :         return other_prefix.IsMoreSpecific(GetPrefix());
     229             :     }
     230             : 
     231           0 :     return false;
     232             : }

Generated by: LCOV version 1.14