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