OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
inet6vpn_route.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3  */
4 
6 
7 #include <algorithm>
8 
10 #include "bgp/inet6/inet6_route.h"
11 
12 using std::copy;
13 using std::string;
14 using std::vector;
15 
16 Inet6VpnPrefix::Inet6VpnPrefix() : prefixlen_(0) {
17 }
18 
20  Inet6VpnPrefix *prefix, uint32_t *label) {
21  size_t nlri_size = proto_prefix.prefix.size();
22  size_t expected_min_nlri_size =
24 
25  if (nlri_size < expected_min_nlri_size)
26  return -1;
27  if (nlri_size > expected_min_nlri_size + Address::kMaxV6Bytes)
28  return -1;
29 
30  size_t label_offset = 0;
31  *label = proto_prefix.ReadLabel(label_offset);
32  size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
33  prefix->rd_ = RouteDistinguisher(&proto_prefix.prefix[rd_offset]);
34 
35  size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
36  prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8;
37  Ip6Address::bytes_type bt = { { 0 } };
38  copy(proto_prefix.prefix.begin() + prefix_offset,
39  proto_prefix.prefix.end(), bt.begin());
40  prefix->addr_ = Ip6Address(bt);
41 
42  return 0;
43 }
44 
46  const BgpProtoPrefix &proto_prefix,
47  const BgpAttr *attr,
48  const Address::Family family,
49  Inet6VpnPrefix *prefix,
50  BgpAttrPtr *new_attr, uint32_t *label,
51  uint32_t *l3_label) {
52  return FromProtoPrefix(proto_prefix, prefix, label);
53 }
54 
56  BgpProtoPrefix *proto_prefix) const {
57  proto_prefix->prefix.clear();
58  size_t prefix_size = (prefixlen_ + 7) / 8;
59  size_t nlri_size =
61 
62  proto_prefix->prefix.resize(nlri_size, 0);
63  size_t label_offset = 0;
64  proto_prefix->WriteLabel(label_offset, label);
65  size_t rd_offset = label_offset + BgpProtoPrefix::kLabelSize;
67  proto_prefix->prefix.begin() + rd_offset);
68 
69  size_t prefix_offset = rd_offset + RouteDistinguisher::kSize;
70  proto_prefix->prefixlen = prefix_offset * 8 + prefixlen_;
71  const Ip6Address::bytes_type &addr_bytes = addr_.to_bytes();
72  copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
73  proto_prefix->prefix.begin() + prefix_offset);
74 }
75 
76 // RD:inet6-prefix
78  boost::system::error_code *errorp) {
79  Inet6VpnPrefix prefix;
80 
81  size_t pos = str.find(':');
82  if (pos == string::npos) {
83  if (errorp != NULL) {
84  *errorp = make_error_code(boost::system::errc::invalid_argument);
85  }
86  return prefix;
87  }
88  pos = str.find(':', (pos + 1));
89  if (pos == string::npos) {
90  if (errorp != NULL) {
91  *errorp = make_error_code(boost::system::errc::invalid_argument);
92  }
93  return prefix;
94  }
95  string rdstr = str.substr(0, pos);
96  boost::system::error_code rderr;
97  prefix.rd_ = RouteDistinguisher::FromString(rdstr, &rderr);
98  if (rderr.failed()) {
99  if (errorp != NULL) {
100  *errorp = rderr;
101  }
102  return prefix;
103  }
104 
105  string ip6pstr(str, pos + 1);
106  boost::system::error_code pfxerr = Inet6SubnetParse(ip6pstr, &prefix.addr_,
107  &prefix.prefixlen_);
108  if (errorp != NULL) {
109  *errorp = pfxerr;
110  }
111  return prefix;
112 }
113 
114 string Inet6VpnPrefix::ToString() const {
115  Inet6Prefix prefix(addr_, prefixlen_);
116  return (rd_.ToString() + ":" + prefix.ToString());
117 }
118 
119 // Check whether 'this' is more specific than rhs.
121  Inet6Prefix this_prefix(addr_, prefixlen_);
122  Inet6Prefix match_prefix(rhs.addr(), rhs.prefixlen());
123 
124  return this_prefix.IsMoreSpecific(match_prefix);
125 }
126 
127 int Inet6VpnPrefix::CompareTo(const Inet6VpnPrefix &other) const {
129  if (res != 0) {
130  return res;
131  }
132  Ip6Address laddr = addr();
133  Ip6Address raddr = other.addr();
134  if (laddr < raddr) {
135  return -1;
136  }
137  if (laddr > raddr) {
138  return 1;
139  }
140  if (prefixlen() < other.prefixlen()) {
141  return -1;
142  }
143  if (prefixlen() > other.prefixlen()) {
144  return 1;
145  }
146  return 0;
147 }
148 
150  return (rd_ == rhs.rd_ && addr_ == rhs.addr_ &&
151  prefixlen_ == rhs.prefixlen_);
152 }
153 
154 Inet6VpnRoute::Inet6VpnRoute(const Inet6VpnPrefix &prefix) : prefix_(prefix) {
155 }
156 
157 int Inet6VpnRoute::CompareTo(const Route &rhs) const {
158  const Inet6VpnRoute &other = static_cast<const Inet6VpnRoute &>(rhs);
159  return prefix_.CompareTo(other.GetPrefix());
160 }
161 
162 string Inet6VpnRoute::ToString() const {
163  string repr = prefix_.route_distinguisher().ToString() + ":";
164  repr += prefix_.addr().to_string();
165  char strplen[5];
166  snprintf(strplen, sizeof(strplen), "/%d", prefix_.prefixlen());
167  repr.append(strplen);
168 
169  return repr;
170 }
171 
172 void Inet6VpnRoute::SetKey(const DBRequestKey *reqkey) {
173  const Inet6VpnTable::RequestKey *key =
174  static_cast<const Inet6VpnTable::RequestKey *>(reqkey);
175  prefix_ = key->prefix;
176 }
177 
179  const BgpAttr*,
180  uint32_t label,
181  uint32_t l3_label) const {
182  prefix_.BuildProtoPrefix(label, prefix);
183 }
184 
185 // XXX dest_nh should have been pointer. See if can change
186 void Inet6VpnRoute::BuildBgpProtoNextHop(vector<uint8_t> &dest_nh,
187  IpAddress src_nh) const {
188  dest_nh.resize(sizeof(Ip6Address::bytes_type) + RouteDistinguisher::kSize,
189  0);
190  Ip6Address source_addr;
191  if (src_nh.is_v4()) {
192  source_addr = Ip6Address::v4_mapped(src_nh.to_v4());
193  } else if (src_nh.is_v6()) {
194  source_addr = src_nh.to_v6();
195  } else {
196  assert(0);
197  }
198 
199  Ip6Address::bytes_type addr_bytes = source_addr.to_bytes();
200  copy(addr_bytes.begin(), addr_bytes.end(),
201  dest_nh.begin() + RouteDistinguisher::kSize);
202 }
203 
207  return KeyPtr(key);
208 }
209 
210 // Check whether 'this' is more specific than rhs.
211 bool Inet6VpnRoute::IsMoreSpecific(const string &other) const {
212  boost::system::error_code ec;
213 
214  Inet6VpnPrefix other_prefix = Inet6VpnPrefix::FromString(other, &ec);
215  if (!ec) {
216  return GetPrefix().IsMoreSpecific(other_prefix);
217  }
218 
219  return false;
220 }
221 
222 // Check whether 'this' is less specific than rhs.
223 bool Inet6VpnRoute::IsLessSpecific(const string &other) const {
224  boost::system::error_code ec;
225 
226  Inet6VpnPrefix other_prefix = Inet6VpnPrefix::FromString(other, &ec);
227  if (!ec) {
228  return other_prefix.IsMoreSpecific(GetPrefix());
229  }
230 
231  return false;
232 }
virtual bool IsLessSpecific(const std::string &other) const
virtual std::string ToString() const
void WriteLabel(size_t label_offset, uint32_t label, bool is_vni=false)
std::string ToString() const
static int FromProtoPrefix(const BgpProtoPrefix &proto_prefix, Inet6VpnPrefix *prefix, uint32_t *label)
int prefixlen() const
Family
Definition: address.h:24
boost::asio::ip::address IpAddress
Definition: address.h:13
Definition: route.h:14
static RouteDistinguisher FromString(const std::string &str, boost::system::error_code *error=NULL)
Definition: rd.cc:83
uint32_t ReadLabel(size_t label_offset, bool is_vni=false) const
virtual bool IsMoreSpecific(const std::string &other) const
Inet6VpnRoute(const Inet6VpnPrefix &prefix)
static Inet6VpnPrefix FromString(const std::string &str, boost::system::error_code *errorp=NULL)
int CompareTo(const RouteDistinguisher &rhs) const
Definition: rd.cc:157
std::unique_ptr< DBRequestKey > KeyPtr
Definition: db_entry.h:25
int CompareTo(const Inet6VpnPrefix &other) const
bool operator==(const Inet6VpnPrefix &rhs) const
static const size_t kSize
Definition: rd.h:13
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
Definition: bgp_attr.h:991
virtual void BuildBgpProtoNextHop(std::vector< uint8_t > &nh, IpAddress nexthop) const
Inet6VpnPrefix prefix_
static const size_t kLabelSize
Definition: bgp_attr_base.h:98
std::vector< uint8_t > prefix
virtual void SetKey(const DBRequestKey *reqkey)
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
std::string ToString() const
Definition: inet6_route.cc:36
virtual KeyPtr GetDBRequestKey() const
static const uint8_t kMaxV6Bytes
Definition: address.h:21
Ip6Address addr_
void BuildProtoPrefix(uint32_t label, BgpProtoPrefix *prefix) const
virtual void BuildProtoPrefix(BgpProtoPrefix *prefix, const BgpAttr *attr, uint32_t label, uint32_t l3_label=0) const
const RouteDistinguisher & route_distinguisher() const
bool IsMoreSpecific(const Inet6VpnPrefix &rhs) const
std::string ToString() const
Definition: rd.cc:56
const uint8_t * GetData() const
Definition: rd.h:59
Ip6Address addr() const
const Inet6VpnPrefix & GetPrefix() const
RouteDistinguisher rd_
bool IsMoreSpecific(const Inet6Prefix &rhs) const
Definition: inet6_route.cc:69
boost::system::error_code Inet6SubnetParse(const string &str, Ip6Address *addr, int *plen)
Definition: address.cc:162
virtual int CompareTo(const Route &rhs) const