OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
inet_route.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "bgp/inet/inet_route.h"
6 
7 #include <algorithm>
8 
9 #include "bgp/inet/inet_table.h"
10 
11 using std::copy;
12 using std::string;
13 using std::vector;
14 
16  Ip4Prefix *prefix) {
17  if (proto_prefix.prefix.size() > Address::kMaxV4Bytes)
18  return -1;
19  prefix->prefixlen_ = proto_prefix.prefixlen;
20  Ip4Address::bytes_type bt = { { 0 } };
21  copy(proto_prefix.prefix.begin(), proto_prefix.prefix.end(), bt.begin());
22  prefix->ip4_addr_ = Ip4Address(bt);
23 
24  return 0;
25 }
26 
28  const BgpProtoPrefix &proto_prefix,
29  const BgpAttr *attr,
30  const Address::Family family,
31  Ip4Prefix *prefix,
32  BgpAttrPtr *new_attr, uint32_t *label,
33  uint32_t *l3_label) {
34  if (family == Address::INET) {
35  return FromProtoPrefix(proto_prefix, prefix);
36  }
37  size_t nlri_size = proto_prefix.prefix.size();
38  size_t expected_min_nlri_size =
40 
41  if (nlri_size < expected_min_nlri_size)
42  return -1;
43  if (nlri_size > expected_min_nlri_size + Address::kMaxV4Bytes)
44  return -1;
45 
46  size_t label_offset = 0;
47  *label = proto_prefix.ReadLabel(label_offset);
48  size_t prefix_offset = label_offset + BgpProtoPrefix::kLabelSize;
49  prefix->prefixlen_ = proto_prefix.prefixlen - prefix_offset * 8;
50  Ip4Address::bytes_type bt = { { 0 } };
51  copy(proto_prefix.prefix.begin() + prefix_offset,
52  proto_prefix.prefix.end(), bt.begin());
53  prefix->ip4_addr_ = Ip4Address(bt);
54 
55  return 0;
56 }
57 
58 
59 
60 string Ip4Prefix::ToString() const {
61  string repr(ip4_addr().to_string());
62  char strplen[4];
63  snprintf(strplen, sizeof(strplen), "/%d", prefixlen());
64  repr.append(strplen);
65  return repr;
66 }
67 
68 int Ip4Prefix::CompareTo(const Ip4Prefix &rhs) const {
69  if (ip4_addr_ < rhs.ip4_addr_) {
70  return -1;
71  }
72  if (ip4_addr_ > rhs.ip4_addr_) {
73  return 1;
74  }
75  if (prefixlen_ < rhs.prefixlen_) {
76  return -1;
77  }
78  if (prefixlen_ > rhs.prefixlen_) {
79  return 1;
80  }
81  return 0;
82 }
83 
84 Ip4Prefix Ip4Prefix::FromString(const string &str,
85  boost::system::error_code *errorp) {
86  Ip4Prefix prefix;
87  boost::system::error_code pfxerr = Ip4SubnetParse(str, &prefix.ip4_addr_,
88  &prefix.prefixlen_);
89  if (errorp != NULL) {
90  *errorp = pfxerr;
91  }
92  return prefix;
93 }
94 
95 // Check whether 'this' is more specific than rhs.
96 bool Ip4Prefix::IsMoreSpecific(const Ip4Prefix &rhs) const {
97  // My prefixlen must be longer in order to be more specific.
98  if (prefixlen_ < rhs.prefixlen()) return false;
99 
100  uint32_t mask = 0;
101  if (rhs.prefixlen())
102  mask = ((uint32_t) ~0) << (Address::kMaxV4PrefixLen - rhs.prefixlen());
103  return (ip4_addr_.to_ulong() & mask) ==
104  (rhs.ip4_addr().to_ulong() & mask);
105 }
106 
108  : prefix_(prefix),
109  prefix_str_(prefix.ToString()) {
110 }
111 
112 int InetRoute::CompareTo(const Route &rhs) const {
113  const InetRoute &rt_other = static_cast<const InetRoute &>(rhs);
114  return prefix_.CompareTo(rt_other.prefix_);
115 }
116 
117 // Check whether 'this' is more specific than rhs.
118 bool InetRoute::IsMoreSpecific(const string &match) const {
119  boost::system::error_code ec;
120 
121  Ip4Prefix prefix = Ip4Prefix::FromString(match, &ec);
122  if (!ec) {
123  return GetPrefix().IsMoreSpecific(prefix);
124  }
125 
126  return false;
127 }
128 
129 // Check whether 'this' is less specific than rhs.
130 bool InetRoute::IsLessSpecific(const string &match) const {
131  boost::system::error_code ec;
132 
133  Ip4Prefix prefix = Ip4Prefix::FromString(match, &ec);
134  if (!ec) {
135  return prefix.IsMoreSpecific(GetPrefix());
136  }
137 
138  return false;
139 }
140 
143  return KeyPtr(key);
144 }
145 
146 void InetRoute::SetKey(const DBRequestKey *reqkey) {
147  const InetTable::RequestKey *key =
148  static_cast<const InetTable::RequestKey *>(reqkey);
149  prefix_ = key->prefix;
150 }
151 
153  const BgpAttr *attr,
154  const uint32_t label,
155  uint32_t l3_label) const {
156  size_t prefix_size;
157  prefix->prefix.clear();
158  if (label) { // Labeled Unicast
159  prefix_size = (prefix_.prefixlen() + 7) / 8;
160  size_t nlri_size = BgpProtoPrefix::kLabelSize + prefix_size;
161  prefix->prefix.resize(nlri_size, 0);
162  size_t label_offset = 0;
163  prefix->WriteLabel(label_offset, label);
164  size_t prefix_offset = label_offset + BgpProtoPrefix::kLabelSize;
165  prefix->prefixlen = prefix_offset * 8 + prefix_.prefixlen();
166  const Ip4Address::bytes_type &addr_bytes = prefix_.ip4_addr().to_bytes();
167  copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
168  prefix->prefix.begin() + prefix_offset);
169  } else {
170  prefix->prefixlen = prefix_.prefixlen();
171  const Ip4Address::bytes_type &addr_bytes = prefix_.ip4_addr().to_bytes();
172  prefix_size = (prefix->prefixlen + 7) / 8;
173  copy(addr_bytes.begin(), addr_bytes.begin() + prefix_size,
174  back_inserter(prefix->prefix));
175  }
176 }
177 
178 void InetRoute::BuildBgpProtoNextHop(vector<uint8_t> &nh,
179  IpAddress nexthop) const {
180  nh.resize(Address::kMaxV4Bytes);
181  const Ip4Address::bytes_type &addr_bytes = nexthop.to_v4().to_bytes();
182  copy(addr_bytes.begin(), addr_bytes.end(), nh.begin());
183 }
static int FromProtoPrefix(const BgpProtoPrefix &proto_prefix, Ip4Prefix *prefix)
Definition: inet_route.cc:15
int CompareTo(const Ip4Prefix &rhs) const
Definition: inet_route.cc:68
void WriteLabel(size_t label_offset, uint32_t label, bool is_vni=false)
virtual bool IsMoreSpecific(const std::string &match) const
Definition: inet_route.cc:118
Family
Definition: address.h:24
boost::asio::ip::address IpAddress
Definition: address.h:13
Definition: route.h:14
uint32_t ReadLabel(size_t label_offset, bool is_vni=false) const
static const uint8_t kMaxV4PrefixLen
Definition: address.h:20
std::unique_ptr< DBRequestKey > KeyPtr
Definition: db_entry.h:25
int prefixlen() const
Definition: inet_route.h:27
static string ToString(PhysicalDevice::ManagementProtocol proto)
boost::intrusive_ptr< const BgpAttr > BgpAttrPtr
Definition: bgp_attr.h:991
Ip4Address ip4_addr() const
Definition: inet_route.h:25
virtual void BuildBgpProtoNextHop(std::vector< uint8_t > &nh, IpAddress nexthop) const
Definition: inet_route.cc:178
static const uint8_t kMaxV4Bytes
Definition: address.h:19
static const size_t kLabelSize
Definition: bgp_attr_base.h:98
std::vector< uint8_t > prefix
static Ip4Prefix FromString(const std::string &str, boost::system::error_code *errorp=NULL)
Definition: inet_route.cc:84
virtual int CompareTo(const Route &rhs) const
Definition: inet_route.cc:112
std::string ToString() const
Definition: inet_route.cc:60
virtual bool IsLessSpecific(const std::string &match) const
Definition: inet_route.cc:130
const Ip4Prefix & GetPrefix() const
Definition: inet_route.h:70
virtual KeyPtr GetDBRequestKey() const
Definition: inet_route.cc:141
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
boost::system::error_code Ip4SubnetParse(const string &str, Ip4Address *addr, int *plen)
Definition: address.cc:131
virtual void SetKey(const DBRequestKey *reqkey)
Definition: inet_route.cc:146
bool IsMoreSpecific(const Ip4Prefix &rhs) const
Definition: inet_route.cc:96
Ip4Prefix prefix_
Definition: inet_route.h:92
virtual void BuildProtoPrefix(BgpProtoPrefix *prefix, const BgpAttr *attr=NULL, uint32_t label=0, uint32_t l3_label=0) const
Definition: inet_route.cc:152
InetRoute(const Ip4Prefix &prefix)
Definition: inet_route.cc:107
Ip4Address ip4_addr_
Definition: inet_route.h:61
int prefixlen_
Definition: inet_route.h:62