LCOV - code coverage report
Current view: top level - net - rd.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 96 96 100.0 %
Date: 2026-11-09 02:10:49 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  * Copyright Contributors to the OpenSDN project
       4             :  */
       5             : 
       6             : #include "net/rd.h"
       7             : 
       8             : #include <string>
       9             : 
      10             : #include "base/parse_object.h"
      11             : #include "base/address.h"
      12             : 
      13             : using std::string;
      14             : 
      15             : RouteDistinguisher RouteDistinguisher::kZeroRd;
      16             : 
      17     1908914 : RouteDistinguisher::RouteDistinguisher() {
      18     1908914 :     memset(data_, 0, kSize);
      19     1908914 : }
      20             : 
      21      189114 : RouteDistinguisher::RouteDistinguisher(const uint8_t *data) {
      22      189114 :     memcpy(data_, data, kSize);
      23      189114 : }
      24             : 
      25      233285 : RouteDistinguisher::RouteDistinguisher(uint32_t address, uint16_t vrf_id) {
      26      233285 :     put_value(data_, 2, TypeIpAddressBased);
      27      233285 :     put_value(data_ + 2, 4, address);
      28      233284 :     put_value(data_ + 6, 2, vrf_id);
      29      233284 : }
      30             : 
      31        1247 : RouteDistinguisher::RouteDistinguisher(bool is_bgpaas, uint32_t asn, uint16_t vmi_index) {
      32        1247 :     put_value(data_, 2, Type4ByteASBased);
      33        1247 :     put_value(data_ + 2, 4, asn);
      34        1247 :     put_value(data_ + 6, 2, vmi_index);
      35        1247 : }
      36             : 
      37           8 : RouteDistinguisher::RouteDistinguisher(uint16_t cluster_seed, uint32_t address,
      38           8 :                                        uint16_t vrf_id) {
      39           8 :     put_value(data_, 2, TypeIpAddressBased);
      40           8 :     put_value(data_ + 2, 2, cluster_seed);
      41           8 :     put_value(data_ + 4, 2, (address & 0xFFFF));
      42           8 :     put_value(data_ + 6, 2, vrf_id);
      43           8 : }
      44             : 
      45       62606 : uint16_t RouteDistinguisher::Type() const {
      46       62606 :     return get_value(data_, 2);
      47             : }
      48             : 
      49       41239 : uint32_t RouteDistinguisher::GetAddress() const {
      50       41239 :     return (Type() == TypeIpAddressBased ? get_value(data_ + 2, 4) : 0);
      51             : }
      52             : 
      53       19890 : uint16_t RouteDistinguisher::GetVrfId() const {
      54       19890 :     return (Type() == TypeIpAddressBased ? get_value(data_ + 6, 2) : 0);
      55             : }
      56             : 
      57     2373299 : string RouteDistinguisher::ToString() const {
      58             :     char temp[32];
      59             : 
      60     2373299 :     uint16_t rd_type = get_value(data_, 2);
      61     2373324 :     if (rd_type == Type2ByteASBased) {
      62      687792 :         uint16_t asn = get_value(data_ + 2, 2);
      63      687801 :         uint32_t value = get_value(data_ + 4, 4);
      64      687803 :         snprintf(temp, sizeof(temp), "%u:%u", asn, value);
      65      687803 :         return string(temp);
      66     1685532 :     } else if (rd_type == TypeIpAddressBased) {
      67     1683928 :         Ip4Address ip(get_value(data_ + 2, 4));
      68     1683928 :         uint16_t value = get_value(data_ + 6, 2);
      69     1683931 :         snprintf(temp, sizeof(temp), ":%u", value);
      70     3367871 :         return ip.to_string() + temp;
      71        1604 :     } else if (rd_type == Type4ByteASBased) {
      72        1602 :         uint32_t asn = get_value(data_ + 2, 4);
      73        1602 :         uint16_t value = get_value(data_ + 6, 2);
      74        1602 :         snprintf(temp, sizeof(temp), "%u:%u", asn, value);
      75        1602 :         return string(temp);
      76             :     } else {
      77           2 :         snprintf(temp, sizeof(temp), "%u:%02x:%02x:%02x:%02x:%02x:%02x",
      78           2 :             rd_type, data_[2], data_[3], data_[4], data_[5], data_[6],
      79           2 :             data_[7]);
      80           2 :         return string(temp);
      81             :     }
      82             : }
      83             : 
      84      178660 : RouteDistinguisher RouteDistinguisher::FromString(
      85             :     const string &str, boost::system::error_code *errorp) {
      86      178660 :     RouteDistinguisher rd;
      87      178660 :     size_t pos = str.rfind(':');
      88      178660 :     if (pos == string::npos) {
      89          34 :         if (errorp != NULL) {
      90           1 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      91             :         }
      92          34 :         return RouteDistinguisher::kZeroRd;
      93             :     }
      94             : 
      95      178626 :     boost::system::error_code ec;
      96      178626 :     string first(str.substr(0, pos));
      97      178626 :     Ip4Address addr = Ip4Address::from_string(first, ec);
      98             :     int offset;
      99             :     char *endptr;
     100      178626 :     int32_t asn = -1;
     101      178626 :     if (ec.value() != 0) {
     102             :         // Not an IP address, try ASN.
     103       69717 :         asn = strtol(first.c_str(), &endptr, 10);
     104       69717 :         if (asn >= 65535 || *endptr != '\0') {
     105           8 :             if (errorp != NULL) {
     106             :                 *errorp =
     107           8 :                     make_error_code(boost::system::errc::invalid_argument);
     108             :             }
     109           8 :             return RouteDistinguisher::kZeroRd;
     110             :         }
     111             : 
     112       69709 :         put_value(rd.data_, 2, 0);
     113       69709 :         put_value(rd.data_ + 2, 2, asn);
     114       69709 :         offset = 4;
     115             :     } else {
     116      108909 :         put_value(rd.data_, 2, 1);
     117      108909 :         put_value(rd.data_ + 2, 4, addr.to_ulong());
     118      108909 :         offset = 6;
     119             :     }
     120             : 
     121      178618 :     string second(str, pos + 1);
     122      178618 :     uint64_t value = strtol(second.c_str(), &endptr, 10);
     123      178618 :     if (*endptr != '\0') {
     124           4 :         if (errorp != NULL) {
     125           4 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     126             :         }
     127           4 :         return RouteDistinguisher::kZeroRd;
     128             :     }
     129             : 
     130             :     // ASN 0 is not allowed if the assigned number is not 0.
     131      178614 :     if (asn == 0 && value != 0) {
     132           2 :         if (errorp != NULL) {
     133           2 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     134             :         }
     135           2 :         return RouteDistinguisher::kZeroRd;
     136             :     }
     137             : 
     138             :     // Check assigned number for type 0.
     139      178612 :     if (offset == 4 && value > 0xFFFFFFFF) {
     140           2 :         if (errorp != NULL) {
     141           2 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     142             :         }
     143           2 :         return RouteDistinguisher::kZeroRd;
     144             :     }
     145             : 
     146             :     // Check assigned number for type 1.
     147      178610 :     if (offset == 6 && value > 0xFFFF) {
     148          11 :         if (errorp != NULL) {
     149          11 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     150             :         }
     151          11 :         return RouteDistinguisher::kZeroRd;
     152             :     }
     153             : 
     154      178599 :     put_value(rd.data_ + offset, 8 - offset, value);
     155      178599 :     return rd;
     156      178626 : }
     157             : 
     158    39664003 : int RouteDistinguisher::CompareTo(const RouteDistinguisher &rhs) const {
     159    39664003 :     return memcmp(data_, rhs.data_, kSize);
     160             : }

Generated by: LCOV version 1.14