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

Generated by: LCOV version 1.14