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