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