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 : }
|