Line data Source code
1 : /*
2 : * Copyright (c) 2017 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #include "bgp/mvpn/mvpn_route.h"
7 :
8 : #include <algorithm>
9 : #include <string>
10 : #include <vector>
11 :
12 : #include "base/string_util.h"
13 : #include "bgp/mvpn/mvpn_table.h"
14 :
15 : using boost::system::errc::invalid_argument;
16 : using boost::system::error_code;
17 : using std::copy;
18 : using std::string;
19 : using std::vector;
20 :
21 : const size_t MvpnPrefix::kRdSize = RouteDistinguisher::kSize;
22 : const size_t MvpnPrefix::kAsnSize = 4;
23 : const size_t MvpnPrefix::kIp4AddrSize = Address::kMaxV4Bytes;
24 : const size_t MvpnPrefix::kIp4AddrBitSize = Address::kMaxV4PrefixLen;
25 :
26 : const size_t MvpnPrefix::kPrefixBytes = 2;
27 : const size_t MvpnPrefix::kIntraASPMSIADRouteSize = kRdSize + kIp4AddrSize;
28 : const size_t MvpnPrefix::kInterASPMSIADRouteSize = kRdSize + kAsnSize;
29 : const size_t MvpnPrefix::kSPMSIADRouteSize =
30 : kRdSize + 2 * (1 + kIp4AddrSize) + kIp4AddrSize;
31 : const size_t MvpnPrefix::kSourceActiveADRouteSize =
32 : kRdSize + 2 * (1 + kIp4AddrSize);
33 : const size_t MvpnPrefix::kSourceTreeJoinRouteSize =
34 : kRdSize + kAsnSize + 2 * (1 + kIp4AddrSize);
35 :
36 229884 : MvpnPrefix::MvpnPrefix() : type_(MvpnPrefix::Unspecified), ip_prefixlen_(0),
37 114942 : asn_(0) {
38 114942 : }
39 :
40 2 : MvpnPrefix::MvpnPrefix(uint8_t type, const RouteDistinguisher &rd,
41 2 : const uint32_t asn)
42 2 : : type_(type), rd_(rd), ip_prefixlen_(0), asn_(asn) {
43 :
44 2 : assert(type == InterASPMSIADRoute);
45 2 : }
46 :
47 3048 : MvpnPrefix::MvpnPrefix(uint8_t type, const Ip4Address &originator)
48 3048 : : type_(type), originator_(originator), ip_prefixlen_(0), asn_(0) {
49 :
50 3048 : assert(type == LeafADRoute);
51 3048 : }
52 :
53 112754 : MvpnPrefix::MvpnPrefix(uint8_t type, const RouteDistinguisher &rd,
54 112754 : const Ip4Address &originator)
55 112754 : : type_(type), rd_(rd), originator_(originator), ip_prefixlen_(0),
56 112754 : asn_(0) {
57 :
58 112754 : assert(type == IntraASPMSIADRoute);
59 112754 : }
60 :
61 89 : MvpnPrefix::MvpnPrefix(uint8_t type, const RouteDistinguisher &rd,
62 89 : const Ip4Address &group, const Ip4Address &source)
63 178 : : type_(type), rd_(rd), group_(group), source_(source),
64 178 : ip_prefixlen_(0), asn_(0) {
65 :
66 89 : assert(type == SourceActiveADRoute);
67 89 : }
68 :
69 4508 : MvpnPrefix::MvpnPrefix(uint8_t type, const RouteDistinguisher &rd,
70 : const Ip4Address &originator,
71 4508 : const Ip4Address &group, const Ip4Address &source)
72 4508 : : type_(type), rd_(rd), originator_(originator),
73 4508 : group_(group), source_(source), ip_prefixlen_(0), asn_(0) {
74 :
75 4508 : assert(type == SPMSIADRoute);
76 4508 : }
77 :
78 24404 : MvpnPrefix::MvpnPrefix(uint8_t type, const RouteDistinguisher &rd,
79 24404 : const uint32_t asn, const Ip4Address &group, const Ip4Address &source)
80 48808 : : type_(type), rd_(rd), group_(group), source_(source), ip_prefixlen_(0),
81 48808 : asn_(asn) {
82 :
83 24404 : assert((type == SharedTreeJoinRoute) || (type == SourceTreeJoinRoute));
84 24404 : }
85 :
86 7564 : Ip4Address MvpnPrefix::GetType3OriginatorFromType4Route() const {
87 7564 : size_t originator_offset = rt_key_.size() - kIp4AddrSize;
88 : return Ip4Address(get_value
89 7564 : (&rt_key_[originator_offset], kIp4AddrSize));
90 : }
91 :
92 343 : int MvpnPrefix::SpmsiAdRouteFromProtoPrefix(const BgpProtoPrefix &proto_prefix,
93 : MvpnPrefix *prefix, size_t rd_offset) {
94 343 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
95 343 : size_t source_offset = rd_offset + kRdSize;
96 343 : if (proto_prefix.prefix[source_offset++] != kIp4AddrBitSize)
97 4 : return -1;
98 339 : prefix->source_ = Ip4Address(get_value(
99 678 : &proto_prefix.prefix[source_offset], kIp4AddrSize));
100 :
101 339 : size_t group_offset = source_offset + kIp4AddrSize;
102 339 : if (proto_prefix.prefix[group_offset++] != kIp4AddrBitSize)
103 5 : return -1;
104 334 : prefix->group_ = Ip4Address(get_value(
105 668 : &proto_prefix.prefix[group_offset], kIp4AddrSize));
106 334 : size_t originator_offset = group_offset + kIp4AddrSize;
107 334 : prefix->originator_ = Ip4Address(get_value(
108 668 : &proto_prefix.prefix[originator_offset], kIp4AddrSize));
109 334 : return 0;
110 : }
111 :
112 1698 : int MvpnPrefix::FromProtoPrefix(const BgpProtoPrefix &proto_prefix,
113 : MvpnPrefix *prefix) {
114 1698 : size_t nlri_size = proto_prefix.prefix.size();
115 :
116 1698 : prefix->type_ = proto_prefix.type;
117 1698 : switch (prefix->type_) {
118 1061 : case IntraASPMSIADRoute: {
119 1061 : size_t expected_nlri_size = kIntraASPMSIADRouteSize;
120 1061 : if (nlri_size != expected_nlri_size)
121 0 : return -1;
122 1061 : size_t rd_offset = 0;
123 1061 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
124 1061 : size_t originator_offset = rd_offset + kRdSize;
125 1061 : prefix->originator_ = Ip4Address(get_value(
126 2122 : &proto_prefix.prefix[originator_offset], kIp4AddrSize));
127 1061 : break;
128 : }
129 0 : case InterASPMSIADRoute: {
130 0 : size_t expected_nlri_size = kInterASPMSIADRouteSize;
131 0 : if (nlri_size != expected_nlri_size)
132 0 : return -1;
133 0 : size_t rd_offset = 0;
134 0 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
135 0 : size_t asn_offset = rd_offset + kRdSize;
136 0 : prefix->asn_ = get_value(&proto_prefix.prefix[asn_offset], kAsnSize);
137 0 : break;
138 : }
139 156 : case SPMSIADRoute: {
140 156 : size_t expected_nlri_size = kSPMSIADRouteSize;
141 156 : if (nlri_size != expected_nlri_size)
142 3 : return -1;
143 153 : if (SpmsiAdRouteFromProtoPrefix(proto_prefix, prefix, 0))
144 8 : return -1;
145 145 : break;
146 : }
147 190 : case LeafADRoute: {
148 : size_t expected_nlri_size;
149 190 : if (proto_prefix.prefix[0] == SPMSIADRoute) {
150 190 : expected_nlri_size = kPrefixBytes + kSPMSIADRouteSize +
151 : kIp4AddrSize;
152 0 : } else if (proto_prefix.prefix[0] == InterASPMSIADRoute) {
153 0 : expected_nlri_size = kPrefixBytes + kInterASPMSIADRouteSize +
154 : kIp4AddrSize;
155 : } else {
156 0 : return -1;
157 : }
158 190 : if (nlri_size != expected_nlri_size)
159 0 : return -1;
160 190 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[kPrefixBytes]);
161 190 : if (proto_prefix.prefix[0] == SPMSIADRoute) {
162 190 : if (SpmsiAdRouteFromProtoPrefix(proto_prefix, prefix,
163 : kPrefixBytes)) {
164 1 : return -1;
165 : }
166 0 : } else if (proto_prefix.prefix[0] == InterASPMSIADRoute) {
167 0 : size_t asn_offset = kPrefixBytes + kRdSize;
168 0 : prefix->asn_ = get_value(&proto_prefix.prefix[asn_offset], kAsnSize);
169 : }
170 189 : size_t originator_offset = nlri_size - kIp4AddrSize;
171 189 : prefix->rt_key_.resize(originator_offset);
172 189 : copy(proto_prefix.prefix.begin(), proto_prefix.prefix.begin() +
173 : originator_offset, prefix->rt_key_.begin());
174 189 : prefix->originator_ = Ip4Address(get_value(
175 378 : &proto_prefix.prefix[originator_offset], kIp4AddrSize));
176 189 : break;
177 : }
178 128 : case SourceActiveADRoute: {
179 128 : size_t expected_nlri_size = kSourceActiveADRouteSize;
180 128 : if (nlri_size != expected_nlri_size)
181 0 : return -1;
182 128 : size_t rd_offset = 0;
183 128 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
184 128 : size_t source_offset = rd_offset + kRdSize;
185 128 : if (proto_prefix.prefix[source_offset++] != kIp4AddrBitSize)
186 0 : return -1;
187 128 : prefix->source_ = Ip4Address(get_value(
188 256 : &proto_prefix.prefix[source_offset], kIp4AddrSize));
189 :
190 128 : size_t group_offset = source_offset + kIp4AddrSize;
191 128 : if (proto_prefix.prefix[group_offset++] != kIp4AddrBitSize)
192 0 : return -1;
193 128 : prefix->group_ = Ip4Address(get_value(
194 256 : &proto_prefix.prefix[group_offset], kIp4AddrSize));
195 128 : break;
196 : }
197 162 : case SourceTreeJoinRoute:
198 : case SharedTreeJoinRoute: {
199 162 : size_t expected_nlri_size = kSourceTreeJoinRouteSize;
200 162 : if (nlri_size != expected_nlri_size)
201 0 : return -1;
202 162 : size_t rd_offset = 0;
203 162 : prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
204 162 : size_t asn_offset = rd_offset + kRdSize;
205 162 : uint32_t asn = get_value(&proto_prefix.prefix[asn_offset], kAsnSize);
206 162 : prefix->asn_ = asn;
207 162 : size_t source_offset = asn_offset + kAsnSize;
208 162 : if (proto_prefix.prefix[source_offset++] != kIp4AddrBitSize)
209 0 : return -1;
210 162 : prefix->source_ = Ip4Address(get_value(
211 324 : &proto_prefix.prefix[source_offset], kIp4AddrSize));
212 :
213 162 : size_t group_offset = source_offset + kIp4AddrSize;
214 162 : if (proto_prefix.prefix[group_offset++] != kIp4AddrBitSize)
215 0 : return -1;
216 162 : prefix->group_ = Ip4Address(get_value(
217 324 : &proto_prefix.prefix[group_offset], kIp4AddrSize));
218 162 : break;
219 : }
220 1 : default: {
221 1 : return -1;
222 : }
223 : }
224 :
225 1685 : return 0;
226 : }
227 :
228 1 : void MvpnPrefix::set_originator(const Ip4Address &originator) {
229 1 : originator_ = originator;
230 1 : }
231 :
232 1683 : int MvpnPrefix::FromProtoPrefix(BgpServer *server,
233 : const BgpProtoPrefix &proto_prefix,
234 : const BgpAttr *attr,
235 : const Address::Family family,
236 : MvpnPrefix *prefix,
237 : BgpAttrPtr *new_attr, uint32_t *label,
238 : uint32_t *l3_label) {
239 1683 : return FromProtoPrefix(proto_prefix, prefix);
240 : }
241 :
242 1817 : void MvpnPrefix::BuildProtoPrefix(BgpProtoPrefix *proto_prefix) const {
243 1817 : proto_prefix->type = type_;
244 1817 : proto_prefix->prefix.clear();
245 :
246 1817 : switch (type_) {
247 1186 : case IntraASPMSIADRoute: {
248 1186 : size_t nlri_size = kIntraASPMSIADRouteSize;
249 1186 : proto_prefix->prefixlen = nlri_size * 8;
250 1186 : proto_prefix->prefix.resize(nlri_size, 0);
251 :
252 1186 : size_t rd_offset = 0;
253 1186 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
254 1186 : proto_prefix->prefix.begin() + rd_offset);
255 1186 : size_t originator_offset = rd_offset + kRdSize;
256 1186 : const Ip4Address::bytes_type &source_bytes = originator_.to_bytes();
257 1186 : copy(source_bytes.begin(), source_bytes.begin() + kIp4AddrSize,
258 1186 : proto_prefix->prefix.begin() + originator_offset);
259 1186 : break;
260 : }
261 0 : case InterASPMSIADRoute: {
262 0 : size_t nlri_size = kInterASPMSIADRouteSize;
263 0 : proto_prefix->prefixlen = nlri_size * 8;
264 0 : proto_prefix->prefix.resize(nlri_size, 0);
265 :
266 0 : size_t rd_offset = 0;
267 0 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
268 0 : proto_prefix->prefix.begin() + rd_offset);
269 0 : size_t asn_offset = rd_offset + kRdSize;
270 0 : put_value(&proto_prefix->prefix[asn_offset], kAsnSize, asn_);
271 0 : break;
272 : }
273 151 : case SPMSIADRoute: {
274 151 : size_t nlri_size = kSPMSIADRouteSize;
275 151 : proto_prefix->prefixlen = nlri_size * 8;
276 151 : proto_prefix->prefix.resize(nlri_size, 0);
277 :
278 151 : size_t rd_offset = 0;
279 151 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
280 151 : proto_prefix->prefix.begin() + rd_offset);
281 151 : size_t source_offset = rd_offset + kRdSize;
282 151 : proto_prefix->prefix[source_offset++] = kIp4AddrBitSize;
283 151 : const Ip4Address::bytes_type &source_bytes = source_.to_bytes();
284 151 : copy(source_bytes.begin(), source_bytes.begin() + kIp4AddrSize,
285 151 : proto_prefix->prefix.begin() + source_offset);
286 :
287 151 : size_t group_offset = source_offset + kIp4AddrSize;
288 151 : proto_prefix->prefix[group_offset++] = kIp4AddrBitSize;
289 151 : const Ip4Address::bytes_type &group_bytes = group_.to_bytes();
290 151 : copy(group_bytes.begin(), group_bytes.begin() + kIp4AddrSize,
291 151 : proto_prefix->prefix.begin() + group_offset);
292 :
293 151 : size_t originator_offset = group_offset + kIp4AddrSize;
294 151 : const Ip4Address::bytes_type &originator_bytes = originator_.to_bytes();
295 151 : copy(originator_bytes.begin(), originator_bytes.begin() +
296 151 : kIp4AddrSize, proto_prefix->prefix.begin() +
297 : originator_offset);
298 151 : break;
299 : }
300 190 : case LeafADRoute: {
301 190 : size_t keySize = rt_key_.size();
302 190 : size_t nlri_size = keySize + kIp4AddrSize;
303 190 : proto_prefix->prefixlen = nlri_size * 8;
304 190 : proto_prefix->prefix.resize(nlri_size, 0);
305 :
306 190 : copy(rt_key_.begin(), rt_key_.begin() + keySize,
307 : proto_prefix->prefix.begin());
308 :
309 190 : const Ip4Address::bytes_type &originator_bytes = originator_.to_bytes();
310 190 : copy(originator_bytes.begin(), originator_bytes.begin() +
311 190 : kIp4AddrSize, proto_prefix->prefix.begin() + keySize);
312 190 : break;
313 : }
314 128 : case SourceActiveADRoute: {
315 128 : size_t nlri_size = kSourceActiveADRouteSize;
316 128 : proto_prefix->prefixlen = nlri_size * 8;
317 128 : proto_prefix->prefix.resize(nlri_size, 0);
318 :
319 128 : size_t rd_offset = 0;
320 128 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
321 128 : proto_prefix->prefix.begin() + rd_offset);
322 128 : size_t source_offset = rd_offset + kRdSize;
323 128 : proto_prefix->prefix[source_offset++] = kIp4AddrBitSize;
324 128 : const Ip4Address::bytes_type &source_bytes = source_.to_bytes();
325 128 : copy(source_bytes.begin(), source_bytes.begin() + kIp4AddrSize,
326 128 : proto_prefix->prefix.begin() + source_offset);
327 :
328 128 : size_t group_offset = source_offset + kIp4AddrSize;
329 128 : proto_prefix->prefix[group_offset++] = kIp4AddrBitSize;
330 128 : const Ip4Address::bytes_type &group_bytes = group_.to_bytes();
331 128 : copy(group_bytes.begin(), group_bytes.begin() + kIp4AddrSize,
332 128 : proto_prefix->prefix.begin() + group_offset);
333 128 : break;
334 : }
335 162 : case SourceTreeJoinRoute:
336 : case SharedTreeJoinRoute: {
337 162 : size_t nlri_size = kSourceTreeJoinRouteSize;
338 162 : proto_prefix->prefixlen = nlri_size * 8;
339 162 : proto_prefix->prefix.resize(nlri_size, 0);
340 :
341 162 : size_t rd_offset = 0;
342 162 : copy(rd_.GetData(), rd_.GetData() + kRdSize,
343 162 : proto_prefix->prefix.begin() + rd_offset);
344 162 : size_t asn_offset = rd_offset + kRdSize;
345 162 : put_value(&proto_prefix->prefix[asn_offset], kAsnSize, asn_);
346 162 : size_t source_offset = asn_offset + kAsnSize;
347 162 : proto_prefix->prefix[source_offset++] = kIp4AddrBitSize;
348 162 : const Ip4Address::bytes_type &source_bytes = source_.to_bytes();
349 162 : copy(source_bytes.begin(), source_bytes.begin() + kIp4AddrSize,
350 162 : proto_prefix->prefix.begin() + source_offset);
351 :
352 162 : size_t group_offset = source_offset + kIp4AddrSize;
353 162 : proto_prefix->prefix[group_offset++] = kIp4AddrBitSize;
354 162 : const Ip4Address::bytes_type &group_bytes = group_.to_bytes();
355 162 : copy(group_bytes.begin(), group_bytes.begin() + kIp4AddrSize,
356 162 : proto_prefix->prefix.begin() + group_offset);
357 162 : break;
358 : }
359 0 : default: {
360 0 : assert(false);
361 : break;
362 : }
363 : }
364 1817 : }
365 :
366 46822 : bool MvpnPrefix::GetTypeFromString(MvpnPrefix *prefix, const string &str,
367 : error_code *errorp, size_t *pos1) {
368 46822 : *pos1 = str.find('-');
369 46822 : if (*pos1 == string::npos) {
370 17 : if (errorp != NULL) {
371 17 : *errorp = make_error_code(invalid_argument);
372 : }
373 17 : return false;
374 : }
375 46805 : string temp_str = str.substr(0, *pos1);
376 46805 : stringToInteger(temp_str, prefix->type_);
377 46805 : if (!IsValid(prefix->type_)) {
378 1 : if (errorp != NULL) {
379 1 : *errorp = make_error_code(invalid_argument);
380 : }
381 1 : return false;
382 : }
383 46804 : return true;
384 46805 : }
385 :
386 42674 : bool MvpnPrefix::GetRDFromString(MvpnPrefix *prefix, const string &str,
387 : size_t pos1, size_t *pos2, error_code *errorp) {
388 42674 : *pos2 = str.find(',', pos1 + 1);
389 42674 : if (*pos2 == string::npos) {
390 4 : if (errorp != NULL) {
391 4 : *errorp = make_error_code(invalid_argument);
392 : }
393 4 : return false;
394 : }
395 42670 : string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
396 42670 : error_code rd_err;
397 42670 : prefix->rd_ = RouteDistinguisher::FromString(temp_str, &rd_err);
398 42670 : if (rd_err.failed()) {
399 4 : if (errorp != NULL) {
400 4 : *errorp = rd_err;
401 : }
402 4 : return false;
403 : }
404 42666 : return true;
405 42670 : }
406 :
407 15014 : bool MvpnPrefix::GetOriginatorFromString(MvpnPrefix *prefix,
408 : const string &str, size_t pos1, error_code *errorp) {
409 15014 : string temp_str = str.substr(pos1 + 1, string::npos);
410 15014 : error_code originator_err;
411 15014 : prefix->originator_ = Ip4Address::from_string(temp_str, originator_err);
412 15014 : if (originator_err.failed()) {
413 3 : if (errorp != NULL) {
414 3 : *errorp = originator_err;
415 : }
416 3 : return false;
417 : }
418 15011 : return true;
419 15014 : }
420 :
421 42018 : bool MvpnPrefix::GetSourceFromString(MvpnPrefix *prefix, const string &str,
422 : size_t pos1, size_t *pos2, error_code *errorp) {
423 42018 : *pos2 = str.find(',', pos1 + 1);
424 42018 : if (*pos2 == string::npos) {
425 0 : if (errorp != NULL) {
426 0 : *errorp = make_error_code(invalid_argument);
427 : }
428 0 : return false;
429 : }
430 42018 : string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
431 42018 : error_code source_err;
432 42018 : prefix->source_ = Ip4Address::from_string(temp_str, source_err);
433 42018 : if (source_err.failed()) {
434 2 : if (errorp != NULL) {
435 2 : *errorp = source_err;
436 : }
437 2 : return false;
438 : }
439 42016 : return true;
440 42018 : }
441 :
442 42016 : bool MvpnPrefix::GetGroupFromString(MvpnPrefix *prefix, const string &str,
443 : size_t pos1, size_t *pos2, error_code *errorp,
444 : bool last) {
445 42016 : *pos2 = str.find(',', pos1 + 1);
446 42016 : if (!last && *pos2 == string::npos) {
447 1 : if (errorp != NULL) {
448 1 : *errorp = make_error_code(invalid_argument);
449 : }
450 1 : return false;
451 : }
452 42015 : string temp_str;
453 42015 : if (last)
454 27648 : temp_str = str.substr(pos1 + 1, string::npos);
455 : else
456 14367 : temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
457 42015 : error_code group_err;
458 42015 : prefix->group_ = Ip4Address::from_string(temp_str, group_err);
459 42015 : if (group_err.failed()) {
460 2 : if (errorp != NULL) {
461 2 : *errorp = group_err;
462 : }
463 2 : return false;
464 : }
465 42013 : return true;
466 42015 : }
467 :
468 20596 : bool MvpnPrefix::GetAsnFromString(MvpnPrefix *prefix, const string &str,
469 : size_t pos1, size_t *pos2, error_code *errorp) {
470 20596 : *pos2 = str.find(',', pos1 + 1);
471 20596 : if (*pos2 == string::npos) {
472 0 : if (errorp != NULL) {
473 0 : *errorp = make_error_code(invalid_argument);
474 : }
475 0 : return false;
476 : }
477 20596 : string temp_str = str.substr(pos1 + 1, *pos2 - pos1 - 1);
478 20596 : if (!stringToInteger(temp_str, prefix->asn_)) {
479 0 : return false;
480 : }
481 20596 : return true;
482 20596 : }
483 :
484 42693 : MvpnPrefix MvpnPrefix::FromString(const string &str, error_code *errorp) {
485 42693 : MvpnPrefix prefix, null_prefix;
486 42693 : string temp_str;
487 :
488 : // Look for Type.
489 : size_t pos1;
490 42693 : if (!GetTypeFromString(&prefix, str, errorp, &pos1))
491 17 : return null_prefix;
492 :
493 42676 : switch (prefix.type_) {
494 644 : case IntraASPMSIADRoute: {
495 : // Look for RD.
496 : size_t pos2;
497 644 : if (!GetRDFromString(&prefix, str, pos1, &pos2, errorp))
498 3 : return null_prefix;
499 : // rest is originator
500 642 : if (!GetOriginatorFromString(&prefix, str, pos2, errorp))
501 1 : return null_prefix;
502 641 : break;
503 : }
504 8 : case InterASPMSIADRoute: {
505 : // Look for RD.
506 : size_t pos2;
507 8 : if (!GetRDFromString(&prefix, str, pos1, &pos2, errorp))
508 3 : return null_prefix;
509 : // rest is asn
510 5 : temp_str = str.substr(pos2 + 1, string::npos);
511 5 : if (!stringToInteger(temp_str, prefix.asn_)) {
512 0 : return null_prefix;
513 : }
514 5 : break;
515 : }
516 10246 : case SPMSIADRoute: {
517 : // Look for RD.
518 : size_t pos2;
519 10246 : if (!GetRDFromString(&prefix, str, pos1, &pos2, errorp))
520 5 : return null_prefix;
521 : // Look for source.
522 : size_t pos3;
523 10244 : if (!GetSourceFromString(&prefix, str, pos2, &pos3, errorp))
524 0 : return null_prefix;
525 :
526 : // Look for group.
527 : size_t pos4;
528 10244 : if (!GetGroupFromString(&prefix, str, pos3, &pos4, errorp))
529 2 : return null_prefix;
530 :
531 : // rest is originator
532 10242 : if (!GetOriginatorFromString(&prefix, str, pos4, errorp))
533 1 : return null_prefix;
534 10241 : break;
535 : }
536 4130 : case LeafADRoute: {
537 : // First get the originator from the end
538 4130 : size_t pos_last = str.find_last_of(',');
539 4130 : if (pos_last == string::npos) {
540 0 : if (errorp != NULL) {
541 0 : *errorp = make_error_code(invalid_argument);
542 : }
543 6 : return null_prefix;
544 : }
545 4130 : if (!GetOriginatorFromString(&prefix, str, pos_last, errorp))
546 1 : return null_prefix;
547 4129 : temp_str = str.substr(pos1 + 1, string::npos);
548 : // Look for type.
549 : size_t pos2;
550 4129 : if (!GetTypeFromString(&prefix, temp_str, errorp, &pos2))
551 1 : return null_prefix;
552 4128 : uint8_t src_rt_type = prefix.type_;
553 4128 : prefix.type_ = LeafADRoute;
554 4128 : size_t key_size = 0;
555 4128 : if (src_rt_type == InterASPMSIADRoute) {
556 1 : key_size = kPrefixBytes + kInterASPMSIADRouteSize;
557 1 : prefix.rt_key_.resize(key_size);
558 1 : prefix.rt_key_[0] = InterASPMSIADRoute;
559 1 : prefix.rt_key_[1] = kInterASPMSIADRouteSize;
560 4127 : } else if (src_rt_type == SPMSIADRoute) {
561 4127 : key_size = kPrefixBytes + kSPMSIADRouteSize;
562 4127 : prefix.rt_key_.resize(key_size);
563 4127 : prefix.rt_key_[0] = SPMSIADRoute;
564 4127 : prefix.rt_key_[1] = kSPMSIADRouteSize;
565 : }
566 4128 : size_t key_offset = 2;
567 : // Look for RD.
568 : size_t pos3;
569 4128 : pos2 = pos1 + 1 + pos2;
570 4128 : if (!GetRDFromString(&prefix, str, pos2, &pos3, errorp))
571 1 : return null_prefix;
572 4127 : copy(prefix.rd_.GetData(), prefix.rd_.GetData() + kRdSize,
573 4127 : prefix.rt_key_.begin() + key_offset);
574 4127 : key_offset += kRdSize;
575 : // check if source ip or asn
576 : size_t pos4;
577 4127 : if (src_rt_type == InterASPMSIADRoute) {
578 : // check for asn
579 1 : if (!GetAsnFromString(&prefix, str, pos3, &pos4, errorp))
580 0 : return null_prefix;
581 1 : size_t asn_size = sizeof(prefix.asn_);
582 1 : put_value(&prefix.rt_key_[key_offset], asn_size, prefix.asn_);
583 4124 : break;
584 : }
585 4126 : if (!GetSourceFromString(&prefix, str, pos3, &pos4, errorp))
586 2 : return null_prefix;
587 4124 : const Ip4Address::bytes_type &source_bytes = prefix.source_.to_bytes();
588 4124 : prefix.rt_key_[key_offset++] = kIp4AddrBitSize;
589 4124 : copy(source_bytes.begin(), source_bytes.begin() +
590 4124 : kIp4AddrSize, prefix.rt_key_.begin() + key_offset);
591 4124 : key_offset += kIp4AddrSize;
592 :
593 : // Look for group.
594 : size_t pos5;
595 4124 : if (!GetGroupFromString(&prefix, str, pos4, &pos5, errorp))
596 1 : return null_prefix;
597 4123 : const Ip4Address::bytes_type &group_bytes = prefix.group_.to_bytes();
598 4123 : prefix.rt_key_[key_offset++] = kIp4AddrBitSize;
599 4123 : copy(group_bytes.begin(), group_bytes.begin() +
600 4123 : kIp4AddrSize, prefix.rt_key_.begin() + key_offset);
601 4123 : key_offset += kIp4AddrSize;
602 :
603 : // Look for originator of rt_key and ignore it.
604 4123 : size_t pos6 = str.find(',', pos5 + 1);
605 4123 : if (pos6 == string::npos) {
606 0 : if (errorp != NULL) {
607 0 : *errorp = make_error_code(invalid_argument);
608 : }
609 0 : return null_prefix;
610 : }
611 4123 : temp_str = str.substr(pos5 + 1, pos6 - pos5 - 1);
612 4123 : error_code originator_err;
613 4123 : Ip4Address ip = Ip4Address::from_string(temp_str, originator_err);
614 4123 : if (originator_err.failed()) {
615 0 : if (errorp != NULL) {
616 0 : *errorp = originator_err;
617 : }
618 0 : return null_prefix;
619 : }
620 4123 : const Ip4Address::bytes_type &originator_bytes = ip.to_bytes();
621 4123 : copy(originator_bytes.begin(), originator_bytes.begin() +
622 4123 : kIp4AddrSize, prefix.rt_key_.begin() + key_offset);
623 4123 : break;
624 : }
625 7053 : case SourceActiveADRoute: {
626 : // Look for RD.
627 : size_t pos2;
628 7053 : if (!GetRDFromString(&prefix, str, pos1, &pos2, errorp))
629 0 : return null_prefix;
630 : // Look for source.
631 : size_t pos3;
632 7053 : if (!GetSourceFromString(&prefix, str, pos2, &pos3, errorp))
633 0 : return null_prefix;
634 :
635 : // rest is group.
636 : size_t pos4;
637 7053 : if (!GetGroupFromString(&prefix, str, pos3, &pos4, errorp, true))
638 0 : return null_prefix;
639 7053 : break;
640 : }
641 20595 : case SharedTreeJoinRoute:
642 : case SourceTreeJoinRoute: {
643 : // Look for RD.
644 : size_t pos2;
645 20595 : if (!GetRDFromString(&prefix, str, pos1, &pos2, errorp))
646 0 : return null_prefix;
647 : // Look for asn
648 : size_t pos3;
649 20595 : if (!GetAsnFromString(&prefix, str, pos2, &pos3, errorp))
650 0 : return null_prefix;
651 : // Look for source.
652 : size_t pos4;
653 20595 : if (!GetSourceFromString(&prefix, str, pos3, &pos4, errorp))
654 0 : return null_prefix;
655 :
656 : // rest is group.
657 : size_t pos5;
658 20595 : if (!GetGroupFromString(&prefix, str, pos4, &pos5, errorp, true))
659 0 : return null_prefix;
660 20595 : break;
661 : }
662 : }
663 :
664 42659 : return prefix;
665 42693 : }
666 :
667 990416 : string MvpnPrefix::ToString() const {
668 990416 : string repr = integerToString(type_);
669 990416 : switch (type_) {
670 550371 : case IntraASPMSIADRoute:
671 550371 : repr += "-" + rd_.ToString();
672 550371 : repr += "," + originator_.to_string();
673 550371 : break;
674 11 : case InterASPMSIADRoute:
675 11 : repr += "-" + rd_.ToString();
676 11 : repr += "," + integerToString(asn_);
677 11 : break;
678 136988 : case SPMSIADRoute:
679 136988 : repr += "-" + rd_.ToString();
680 136988 : repr += "," + source_.to_string();
681 136988 : repr += "," + group_.to_string();
682 136988 : repr += "," + originator_.to_string();
683 136988 : break;
684 30459 : case LeafADRoute: {
685 30459 : size_t key_offset = kPrefixBytes;
686 30459 : RouteDistinguisher rd(&rt_key_[key_offset]);
687 30459 : uint8_t rt_type = rt_key_[0];
688 30459 : if (rt_type == SPMSIADRoute) {
689 30458 : repr += "-3";
690 30458 : repr += "-" + rd.ToString();
691 30458 : key_offset += kRdSize + 1;
692 : Ip4Address ip = Ip4Address(get_value
693 30458 : (&rt_key_[key_offset], kIp4AddrSize));
694 30458 : repr += "," + ip.to_string();
695 30457 : key_offset += kIp4AddrSize + 1;
696 30457 : ip = Ip4Address(get_value (&rt_key_[key_offset], kIp4AddrSize));
697 30457 : key_offset += kIp4AddrSize;
698 30457 : repr += "," + ip.to_string();
699 30457 : ip = Ip4Address(get_value (&rt_key_[key_offset], kIp4AddrSize));
700 30457 : repr += "," + ip.to_string();
701 1 : } else if (rt_type == InterASPMSIADRoute) {
702 1 : repr += "-2";
703 1 : repr += "-" + rd.ToString();
704 1 : key_offset += kRdSize;
705 1 : uint32_t asn = get_value(&rt_key_[key_offset], kAsnSize);
706 1 : repr += "," + integerToString(asn);
707 : }
708 30459 : repr += "," + originator_.to_string();
709 30459 : break;
710 : }
711 128668 : case SourceActiveADRoute:
712 128668 : repr += "-" + rd_.ToString();
713 128668 : repr += "," + source_.to_string();
714 128668 : repr += "," + group_.to_string();
715 128668 : break;
716 143919 : case SharedTreeJoinRoute:
717 : case SourceTreeJoinRoute:
718 143919 : repr += "-" + rd_.ToString();
719 143919 : repr += "," + integerToString(asn_);
720 143919 : repr += "," + source_.to_string();
721 143919 : repr += "," + group_.to_string();
722 143919 : break;
723 : }
724 990416 : return repr;
725 0 : }
726 :
727 2857781 : int MvpnPrefix::CompareTo(const MvpnPrefix &rhs) const {
728 2857781 : KEY_COMPARE(type_, rhs.type_);
729 :
730 2147169 : switch (type_) {
731 1489668 : case IntraASPMSIADRoute:
732 1489668 : KEY_COMPARE(rd_, rhs.rd_);
733 571292 : KEY_COMPARE(originator_, rhs.originator_);
734 571190 : break;
735 8 : case InterASPMSIADRoute:
736 8 : KEY_COMPARE(rd_, rhs.rd_);
737 8 : KEY_COMPARE(asn_, rhs.asn_);
738 8 : break;
739 230698 : case SPMSIADRoute:
740 230698 : KEY_COMPARE(rd_, rhs.rd_);
741 204046 : KEY_COMPARE(source_, rhs.source_);
742 204046 : KEY_COMPARE(group_, rhs.group_);
743 98190 : KEY_COMPARE(originator_, rhs.originator_);
744 98001 : break;
745 66409 : case LeafADRoute:
746 66409 : KEY_COMPARE(rt_key_, rhs.rt_key_);
747 30559 : KEY_COMPARE(originator_, rhs.originator_);
748 30560 : break;
749 193820 : case SourceActiveADRoute:
750 193820 : KEY_COMPARE(rd_, rhs.rd_);
751 168725 : KEY_COMPARE(source_, rhs.source_);
752 168712 : KEY_COMPARE(group_, rhs.group_);
753 101016 : break;
754 166572 : case SourceTreeJoinRoute:
755 : case SharedTreeJoinRoute:
756 166572 : KEY_COMPARE(rd_, rhs.rd_);
757 156833 : KEY_COMPARE(asn_, rhs.asn_);
758 156833 : KEY_COMPARE(source_, rhs.source_);
759 156806 : KEY_COMPARE(group_, rhs.group_);
760 97162 : break;
761 0 : default:
762 0 : break;
763 : }
764 897931 : return 0;
765 : }
766 :
767 : // Populate LeafADRoute(Type4) rt_key_ from SPMSIADRoute(Type3)
768 3048 : void MvpnPrefix::SetLeafADPrefixFromSPMSIPrefix(const MvpnPrefix &prefix) {
769 3048 : assert(prefix.type() == SPMSIADRoute);
770 :
771 3048 : size_t key_size = kPrefixBytes + kSPMSIADRouteSize;
772 3048 : rt_key_.resize(key_size);
773 3048 : size_t key_offset = 0;
774 3048 : rt_key_[key_offset++] = SPMSIADRoute;
775 3048 : rt_key_[key_offset++] = (uint8_t)kSPMSIADRouteSize;
776 6096 : copy(prefix.route_distinguisher().GetData(),
777 3048 : prefix.route_distinguisher().GetData() + kRdSize,
778 3048 : rt_key_.begin() + key_offset);
779 3048 : size_t source_offset = key_offset+ kRdSize;
780 3048 : rt_key_[source_offset++] = kIp4AddrBitSize;
781 3048 : RouteDistinguisher rd(prefix.route_distinguisher().GetData());
782 3048 : rd_ = rd;
783 3048 : const Ip4Address::bytes_type &source_bytes = prefix.source().to_bytes();
784 3048 : copy(source_bytes.begin(), source_bytes.begin() + kIp4AddrSize,
785 3048 : rt_key_.begin() + source_offset);
786 3048 : size_t group_offset = source_offset + kIp4AddrSize;
787 3048 : source_ = Ip4Address(prefix.source().to_ulong());
788 3048 : rt_key_[group_offset++] = kIp4AddrBitSize;
789 3048 : const Ip4Address::bytes_type &group_bytes = prefix.group().to_bytes();
790 3048 : copy(group_bytes.begin(), group_bytes.begin() +
791 3048 : kIp4AddrSize, rt_key_.begin() + group_offset);
792 3048 : size_t originator_offset = group_offset + kIp4AddrSize;
793 3048 : group_ = Ip4Address(prefix.group().to_ulong());
794 : const Ip4Address::bytes_type &originator_bytes =
795 3048 : prefix.originator().to_bytes();
796 3048 : copy(originator_bytes.begin(), originator_bytes.begin() +
797 3048 : kIp4AddrSize, rt_key_.begin() + originator_offset);
798 3048 : }
799 :
800 3773 : void MvpnPrefix::SetSPMSIPrefixFromLeafADPrefix(const MvpnPrefix &prefix) {
801 3773 : assert(prefix.type() == LeafADRoute);
802 3773 : RouteDistinguisher rd(prefix.route_distinguisher().GetData());
803 3773 : rd_ = rd;
804 3773 : source_ = Ip4Address(prefix.source().to_ulong());
805 3773 : group_ = Ip4Address(prefix.group().to_ulong());
806 3773 : originator_ = prefix.GetType3OriginatorFromType4Route();
807 3773 : type_ = SPMSIADRoute;
808 3773 : }
809 :
810 356 : string MvpnPrefix::ToXmppIdString() const {
811 356 : string repr = rd_.ToString();
812 356 : repr += ":" + group_.to_string();
813 356 : repr += "," + source_.to_string();
814 356 : return repr;
815 0 : }
816 :
817 46818 : bool MvpnPrefix::IsValid(uint8_t type) {
818 46818 : return (type > Unspecified) && (type <= SourceTreeJoinRoute);
819 : }
820 :
821 4122 : bool MvpnPrefix::operator==(const MvpnPrefix &rhs) const {
822 : return (
823 8244 : type_ == rhs.type_ &&
824 8244 : rd_ == rhs.rd_ &&
825 8244 : originator_ == rhs.originator_ &&
826 12366 : group_ == rhs.group_ &&
827 8244 : source_ == rhs.source_);
828 : }
829 :
830 630569 : MvpnRoute::MvpnRoute(const MvpnPrefix &prefix) : prefix_(prefix) {
831 630567 : }
832 :
833 2857780 : int MvpnRoute::CompareTo(const Route &rhs) const {
834 2857780 : const MvpnRoute &other = static_cast<const MvpnRoute &>(rhs);
835 2857780 : return prefix_.CompareTo(other.prefix_);
836 : KEY_COMPARE(prefix_.type(), other.prefix_.type());
837 : KEY_COMPARE(
838 : prefix_.route_distinguisher(), other.prefix_.route_distinguisher());
839 : KEY_COMPARE(prefix_.originator(), other.prefix_.originator());
840 : KEY_COMPARE(prefix_.source(), other.prefix_.source());
841 : KEY_COMPARE(prefix_.group(), other.prefix_.group());
842 : KEY_COMPARE(prefix_.asn(), other.prefix_.asn());
843 : return 0;
844 : }
845 :
846 982166 : string MvpnRoute::ToString() const {
847 982166 : return prefix_.ToString();
848 : }
849 :
850 196939 : string MvpnRoute::ToXmppIdString() const {
851 196939 : if (xmpp_id_str_.empty())
852 356 : xmpp_id_str_ = prefix_.ToXmppIdString();
853 196939 : return xmpp_id_str_;
854 : }
855 :
856 1 : bool MvpnRoute::IsValid() const {
857 1 : if (!BgpRoute::IsValid())
858 1 : return false;
859 :
860 0 : return true;
861 : }
862 :
863 1 : void MvpnRoute::SetKey(const DBRequestKey *reqkey) {
864 1 : const MvpnTable::RequestKey *key =
865 : static_cast<const MvpnTable::RequestKey *>(reqkey);
866 1 : prefix_ = key->prefix;
867 1 : }
868 :
869 1817 : void MvpnRoute::BuildProtoPrefix(BgpProtoPrefix *prefix,
870 : const BgpAttr *attr, uint32_t label, uint32_t l3_label) const {
871 1817 : prefix_.BuildProtoPrefix(prefix);
872 1817 : }
873 :
874 970 : void MvpnRoute::BuildBgpProtoNextHop(
875 : vector<uint8_t> &nh, IpAddress nexthop) const {
876 970 : nh.resize(4);
877 970 : const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes();
878 970 : copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
879 970 : }
880 :
881 73973 : DBEntryBase::KeyPtr MvpnRoute::GetDBRequestKey() const {
882 : MvpnTable::RequestKey *key;
883 73973 : key = new MvpnTable::RequestKey(GetPrefix(), NULL);
884 73973 : return KeyPtr(key);
885 : }
886 :
887 332750 : const string MvpnPrefix::GetType() const {
888 332750 : switch (type_) {
889 0 : case Unspecified:
890 0 : return "Unspecified";
891 124508 : case IntraASPMSIADRoute:
892 124508 : return "IntraASPMSIADRoute";
893 2 : case InterASPMSIADRoute:
894 2 : return "InterASPMSIADRoute";
895 55356 : case SPMSIADRoute:
896 55356 : return "SPMSIADRoute";
897 8192 : case LeafADRoute:
898 8192 : return "LeafADRoute";
899 30688 : case SourceActiveADRoute:
900 30688 : return "SourceActiveADRoute";
901 0 : case SharedTreeJoinRoute:
902 0 : return "SharedTreeJoinRoute";
903 114004 : case SourceTreeJoinRoute:
904 114004 : return "SourceTreeJoinRoute";
905 : }
906 0 : return "";
907 : }
908 :
909 332750 : const string MvpnRoute::GetType() const {
910 332750 : return GetPrefix().GetType();
911 : }
|