FD.io VPP  v21.10.1-2-g0a485f517
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)
85  : enum_base<nh_proto_t>(v, s)
86 {
87 }
88 
89 const nh_proto_t&
90 nh_proto_t::from_address(const boost::asio::ip::address& addr)
91 {
92  if (addr.is_v6()) {
93  return IPV6;
94  }
95 
96  return IPV4;
97 }
98 
99 const ip_dscp_t ip_dscp_t::DSCP_CS0(0, "CS0");
100 const ip_dscp_t ip_dscp_t::DSCP_CS1(8, "CS1");
101 const ip_dscp_t ip_dscp_t::DSCP_CS2(16, "CS2");
102 const ip_dscp_t ip_dscp_t::DSCP_CS3(24, "CS3");
103 const ip_dscp_t ip_dscp_t::DSCP_CS4(32, "CS4");
104 const ip_dscp_t ip_dscp_t::DSCP_CS5(40, "CS5");
105 const ip_dscp_t ip_dscp_t::DSCP_CS6(48, "CS6");
106 const ip_dscp_t ip_dscp_t::DSCP_CS7(50, "CS7");
107 const ip_dscp_t ip_dscp_t::DSCP_AF11(10, "AF11");
108 const ip_dscp_t ip_dscp_t::DSCP_AF12(12, "AF12");
109 const ip_dscp_t ip_dscp_t::DSCP_AF13(14, "AF13");
110 const ip_dscp_t ip_dscp_t::DSCP_AF21(18, "AF21");
111 const ip_dscp_t ip_dscp_t::DSCP_AF22(20, "AF22");
112 const ip_dscp_t ip_dscp_t::DSCP_AF23(22, "AF23");
113 const ip_dscp_t ip_dscp_t::DSCP_AF31(26, "AF31");
114 const ip_dscp_t ip_dscp_t::DSCP_AF32(28, "AF32");
115 const ip_dscp_t ip_dscp_t::DSCP_AF33(30, "AF33");
116 const ip_dscp_t ip_dscp_t::DSCP_AF41(34, "AF41");
117 const ip_dscp_t ip_dscp_t::DSCP_AF42(36, "AF42");
118 const ip_dscp_t ip_dscp_t::DSCP_AF43(38, "AF43");
119 const ip_dscp_t ip_dscp_t::DSCP_EF(46, "EF");
120 
121 ip_dscp_t::ip_dscp_t(int v, const std::string& s)
122  : enum_base<ip_dscp_t>(v, s)
123 {
124 }
126  : enum_base<ip_dscp_t>(v, std::to_string(v))
127 {
128 }
129 
130 /**
131  * The all Zeros prefix
132  */
133 const route::prefix_t route::prefix_t::ZERO("0.0.0.0", 0);
135 
137  : m_addr(addr)
138  , m_len(len)
139 {
140 }
141 
143  : m_addr(addr)
144  , m_len(VOM::mask_width(addr))
145 {
146 }
147 
149  : m_addr(boost::asio::ip::address::from_string(s))
150  , m_len(len)
151 {
152 }
153 
155  : m_addr(o.m_addr)
156  , m_len(o.m_len)
157 {
158 }
159 
161  : m_addr()
162  , m_len(0)
163 {
164 }
165 
167 {
168 }
169 
172 {
173  m_addr = o.m_addr;
174  m_len = o.m_len;
175 
176  return (*this);
177 }
178 
181 {
182  return (m_addr);
183 }
184 
185 uint8_t
187 {
188  return (m_len);
189 }
190 
191 bool
193 {
194  if (m_len == o.m_len) {
195  return (m_addr < o.m_addr);
196  } else {
197  return (m_len < o.m_len);
198  }
199 }
200 
201 bool
203 {
204  return (m_len == o.m_len && m_addr == o.m_addr);
205 }
206 
207 bool
209 {
210  return (!(*this == o));
211 }
212 
215 {
216  std::ostringstream s;
217 
218  s << m_addr.to_string() << "/" << std::to_string(m_len);
219 
220  return (s.str());
221 }
222 
224 from_bytes(uint8_t is_ip6, const uint8_t* bytes)
225 {
227 
228  if (is_ip6) {
229  std::array<uint8_t, 16> a;
230  std::copy(bytes, bytes + 16, std::begin(a));
231  boost::asio::ip::address_v6 v6(a);
232  addr = v6;
233  } else {
234  std::array<uint8_t, 4> a;
235  std::copy(bytes, bytes + 4, std::begin(a));
236  boost::asio::ip::address_v4 v4(a);
237  addr = v4;
238  }
239 
240  return (addr);
241 }
242 
243 route::prefix_t::prefix_t(uint8_t is_ip6, uint8_t* addr, uint8_t len)
244  : m_addr(from_bytes(is_ip6, addr))
245  , m_len(len)
246 {
247 }
248 void
249 to_bytes(const boost::asio::ip::address_v6& addr, uint8_t* array)
250 {
251  memcpy(array, addr.to_bytes().data(), 16);
252 }
253 
254 void
255 to_bytes(const boost::asio::ip::address_v4& addr, uint8_t* array)
256 {
257  memcpy(array, addr.to_bytes().data(), 4);
258 }
259 
260 void
261 to_bytes(const boost::asio::ip::address& addr, uint8_t* is_ip6, uint8_t* array)
262 {
263  if (addr.is_v6()) {
264  *is_ip6 = 1;
265  to_bytes(addr.to_v6(), array);
266  } else {
267  *is_ip6 = 0;
268  to_bytes(addr.to_v4(), array);
269  }
270 }
271 
272 uint32_t
274 {
275  if (addr.is_v6()) {
276  return 128;
277  }
278  return 32;
279 }
280 
281 void
282 route::prefix_t::to_vpp(uint8_t* is_ip6, uint8_t* addr, uint8_t* len) const
283 {
284  *len = m_len;
285  to_bytes(m_addr, is_ip6, addr);
286 }
287 
290 {
291  if (m_addr.is_v6()) {
292  return (l3_proto_t::IPV6);
293  } else {
294  return (l3_proto_t::IPV4);
295  }
296 
297  return (l3_proto_t::IPV4);
298 }
299 
300 std::ostream&
301 operator<<(std::ostream& os, const route::prefix_t& pfx)
302 {
303  os << pfx.to_string();
304 
305  return (os);
306 }
307 
308 boost::asio::ip::address_v4
309 operator|(const boost::asio::ip::address_v4& addr1,
310  const boost::asio::ip::address_v4& addr2)
311 {
312  uint32_t a;
313  a = addr1.to_ulong() | addr2.to_ulong();
314  boost::asio::ip::address_v4 addr(a);
315  return (addr);
316 }
317 
318 boost::asio::ip::address_v4 operator&(const boost::asio::ip::address_v4& addr1,
319  const boost::asio::ip::address_v4& addr2)
320 {
321  uint32_t a;
322  a = addr1.to_ulong() & addr2.to_ulong();
323  boost::asio::ip::address_v4 addr(a);
324  return (addr);
325 }
326 
327 boost::asio::ip::address_v4 operator~(const boost::asio::ip::address_v4& addr1)
328 {
329  uint32_t a;
330  a = ~addr1.to_ulong();
331  boost::asio::ip::address_v4 addr(a);
332  return (addr);
333 }
334 
335 boost::asio::ip::address_v6
336 operator|(const boost::asio::ip::address_v6& addr1,
337  const boost::asio::ip::address_v6& addr2)
338 {
339  boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
340  boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();
341 
342  for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
343  ii < b1.max_size(); ii++) {
344  b1[ii] |= b2[ii];
345  }
346 
347  boost::asio::ip::address_v6 addr(b1);
348  return (addr);
349 }
350 
351 boost::asio::ip::address_v6 operator&(const boost::asio::ip::address_v6& addr1,
352  const boost::asio::ip::address_v6& addr2)
353 {
354  boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
355  boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();
356 
357  for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
358  ii < b1.max_size(); ii++) {
359  b1[ii] &= b2[ii];
360  }
361 
362  boost::asio::ip::address_v6 addr(b1);
363  return (addr);
364 }
365 
366 boost::asio::ip::address_v6 operator~(const boost::asio::ip::address_v6& addr1)
367 {
368  boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
369 
370  for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
371  ii < b1.max_size(); ii++) {
372  b1[ii] = ~b1[ii];
373  }
374 
375  boost::asio::ip::address_v6 addr(b1);
376  return (addr);
377 }
380  const boost::asio::ip::address& addr2)
381 {
382  if (addr1.is_v6())
383  return (addr1.to_v6() | addr2.to_v6());
384  else
385  return (addr1.to_v4() | addr2.to_v4());
386 }
387 
389  const boost::asio::ip::address& addr2)
390 {
391  if (addr1.is_v6())
392  return (addr1.to_v6() & addr2.to_v6());
393  else
394  return (addr1.to_v4() & addr2.to_v4());
395 }
396 
398 {
399  if (addr1.is_v6())
400  return ~(addr1.to_v6());
401  else
402  return ~(addr1.to_v4());
403 }
404 
407 {
408  if (m_addr.is_v6()) {
409  boost::asio::ip::address_v6::bytes_type b =
411 
412  uint8_t n_bits = mask_width();
413 
414  for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
415  ii < b.max_size(); ii++) {
416  for (int8_t bit = 7; bit >= 0 && n_bits; bit--) {
417  b[ii] |= (1 << bit);
418  n_bits--;
419  }
420  if (!n_bits)
421  break;
422  }
423 
424  return (boost::asio::ip::address_v6(b));
425  } else {
426  uint32_t a;
427 
428  a = ~((1 << (32 - mask_width())) - 1);
429 
430  return (boost::asio::ip::address_v4(a));
431  }
432 }
433 
436 {
437  prefix_t pfx(*this);
438 
439  pfx.m_addr = pfx.m_addr & pfx.mask();
440 
441  return (pfx);
442 }
443 
446 {
447  prefix_t pfx(*this);
448 
449  pfx.m_addr = pfx.m_addr | ~pfx.mask();
450 
451  return (pfx);
452 }
453 
454 /**
455  * The all Zeros prefix
456  */
459 
461  : m_gaddr(gaddr)
462  , m_saddr()
463  , m_len(len)
464 {
465 }
466 
468  : m_gaddr(gaddr)
469  , m_saddr()
470  , m_len(VOM::mask_width(gaddr))
471 {
472 }
473 
476  : m_gaddr(gaddr)
477  , m_saddr(saddr)
478  , m_len(2 * VOM::mask_width(gaddr))
479 {
480 }
481 
484  uint16_t len)
485  : m_gaddr(gaddr)
486  , m_saddr(saddr)
487  , m_len(len)
488 {
489 }
490 
492  : m_gaddr(o.m_gaddr)
493  , m_saddr(o.m_saddr)
494  , m_len(o.m_len)
495 {
496 }
498  : m_gaddr()
499  , m_saddr()
500  , m_len(0)
501 {
502 }
503 
505 {
506 }
507 
510 {
511  return (m_gaddr);
512 }
513 
516 {
517  return (m_saddr);
518 }
519 
520 uint8_t
522 {
523  return (m_len);
524 }
525 
528 {
529  if (m_gaddr.is_v6()) {
530  return (l3_proto_t::IPV6);
531  } else {
532  return (l3_proto_t::IPV4);
533  }
534 
535  return (l3_proto_t::IPV4);
536 }
537 
540 {
541  m_gaddr = o.m_gaddr;
542  m_saddr = o.m_saddr;
543  m_len = o.m_len;
544 
545  return (*this);
546 }
547 
548 bool
550 {
551  if (m_len == o.m_len) {
552  if (m_saddr == o.m_saddr)
553  return (m_gaddr < o.m_gaddr);
554  else
555  return (m_saddr < o.m_saddr);
556  } else {
557  return (m_len < o.m_len);
558  }
559 }
560 
561 bool
563 {
564  return (m_len == o.m_len && m_gaddr == o.m_gaddr && m_saddr == o.m_saddr);
565 }
566 
567 bool
569 {
570  return (!(*this == o));
571 }
572 
575 {
576  std::ostringstream s;
577 
578  s << "(" << m_saddr.to_string() << "," << m_gaddr.to_string() << "/"
579  << std::to_string(m_len) << ")";
580 
581  return (s.str());
582 }
583 
584 }; // namespace VOM
585 
586 /*
587  * fd.io coding-style-patch-verification: OFF
588  *
589  * Local Variables:
590  * eval: (c-set-style "mozilla")
591  * End:
592  */
VOM::l3_proto_t::MPLS
const static l3_proto_t MPLS
Definition: prefix.hpp:57
VOM::route::prefix_t
A prefix defintion.
Definition: prefix.hpp:131
VOM::route::mprefix_t::operator!=
bool operator!=(const mprefix_t &o) const
not equal opartor
Definition: prefix.cpp:568
VOM::operator&
boost::asio::ip::address_v4 operator&(const boost::asio::ip::address_v4 &addr1, const boost::asio::ip::address_v4 &addr2)
Definition: prefix.cpp:318
ip_dscp_t
enum ip_dscp_t_ ip_dscp_t
VOM::route::prefix_t::mask_width
uint8_t mask_width() const
Get the network mask width.
Definition: prefix.cpp:186
VOM
The VPP Object Model (VOM) library.
Definition: acl_binding.cpp:19
VOM::route::prefix_t::ZERO
const static prefix_t ZERO
The all Zeros prefix.
Definition: prefix.hpp:205
VOM::operator~
boost::asio::ip::address_v4 operator~(const boost::asio::ip::address_v4 &addr1)
Definition: prefix.cpp:327
VOM::nh_proto_t::MPLS
const static nh_proto_t MPLS
Definition: prefix.hpp:36
VOM::route::prefix_t::prefix_t
prefix_t()
Default Constructor - creates ::/0.
Definition: prefix.cpp:160
VOM::to_bytes
void to_bytes(const boost::asio::ip::address_v6 &addr, uint8_t *array)
Definition: prefix.cpp:249
VOM::l3_proto_t::is_ipv4
bool is_ipv4() const
Definition: prefix.cpp:41
VOM::l3_proto_t::IPV4
const static l3_proto_t IPV4
Definition: prefix.hpp:55
VOM::route::mprefix_t::mprefix_t
mprefix_t()
Default Constructor - creates ::/0.
Definition: prefix.cpp:497
VOM::route::mprefix_t::grp_address
const boost::asio::ip::address & grp_address() const
Get the address.
Definition: prefix.cpp:509
VOM::route::prefix_t::low
prefix_t low() const
get the lowest address in the prefix
Definition: prefix.cpp:435
VOM::mask_width
uint32_t mask_width(const boost::asio::ip::address &addr)
Get the prefix mask length of a host route from the boost address.
Definition: prefix.cpp:273
VOM::route::prefix_t::~prefix_t
~prefix_t()
Destructor.
Definition: prefix.cpp:166
VOM::route::mprefix_t::mask_width
uint8_t mask_width() const
Get the network mask width.
Definition: prefix.cpp:521
VOM::from_bytes
boost::asio::ip::address from_bytes(uint8_t is_ip6, const uint8_t *bytes)
Convert a VPP byte stinrg into a boost addresss.
Definition: prefix.cpp:224
addr
vhost_vring_addr_t addr
Definition: vhost_user.h:130
VOM::operator|
boost::asio::ip::address_v4 operator|(const boost::asio::ip::address_v4 &addr1, const boost::asio::ip::address_v4 &addr2)
Definition: prefix.cpp:309
VOM::route::prefix_t::operator=
prefix_t & operator=(const prefix_t &)
Assignement.
Definition: prefix.cpp:171
VOM::route::mprefix_t
A prefix defintion.
Definition: prefix.hpp:252
VOM::route::mprefix_t::l3_proto
l3_proto_t l3_proto() const
Get the L3 protocol.
Definition: prefix.cpp:527
VOM::route::mprefix_t::src_address
const boost::asio::ip::address & src_address() const
Definition: prefix.cpp:515
VOM::route::prefix_t::address
const boost::asio::ip::address & address() const
Get the address.
Definition: prefix.cpp:180
VOM::route::prefix_t::to_string
std::string to_string() const
convert to string format for debug purposes
Definition: prefix.cpp:214
len
u8 len
Definition: ip_types.api:103
VOM::route::prefix_t::operator!=
bool operator!=(const prefix_t &o) const
not equal opartor
Definition: prefix.cpp:208
any
word any
Definition: types.h:139
VOM::route::mprefix_t::ZERO
const static mprefix_t ZERO
The all Zeros prefix.
Definition: prefix.hpp:330
VOM::nh_proto_t::ETHERNET
const static nh_proto_t ETHERNET
Definition: prefix.hpp:37
VOM::enum_base
A template base class for all enum types.
Definition: enum_base.hpp:30
VOM::route::prefix_t::operator==
bool operator==(const prefix_t &o) const
equals operator
Definition: prefix.cpp:202
address
manual_print typedef address
Definition: ip_types.api:96
VOM::l3_proto_t::from_address
static const l3_proto_t & from_address(const boost::asio::ip::address &addr)
Definition: prefix.cpp:47
VOM::route::operator<<
std::ostream & operator<<(std::ostream &os, const ip_route::key_t &key)
Definition: route.cpp:655
VOM::route::prefix_t::high
prefix_t high() const
Get the highest address in the prefix.
Definition: prefix.cpp:445
VOM::route::mprefix_t::operator==
bool operator==(const mprefix_t &o) const
equals operator
Definition: prefix.cpp:562
VOM::operator<<
std::ostream & operator<<(std::ostream &os, const std::pair< direction_t, interface::key_t > &key)
Definition: acl_binding.cpp:201
VOM::route::prefix_t::l3_proto
l3_proto_t l3_proto() const
Get the L3 protocol.
Definition: prefix.cpp:289
VOM::route::mprefix_t::operator<
bool operator<(const mprefix_t &o) const
Less than operator.
Definition: prefix.cpp:549
VOM::l3_proto_t::is_ipv6
bool is_ipv6() const
Definition: prefix.cpp:35
VOM::route::mprefix_t::ZEROv6
const static mprefix_t ZEROv6
The all Zeros v6 prefix.
Definition: prefix.hpp:335
is_ip6
bool is_ip6
Definition: ip.api:43
VOM::enum_base::to_string
const std::string & to_string() const
convert to string format for debug purposes
Definition: enum_base.hpp:36
VOM::l3_proto_t
An L3 protocol can be used to construct a prefix that is used to match packets are part of a route.
Definition: prefix.hpp:52
VOM::nh_proto_t::IPV6
const static nh_proto_t IPV6
Definition: prefix.hpp:35
VOM::route::prefix_t::mask
boost::asio::ip::address mask() const
Return a address representation of the mask, e.g.
Definition: prefix.cpp:406
prefix.hpp
gaddr
vl_api_ip4_address_t gaddr
Definition: igmp.api:70
VOM::nh_proto_t
Types belonging to Routing.
Definition: prefix.hpp:31
VOM::ip_dscp_t
IP DSCP values.
Definition: prefix.hpp:81
VOM::route::prefix_t::to_vpp
void to_vpp(uint8_t *is_ip6, uint8_t *addr, uint8_t *len) const
Convert the prefix into VPP API parameters.
Definition: prefix.cpp:282
VOM::ip_dscp_t::ip_dscp_t
ip_dscp_t(int v)
Constructor allows the creation of any DSCP value.
Definition: prefix.cpp:125
VOM::route::mprefix_t::~mprefix_t
~mprefix_t()
Destructor.
Definition: prefix.cpp:504
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
a
a
Definition: bitmap.h:525
VOM::route::prefix_t::ZEROv6
const static prefix_t ZEROv6
The all Zeros v6 prefix.
Definition: prefix.hpp:210
ip
vl_api_address_t ip
Definition: l2.api:558
VOM::route::mprefix_t::operator=
mprefix_t & operator=(const mprefix_t &)
Assignement.
Definition: prefix.cpp:539
VOM::nh_proto_t::IPV4
const static nh_proto_t IPV4
Definition: prefix.hpp:34
VOM::route::prefix_t::operator<
bool operator<(const prefix_t &o) const
Less than operator.
Definition: prefix.cpp:192
VOM::l3_proto_t::to_nh_proto
const nh_proto_t & to_nh_proto() const
Definition: prefix.cpp:57
VOM::l3_proto_t::IPV6
const static l3_proto_t IPV6
Definition: prefix.hpp:56
VOM::route::mprefix_t::to_string
std::string to_string() const
convert to string format for debug purposes
Definition: prefix.cpp:574
string
const char *const string
Definition: cJSON.h:172