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