LCOV - code coverage report
Current view: top level - bgp/extended-community - sub_cluster.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 80 89 89.9 %
Date: 2026-06-08 02:02:55 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2019 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "bgp/extended-community/sub_cluster.h"
       6             : 
       7             : #include <algorithm>
       8             : 
       9             : #include "base/address.h"
      10             : 
      11             : using std::copy;
      12             : using std::string;
      13             : 
      14             : SubCluster SubCluster::null_sub_cluster;
      15             : 
      16         175 : SubCluster::SubCluster() {
      17         175 :     data_.fill(0);
      18         175 : }
      19             : 
      20           9 : SubCluster::SubCluster(const bytes_type &data) {
      21           9 :     copy(data.begin(), data.end(), data_.begin());
      22           9 : }
      23             : 
      24           4 : SubCluster::SubCluster(as_t asn, const uint32_t id) {
      25           4 :     if (asn <= AS2_MAX) {
      26           3 :         data_[0] = BgpExtendedCommunityType::Experimental;
      27           3 :         put_value(&data_[2], 2, asn);
      28           3 :         put_value(&data_[4], 4, id);
      29             :     } else {
      30           1 :         data_[0] = BgpExtendedCommunityType::Experimental4ByteAs;
      31           1 :         put_value(&data_[2], 4, asn);
      32           1 :         put_value(&data_[6], SubCluster::kSize - 6, id);
      33             :     }
      34           4 :     data_[1] = BgpExtendedCommunitySubType::SubCluster;
      35           4 : }
      36             : 
      37           5 : uint32_t SubCluster::GetId() const {
      38           5 :     if (data_[0] == BgpExtendedCommunityType::Experimental) {
      39           4 :         return get_value(&data_[4], 4);
      40             :     }
      41             : 
      42           1 :     if (data_[0] == BgpExtendedCommunityType::Experimental4ByteAs) {
      43           1 :         return get_value(&data_[6], 2);
      44             :     }
      45           0 :     return 0;
      46             : }
      47             : 
      48           2 : uint32_t SubCluster::GetAsn() const {
      49           2 :     if (data_[0] == BgpExtendedCommunityType::Experimental) {
      50           1 :         return get_value(&data_[2], 2);
      51             :     }
      52             : 
      53           1 :     if (data_[0] == BgpExtendedCommunityType::Experimental4ByteAs) {
      54           1 :         return get_value(&data_[2], 4);
      55             :     }
      56           0 :     return 0;
      57             : }
      58             : 
      59          10 : string SubCluster::ToString() const {
      60             :     uint8_t data[SubCluster::kSize];
      61          10 :     copy(data_.begin(), data_.end(), &data[0]);
      62             :     char temp[50];
      63             : 
      64          10 :     if (data_[0] == BgpExtendedCommunityType::Experimental) {
      65           7 :         uint16_t asn = get_value(data + 2, 2);
      66           7 :         uint32_t id = get_value(data + 4, 4);
      67           7 :         snprintf(temp, sizeof(temp), "subcluster:%u:%u", asn, id);
      68           7 :         return string(temp);
      69             :     }
      70             : 
      71           3 :     if (data_[0] == BgpExtendedCommunityType::Experimental4ByteAs) {
      72           3 :         uint32_t asn = get_value(data + 2, 4);
      73           3 :         uint16_t id = get_value(data + 6, 2);
      74           3 :         snprintf(temp, sizeof(temp), "subcluster:%u:%u", asn, id);
      75           3 :         return string(temp);
      76             :     }
      77           0 :     return "";
      78             : }
      79             : 
      80          15 : SubCluster SubCluster::FromString(const string &str,
      81             :     boost::system::error_code *errorp) {
      82          15 :     SubCluster sc;
      83             :     uint8_t data[SubCluster::kSize];
      84             : 
      85             :     // subcluster:1:2
      86          15 :     size_t pos = str.find(':');
      87          15 :     if (pos == string::npos) {
      88           0 :         if (errorp != NULL) {
      89           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      90             :         }
      91           0 :         return SubCluster::null_sub_cluster;
      92             :     }
      93             : 
      94          15 :     string first(str.substr(0, pos));
      95          15 :     if (first != "subcluster") {
      96           0 :         if (errorp != NULL) {
      97           0 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
      98             :         }
      99           0 :         return SubCluster::null_sub_cluster;
     100             :     }
     101             : 
     102          15 :     string rest(str.substr(pos+1));
     103             : 
     104          15 :     pos = rest.find(':');
     105          15 :     if (pos == string::npos) {
     106           1 :         if (errorp != NULL) {
     107           1 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     108             :         }
     109           1 :         return SubCluster::null_sub_cluster;
     110             :     }
     111             : 
     112          14 :     boost::system::error_code ec;
     113          14 :     string second(rest.substr(0, pos));
     114          14 :     int offset = 6;
     115             :     char *endptr;
     116             :     // Get ASN
     117          14 :     uint64_t asn = strtoll(second.c_str(), &endptr, 10);
     118          14 :     if (asn == 0 || asn > 0xFFFFFFFF || *endptr != '\0') {
     119           3 :         if (errorp != NULL) {
     120           3 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     121             :         }
     122           3 :         return SubCluster::null_sub_cluster;
     123             :     }
     124             : 
     125          11 :     string third(rest.substr(pos+1));
     126          11 :     uint64_t id = strtoll(third.c_str(), &endptr, 10);
     127          11 :     if (*endptr != '\0') {
     128           1 :         if (errorp != NULL) {
     129           1 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     130             :         }
     131           1 :         return SubCluster::null_sub_cluster;
     132             :     }
     133             : 
     134             :     // Check assigned number.
     135          10 :     if ((asn > AS2_MAX && id > 0xFFFF) || id == 0 || id > 0xFFFFFFFF) {
     136           6 :         if (errorp != NULL) {
     137           6 :             *errorp = make_error_code(boost::system::errc::invalid_argument);
     138             :         }
     139           6 :         return SubCluster::null_sub_cluster;
     140             :     }
     141             : 
     142           4 :     if (asn <= AS2_MAX) {
     143           3 :         data[0] = BgpExtendedCommunityType::Experimental;
     144           3 :         put_value(&data[2], 2, asn);
     145           3 :         offset = 4;
     146             :     } else {
     147           1 :         data[0] = BgpExtendedCommunityType::Experimental4ByteAs;
     148           1 :         put_value(&data[2], 4, asn);
     149           1 :         offset = 6;
     150             :     }
     151           4 :     data[1] = BgpExtendedCommunitySubType::SubCluster;
     152           4 :     put_value(&data[offset], SubCluster::kSize - offset, id);
     153           4 :     copy(&data[0], &data[SubCluster::kSize], sc.data_.begin());
     154           4 :     return sc;
     155          15 : }

Generated by: LCOV version 1.14