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-11-09 02:10:49 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             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include "bgp/inet6vpn/inet6vpn_route.h"
       7             : 
       8             : #include <algorithm>
       9             : 
      10             : #include "bgp/inet6vpn/inet6vpn_table.h"
      11             : #include "bgp/inet6/inet6_route.h"
      12             : 
      13             : using std::copy;
      14             : using std::string;
      15             : using std::vector;
      16             : 
      17       65005 : Inet6VpnPrefix::Inet6VpnPrefix() : prefixlen_(0) {
      18       65005 : }
      19             : 
      20       49829 : int Inet6VpnPrefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
      21             :                                     Inet6VpnPrefix *prefix, uint32_t *label) {
      22       49829 :     size_t nlri_size = proto_prefix.prefix.size();
      23       49829 :     size_t expected_min_nlri_size =
      24       49829 :         BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize;
      25             : 
      26       49829 :     if (nlri_size < expected_min_nlri_size)
      27           1 :         return -1;
      28       49828 :     if (nlri_size > expected_min_nlri_size + Address::kMaxV6Bytes)
      29           1 :         return -1;
      30             : 
      31       49827 :     size_t label_offset = 0;
      32       49827 :     *label = proto_prefix.ReadLabel(label_offset);
      33       49827 :     size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
      34       49827 :     prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
      35             : 
      36       49827 :     size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
      37       49827 :     prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8;
      38       49827 :     Ip6Address::bytes_type bt = { { 0 } };
      39       49827 :     copy(proto_prefix.prefix.begin() + prefix_offset,
      40             :         proto_prefix.prefix.end(), bt.begin());
      41       49827 :     prefix->addr_ = Ip6Address(bt);
      42             : 
      43       49827 :     return 0;
      44             : }
      45             : 
      46       49824 : int Inet6VpnPrefix::FromProtoPrefix(BgpServer *server,
      47             :                                     const BgpProtoPrefix &proto_prefix,
      48             :                                     const BgpAttr *attr,
      49             :                                     const Address::Family family,
      50             :                                     Inet6VpnPrefix *prefix,
      51             :                                     BgpAttrPtr *new_attr, uint32_t *label,
      52             :                                     uint32_t *l3_label) {
      53       49824 :     return FromProtoPrefix(proto_prefix, prefix, label);
      54             : }
      55             : 
      56       57195 : void Inet6VpnPrefix::BuildProtoPrefix(uint32_t label,
      57             :                                       BgpProtoPrefix *proto_prefix) const {
      58       57195 :     proto_prefix->prefix.clear();
      59       57199 :     size_t prefix_size = (prefixlen_ + 7) / 8;
      60       57199 :     size_t nlri_size =
      61       57199 :         BgpProtoPrefix::kLabelSize + RouteDistinguisher::kSize + prefix_size;
      62             : 
      63       57199 :     proto_prefix->prefix.resize(nlri_size, 0);
      64       57202 :     size_t label_offset = 0;
      65       57202 :     proto_prefix->WriteLabel(label_offset, label);
      66       57202 :     size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
      67       57203 :     copy(rd_.GetData(), rd_.GetData() + RouteDistinguisher::kSize,
      68       57202 :         proto_prefix->prefix.begin() + rd_offset);
      69             : 
      70       57197 :     size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
      71       57197 :     proto_prefix->prefixlen = prefix_offset * 8 + prefixlen_;
      72       57197 :     const Ip6Address::bytes_type &addr_bytes = addr_.to_bytes();
      73       57198 :     copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
      74       57199 :         proto_prefix->prefix.begin() + prefix_offset);
      75       57192 : }
      76             : 
      77             : // RD:inet6-prefix
      78       15174 : Inet6VpnPrefix Inet6VpnPrefix::FromString(const string &str,
      79             :                                           boost::system::error_code *errorp) {
      80       15174 :     Inet6VpnPrefix prefix;
      81             : 
      82       15174 :     size_t pos = str.find(':');
      83       15174 :     if (pos == string::npos) {
      84           1 :         if (errorp != NULL) {
      85           1 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      86             :         }
      87           1 :         return prefix;
      88             :     }
      89       15173 :     pos = str.find(':', (pos + 1));
      90       15173 :     if (pos == string::npos) {
      91           1 :         if (errorp != NULL) {
      92           1 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      93             :         }
      94           1 :         return prefix;
      95             :     }
      96       15172 :     string rdstr = str.substr(0, pos);
      97       15172 :     boost::system::error_code rderr;
      98       15172 :     prefix.rd_ = RouteDistinguisher::FromString(rdstr, &rderr);
      99       15172 :     if (rderr.failed()) {
     100           7 :         if (errorp != NULL) {
     101           5 :             *errorp = rderr;
     102             :         }
     103           7 :         return prefix;
     104             :     }
     105             : 
     106       15165 :     string ip6pstr(str, pos + 1);
     107       15165 :     boost::system::error_code pfxerr = Inet6SubnetParse(ip6pstr, &prefix.addr_,
     108             :                                                         &prefix.prefixlen_);
     109       15165 :     if (errorp != NULL) {
     110        1589 :         *errorp = pfxerr;
     111             :     }
     112       15165 :     return prefix;
     113       15172 : }
     114             : 
     115           9 : string Inet6VpnPrefix::ToString() const {
     116           9 :     Inet6Prefix prefix(addr_, prefixlen_);
     117          18 :     return (rd_.ToString() + ":" + prefix.ToString());
     118             : }
     119             : 
     120             : // Check whether 'this' is more specific than rhs.
     121          35 : bool Inet6VpnPrefix::IsMoreSpecific(const Inet6VpnPrefix &rhs) const {
     122          35 :     Inet6Prefix this_prefix(addr_, prefixlen_);
     123          35 :     Inet6Prefix match_prefix(rhs.addr(), rhs.prefixlen());
     124             : 
     125          70 :     return this_prefix.IsMoreSpecific(match_prefix);
     126             : }
     127             : 
     128     1499237 : int Inet6VpnPrefix::CompareTo(const Inet6VpnPrefix &other) const {
     129     1499237 :     int res = route_distinguisher().CompareTo(other.route_distinguisher());
     130     1499433 :     if (res != 0) {
     131      887724 :         return res;
     132             :     }
     133      611709 :     Ip6Address laddr = addr();
     134      611665 :     Ip6Address raddr = other.addr();
     135      611605 :     if (laddr < raddr) {
     136      216261 :         return -1;
     137             :     }
     138      395917 :     if (laddr > raddr) {
     139      173005 :         return 1;
     140             :     }
     141      222894 :     if (prefixlen() < other.prefixlen()) {
     142          16 :         return -1;
     143             :     }
     144      222907 :     if (prefixlen() > other.prefixlen()) {
     145           8 :         return 1;
     146             :     }
     147      222883 :     return 0;
     148             : }
     149             : 
     150           9 : bool Inet6VpnPrefix::operator==(const Inet6VpnPrefix &rhs) const {
     151          18 :     return (rd_ == rhs.rd_ && addr_ == rhs.addr_ &&
     152          18 :             prefixlen_ == rhs.prefixlen_);
     153             : }
     154             : 
     155      196398 : Inet6VpnRoute::Inet6VpnRoute(const Inet6VpnPrefix &prefix) : prefix_(prefix) {
     156      196381 : }
     157             : 
     158     1499348 : int Inet6VpnRoute::CompareTo(const Route &rhs) const {
     159     1499348 :     const Inet6VpnRoute &other = static_cast<const Inet6VpnRoute &>(rhs);
     160     1499348 :     return prefix_.CompareTo(other.GetPrefix());
     161             : }
     162             : 
     163      440765 : string Inet6VpnRoute::ToString() const {
     164      440765 :     string repr = prefix_.route_distinguisher().ToString() + ":";
     165      440762 :     repr += prefix_.addr().to_string();
     166             :     char strplen[5];
     167      440765 :     snprintf(strplen, sizeof(strplen), "/%d", prefix_.prefixlen());
     168      440761 :     repr.append(strplen);
     169             : 
     170      881536 :     return repr;
     171           0 : }
     172             : 
     173           2 : void Inet6VpnRoute::SetKey(const DBRequestKey *reqkey) {
     174           2 :     const Inet6VpnTable::RequestKey *key =
     175             :         static_cast<const Inet6VpnTable::RequestKey *>(reqkey);
     176           2 :     prefix_ = key->prefix;
     177           2 : }
     178             : 
     179       57195 : void Inet6VpnRoute::BuildProtoPrefix(BgpProtoPrefix *prefix,
     180             :                                      const BgpAttr*,
     181             :                                     uint32_t label,
     182             :                                     uint32_t l3_label) const {
     183       57195 :     prefix_.BuildProtoPrefix(label, prefix);
     184       57192 : }
     185             : 
     186             : // XXX dest_nh should have been pointer. See if can change
     187       30254 : void Inet6VpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &dest_nh,
     188             :                                          IpAddress src_nh) const {
     189       30254 :     dest_nh.resize(sizeof(Ip6Address::bytes_type) + RouteDistinguisher::kSize,
     190       30254 :                    0);
     191       30253 :     Ip6Address source_addr;
     192       30251 :     if (src_nh.is_v4()) {
     193       30249 :         source_addr = Ip6Address::v4_mapped(src_nh.to_v4());
     194           0 :     } else if (src_nh.is_v6()) {
     195           0 :         source_addr = src_nh.to_v6();
     196             :     } else {
     197           0 :         assert(0);
     198             :     }
     199             : 
     200       30256 :     Ip6Address::bytes_type addr_bytes = source_addr.to_bytes();
     201       30255 :     copy(addr_bytes.begin(), addr_bytes.end(),
     202       30255 :               dest_nh.begin() + RouteDistinguisher::kSize);
     203       30248 : }
     204             : 
     205       59305 : DBEntryBase::KeyPtr Inet6VpnRoute::GetDBRequestKey() const {
     206             :     Inet6VpnTable::RequestKey *key =
     207       59305 :         new Inet6VpnTable::RequestKey(GetPrefix(), NULL);
     208       59291 :     return KeyPtr(key);
     209             : }
     210             : 
     211             : // Check whether 'this' is more specific than rhs.
     212          22 : bool Inet6VpnRoute::IsMoreSpecific(const string &other) const {
     213          22 :     boost::system::error_code ec;
     214             : 
     215          22 :     Inet6VpnPrefix other_prefix = Inet6VpnPrefix::FromString(other, &ec);
     216          22 :     if (!ec) {
     217          22 :         return GetPrefix().IsMoreSpecific(other_prefix);
     218             :     }
     219             : 
     220           0 :     return false;
     221             : }
     222             : 
     223             : // Check whether 'this' is less specific than rhs.
     224          10 : bool Inet6VpnRoute::IsLessSpecific(const string &other) const {
     225          10 :     boost::system::error_code ec;
     226             : 
     227          10 :     Inet6VpnPrefix other_prefix = Inet6VpnPrefix::FromString(other, &ec);
     228          10 :     if (!ec) {
     229          10 :         return other_prefix.IsMoreSpecific(GetPrefix());
     230             :     }
     231             : 
     232           0 :     return false;
     233             : }

Generated by: LCOV version 1.14