FD.io VPP  v18.07-rc0-415-g6c78436
Vector Packet Processing
prefix.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <boost/algorithm/string.hpp>
17 #include <sstream>
18 
19 #include "vom/prefix.hpp"
20 
21 namespace VOM {
22 /*
23  * Keep this in sync with VPP's fib_protocol_t
24  */
25 const l3_proto_t l3_proto_t::IPV4(0, "ipv4");
26 const l3_proto_t l3_proto_t::IPV6(1, "ipv6");
27 const l3_proto_t l3_proto_t::MPLS(2, "mpls");
28 
29 l3_proto_t::l3_proto_t(int v, const std::string& s)
30  : enum_base<l3_proto_t>(v, s)
31 {
32 }
33 
34 bool
36 {
37  return (*this == IPV6);
38 }
39 
40 bool
42 {
43  return (*this == IPV4);
44 }
45 
46 const l3_proto_t&
48 {
49  if (addr.is_v6()) {
50  return IPV6;
51  }
52 
53  return IPV4;
54 }
55 
56 const nh_proto_t&
58 {
59  if (*this == IPV4)
60  return nh_proto_t::IPV4;
61  else if (*this == IPV6)
62  return nh_proto_t::IPV6;
63  else if (*this == MPLS)
64  return nh_proto_t::MPLS;
65 
66  return nh_proto_t::IPV4;
67 }
68 
69 std::ostream&
70 operator<<(std::ostream& os, const l3_proto_t& l3p)
71 {
72  os << l3p.to_string();
73  return os;
74 }
75 
76 /*
77  * Keep this in sync with VPP's dpo_proto_t
78  */
79 const nh_proto_t nh_proto_t::IPV4(0, "ipv4");
80 const nh_proto_t nh_proto_t::IPV6(1, "ipv6");
81 const nh_proto_t nh_proto_t::MPLS(2, "mpls");
82 const nh_proto_t nh_proto_t::ETHERNET(3, "ethernet");
83 
84 nh_proto_t::nh_proto_t(int v, const std::string& s)
86 {
87 }
88 
89 const nh_proto_t&
91 {
92  if (addr.is_v6()) {
93  return IPV6;
94  }
95 
96  return IPV4;
97 }
98 
99 /**
100  * The all Zeros prefix
101  */
102 const route::prefix_t route::prefix_t::ZERO("0.0.0.0", 0);
104 
106  : m_addr(addr)
107  , m_len(len)
108 {
109 }
110 
112  : m_addr(addr)
113  , m_len(VOM::mask_width(addr))
114 {
115 }
116 
117 route::prefix_t::prefix_t(const std::string& s, uint8_t len)
118  : m_addr(boost::asio::ip::address::from_string(s))
119  , m_len(len)
120 {
121 }
122 
124  : m_addr(o.m_addr)
125  , m_len(o.m_len)
126 {
127 }
128 
130  : m_addr()
131  , m_len(0)
132 {
133 }
134 
136 {
137 }
138 
141 {
142  m_addr = o.m_addr;
143  m_len = o.m_len;
144 
145  return (*this);
146 }
147 
150 {
151  return (m_addr);
152 }
153 
154 uint8_t
156 {
157  return (m_len);
158 }
159 
160 bool
162 {
163  if (m_len == o.m_len) {
164  return (m_addr < o.m_addr);
165  } else {
166  return (m_len < o.m_len);
167  }
168 }
169 
170 bool
172 {
173  return (m_len == o.m_len && m_addr == o.m_addr);
174 }
175 
176 bool
178 {
179  return (!(*this == o));
180 }
181 
182 std::string
184 {
185  std::ostringstream s;
186 
187  s << m_addr.to_string() << "/" << std::to_string(m_len);
188 
189  return (s.str());
190 }
191 
193 from_bytes(uint8_t is_ip6, uint8_t* bytes)
194 {
196 
197  if (is_ip6) {
198  std::array<uint8_t, 16> a;
199  std::copy(bytes, bytes + 16, std::begin(a));
200  boost::asio::ip::address_v6 v6(a);
201  addr = v6;
202  } else {
203  std::array<uint8_t, 4> a;
204  std::copy(bytes, bytes + 4, std::begin(a));
205  boost::asio::ip::address_v4 v4(a);
206  addr = v4;
207  }
208 
209  return (addr);
210 }
211 
212 route::prefix_t::prefix_t(uint8_t is_ip6, uint8_t* addr, uint8_t len)
213  : m_addr(from_bytes(is_ip6, addr))
214  , m_len(len)
215 {
216 }
217 void
218 to_bytes(const boost::asio::ip::address_v6& addr, uint8_t* array)
219 {
220  memcpy(array, addr.to_bytes().data(), 16);
221 }
222 
223 void
224 to_bytes(const boost::asio::ip::address_v4& addr, uint8_t* array)
225 {
226  memcpy(array, addr.to_bytes().data(), 4);
227 }
228 
229 void
230 to_bytes(const boost::asio::ip::address& addr, uint8_t* is_ip6, uint8_t* array)
231 {
232  if (addr.is_v6()) {
233  *is_ip6 = 1;
234  to_bytes(addr.to_v6(), array);
235  } else {
236  *is_ip6 = 0;
237  to_bytes(addr.to_v4(), array);
238  }
239 }
240 
241 uint32_t
243 {
244  if (addr.is_v6()) {
245  return 128;
246  }
247  return 32;
248 }
249 
250 void
251 route::prefix_t::to_vpp(uint8_t* is_ip6, uint8_t* addr, uint8_t* len) const
252 {
253  *len = m_len;
254  to_bytes(m_addr, is_ip6, addr);
255 }
256 
259 {
260  if (m_addr.is_v6()) {
261  return (l3_proto_t::IPV6);
262  } else {
263  return (l3_proto_t::IPV4);
264  }
265 
266  return (l3_proto_t::IPV4);
267 }
268 
269 std::ostream&
270 operator<<(std::ostream& os, const route::prefix_t& pfx)
271 {
272  os << pfx.to_string();
273 
274  return (os);
275 }
276 
277 boost::asio::ip::address_v4
278 operator|(const boost::asio::ip::address_v4& addr1,
279  const boost::asio::ip::address_v4& addr2)
280 {
281  uint32_t a;
282  a = addr1.to_ulong() | addr2.to_ulong();
283  boost::asio::ip::address_v4 addr(a);
284  return (addr);
285 }
286 
287 boost::asio::ip::address_v4 operator&(const boost::asio::ip::address_v4& addr1,
288  const boost::asio::ip::address_v4& addr2)
289 {
290  uint32_t a;
291  a = addr1.to_ulong() & addr2.to_ulong();
292  boost::asio::ip::address_v4 addr(a);
293  return (addr);
294 }
295 
296 boost::asio::ip::address_v4 operator~(const boost::asio::ip::address_v4& addr1)
297 {
298  uint32_t a;
299  a = ~addr1.to_ulong();
300  boost::asio::ip::address_v4 addr(a);
301  return (addr);
302 }
303 
304 boost::asio::ip::address_v6
305 operator|(const boost::asio::ip::address_v6& addr1,
306  const boost::asio::ip::address_v6& addr2)
307 {
308  boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
309  boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();
310 
311  for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
312  ii < b1.max_size(); ii++) {
313  b1[ii] |= b2[ii];
314  }
315 
316  boost::asio::ip::address_v6 addr(b1);
317  return (addr);
318 }
319 
320 boost::asio::ip::address_v6 operator&(const boost::asio::ip::address_v6& addr1,
321  const boost::asio::ip::address_v6& addr2)
322 {
323  boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
324  boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();
325 
326  for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
327  ii < b1.max_size(); ii++) {
328  b1[ii] &= b2[ii];
329  }
330 
331  boost::asio::ip::address_v6 addr(b1);
332  return (addr);
333 }
334 
335 boost::asio::ip::address_v6 operator~(const boost::asio::ip::address_v6& addr1)
336 {
337  boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
338 
339  for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
340  ii < b1.max_size(); ii++) {
341  b1[ii] = ~b1[ii];
342  }
343 
344  boost::asio::ip::address_v6 addr(b1);
345  return (addr);
346 }
349  const boost::asio::ip::address& addr2)
350 {
351  if (addr1.is_v6())
352  return (addr1.to_v6() | addr2.to_v6());
353  else
354  return (addr1.to_v4() | addr2.to_v4());
355 }
356 
358  const boost::asio::ip::address& addr2)
359 {
360  if (addr1.is_v6())
361  return (addr1.to_v6() & addr2.to_v6());
362  else
363  return (addr1.to_v4() & addr2.to_v4());
364 }
365 
367 {
368  if (addr1.is_v6())
369  return ~(addr1.to_v6());
370  else
371  return ~(addr1.to_v4());
372 }
373 
376 {
377  if (m_addr.is_v6()) {
378  boost::asio::ip::address_v6::bytes_type b =
380 
381  uint8_t n_bits = mask_width();
382 
383  for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
384  ii < b.max_size(); ii++) {
385  for (int8_t bit = 7; bit >= 0 && n_bits; bit--) {
386  b[ii] |= (1 << bit);
387  n_bits--;
388  }
389  if (!n_bits)
390  break;
391  }
392 
393  return (boost::asio::ip::address_v6(b));
394  } else {
395  uint32_t a;
396 
397  a = ~((1 << (32 - mask_width())) - 1);
398 
399  return (boost::asio::ip::address_v4(a));
400  }
401 }
402 
405 {
406  prefix_t pfx(*this);
407 
408  pfx.m_addr = pfx.m_addr & pfx.mask();
409 
410  return (pfx);
411 }
412 
415 {
416  prefix_t pfx(*this);
417 
418  pfx.m_addr = pfx.m_addr | ~pfx.mask();
419 
420  return (pfx);
421 }
422 
423 }; // namespace VOM
424 
425 /*
426  * fd.io coding-style-patch-verification: ON
427  *
428  * Local Variables:
429  * eval: (c-set-style "mozilla")
430  * End:
431  */
typedef address
Definition: ip_types.api:34
const nh_proto_t & to_nh_proto() const
Definition: prefix.cpp:57
a
Definition: bitmap.h:537
bool operator<(const prefix_t &o) const
Less than operator.
Definition: prefix.cpp:161
l3_proto_t l3_proto() const
Get the L3 protocol.
Definition: prefix.cpp:258
static const nh_proto_t IPV6
Definition: prefix.hpp:36
static const nh_proto_t IPV4
Definition: prefix.hpp:35
word any
Definition: types.h:139
static const prefix_t ZEROv6
The all Zeros v6 prefix.
Definition: prefix.hpp:170
boost::asio::ip::address mask() const
Return a address representation of the mask, e.g.
Definition: prefix.cpp:375
An L3 protocol can be used to construct a prefix that is used to match packets are part of a route...
Definition: prefix.hpp:53
static const nh_proto_t & from_address(const boost::asio::ip::address &addr)
Definition: prefix.cpp:90
bool operator!=(const prefix_t &o) const
not equal opartor
Definition: prefix.cpp:177
static const l3_proto_t MPLS
Definition: prefix.hpp:58
prefix_t low() const
get the lowest address in the prefix
Definition: prefix.cpp:404
std::ostream & operator<<(std::ostream &os, const ip_route::key_t &key)
Definition: route.cpp:521
Types belonging to Routing.
Definition: prefix.hpp:32
bool is_ipv4()
Definition: prefix.cpp:41
static const l3_proto_t IPV4
Definition: prefix.hpp:56
static const l3_proto_t IPV6
Definition: prefix.hpp:57
void to_bytes(const boost::asio::ip::address_v6 &addr, uint8_t *array)
Definition: prefix.cpp:218
std::string to_string() const
convert to string format for debug purposes
Definition: prefix.cpp:183
boost::asio::ip::address_v4 operator|(const boost::asio::ip::address_v4 &addr1, const boost::asio::ip::address_v4 &addr2)
Definition: prefix.cpp:278
prefix_t high() const
Get the highest address in the prefix.
Definition: prefix.cpp:414
#define v
Definition: acl.c:491
boost::asio::ip::address_v4 operator~(const boost::asio::ip::address_v4 &addr1)
Definition: prefix.cpp:296
prefix_t()
Default Constructor - creates ::/0.
Definition: prefix.cpp:129
void to_vpp(uint8_t *is_ip6, uint8_t *addr, uint8_t *len) const
Convert the prefix into VPP API parameters.
Definition: prefix.cpp:251
boost::asio::ip::address_v4 operator&(const boost::asio::ip::address_v4 &addr1, const boost::asio::ip::address_v4 &addr2)
Definition: prefix.cpp:287
prefix_t & operator=(const prefix_t &)
Assignement.
Definition: prefix.cpp:140
boost::asio::ip::address from_bytes(uint8_t is_ip6, uint8_t *bytes)
Convert a VPP byte stinrg into a boost addresss.
Definition: prefix.cpp:193
bool operator==(const prefix_t &o) const
equals operator
Definition: prefix.cpp:171
std::ostream & operator<<(std::ostream &os, const std::pair< direction_t, interface::key_t > &key)
static const l3_proto_t & from_address(const boost::asio::ip::address &addr)
Definition: prefix.cpp:47
static const nh_proto_t MPLS
Definition: prefix.hpp:37
The VPP Object Model (VOM) library.
Definition: acl_binding.cpp:19
static const prefix_t ZERO
The all Zeros prefix.
Definition: prefix.hpp:165
uint8_t mask_width() const
Get the network mask width.
Definition: prefix.cpp:155
const std::string & to_string() const
convert to string format for debug purposes
Definition: enum_base.hpp:36
const boost::asio::ip::address & address() const
Get the address.
Definition: prefix.cpp:149
vhost_vring_addr_t addr
Definition: vhost-user.h:83
A prefix defintion.
Definition: prefix.hpp:93
~prefix_t()
Destructor.
Definition: prefix.cpp:135
static const nh_proto_t ETHERNET
Definition: prefix.hpp:38
bool is_ipv6()
Definition: prefix.cpp:35