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