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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <boost/algorithm/string.hpp>
19 #include "vom/prefix.hpp"
23 * Keep this in sync with VPP's fib_protocol_t
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");
29 l3_proto_t::l3_proto_t(int v, const std::string& s)
30 : enum_base<l3_proto_t>(v, s)
35 l3_proto_t::is_ipv6() const
37 return (*this == IPV6);
41 l3_proto_t::is_ipv4() const
43 return (*this == IPV4);
47 l3_proto_t::from_address(const boost::asio::ip::address& addr)
57 l3_proto_t::to_nh_proto() const
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;
66 return nh_proto_t::IPV4;
70 operator<<(std::ostream& os, const l3_proto_t& l3p)
72 os << l3p.to_string();
77 * Keep this in sync with VPP's dpo_proto_t
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");
84 nh_proto_t::nh_proto_t(int v, const std::string& s)
85 : enum_base<nh_proto_t>(v, s)
90 nh_proto_t::from_address(const boost::asio::ip::address& addr)
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");
121 ip_dscp_t::ip_dscp_t(int v, const std::string& s)
122 : enum_base<ip_dscp_t>(v, s)
125 ip_dscp_t::ip_dscp_t(int v)
126 : enum_base<ip_dscp_t>(v, std::to_string(v))
131 * The all Zeros prefix
133 const route::prefix_t route::prefix_t::ZERO("0.0.0.0", 0);
134 const route::prefix_t route::prefix_t::ZEROv6("::", 0);
136 route::prefix_t::prefix_t(const boost::asio::ip::address& addr, uint8_t len)
142 route::prefix_t::prefix_t(const boost::asio::ip::address& addr)
144 , m_len(VOM::mask_width(addr))
148 route::prefix_t::prefix_t(const std::string& s, uint8_t len)
149 : m_addr(boost::asio::ip::address::from_string(s))
154 route::prefix_t::prefix_t(const prefix_t& o)
160 route::prefix_t::prefix_t()
166 route::prefix_t::~prefix_t()
171 route::prefix_t::operator=(const route::prefix_t& o)
179 const boost::asio::ip::address&
180 route::prefix_t::address() const
186 route::prefix_t::mask_width() const
192 route::prefix_t::operator<(const route::prefix_t& o) const
194 if (m_len == o.m_len) {
195 return (m_addr < o.m_addr);
197 return (m_len < o.m_len);
202 route::prefix_t::operator==(const route::prefix_t& o) const
204 return (m_len == o.m_len && m_addr == o.m_addr);
208 route::prefix_t::operator!=(const route::prefix_t& o) const
210 return (!(*this == o));
214 route::prefix_t::to_string() const
216 std::ostringstream s;
218 s << m_addr.to_string() << "/" << std::to_string(m_len);
223 boost::asio::ip::address
224 from_bytes(uint8_t is_ip6, const uint8_t* bytes)
226 boost::asio::ip::address addr;
229 std::array<uint8_t, 16> a;
230 std::copy(bytes, bytes + 16, std::begin(a));
231 boost::asio::ip::address_v6 v6(a);
234 std::array<uint8_t, 4> a;
235 std::copy(bytes, bytes + 4, std::begin(a));
236 boost::asio::ip::address_v4 v4(a);
243 route::prefix_t::prefix_t(uint8_t is_ip6, uint8_t* addr, uint8_t len)
244 : m_addr(from_bytes(is_ip6, addr))
249 to_bytes(const boost::asio::ip::address_v6& addr, uint8_t* array)
251 memcpy(array, addr.to_bytes().data(), 16);
255 to_bytes(const boost::asio::ip::address_v4& addr, uint8_t* array)
257 memcpy(array, addr.to_bytes().data(), 4);
261 to_bytes(const boost::asio::ip::address& addr, uint8_t* is_ip6, uint8_t* array)
265 to_bytes(addr.to_v6(), array);
268 to_bytes(addr.to_v4(), array);
273 mask_width(const boost::asio::ip::address& addr)
282 route::prefix_t::to_vpp(uint8_t* is_ip6, uint8_t* addr, uint8_t* len) const
285 to_bytes(m_addr, is_ip6, addr);
289 route::prefix_t::l3_proto() const
291 if (m_addr.is_v6()) {
292 return (l3_proto_t::IPV6);
294 return (l3_proto_t::IPV4);
297 return (l3_proto_t::IPV4);
301 operator<<(std::ostream& os, const route::prefix_t& pfx)
303 os << pfx.to_string();
308 boost::asio::ip::address_v4
309 operator|(const boost::asio::ip::address_v4& addr1,
310 const boost::asio::ip::address_v4& addr2)
313 a = addr1.to_ulong() | addr2.to_ulong();
314 boost::asio::ip::address_v4 addr(a);
318 boost::asio::ip::address_v4 operator&(const boost::asio::ip::address_v4& addr1,
319 const boost::asio::ip::address_v4& addr2)
322 a = addr1.to_ulong() & addr2.to_ulong();
323 boost::asio::ip::address_v4 addr(a);
327 boost::asio::ip::address_v4 operator~(const boost::asio::ip::address_v4& addr1)
330 a = ~addr1.to_ulong();
331 boost::asio::ip::address_v4 addr(a);
335 boost::asio::ip::address_v6
336 operator|(const boost::asio::ip::address_v6& addr1,
337 const boost::asio::ip::address_v6& addr2)
339 boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
340 boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();
342 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
343 ii < b1.max_size(); ii++) {
347 boost::asio::ip::address_v6 addr(b1);
351 boost::asio::ip::address_v6 operator&(const boost::asio::ip::address_v6& addr1,
352 const boost::asio::ip::address_v6& addr2)
354 boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
355 boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();
357 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
358 ii < b1.max_size(); ii++) {
362 boost::asio::ip::address_v6 addr(b1);
366 boost::asio::ip::address_v6 operator~(const boost::asio::ip::address_v6& addr1)
368 boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
370 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
371 ii < b1.max_size(); ii++) {
375 boost::asio::ip::address_v6 addr(b1);
378 boost::asio::ip::address
379 operator|(const boost::asio::ip::address& addr1,
380 const boost::asio::ip::address& addr2)
383 return (addr1.to_v6() | addr2.to_v6());
385 return (addr1.to_v4() | addr2.to_v4());
388 boost::asio::ip::address operator&(const boost::asio::ip::address& addr1,
389 const boost::asio::ip::address& addr2)
392 return (addr1.to_v6() & addr2.to_v6());
394 return (addr1.to_v4() & addr2.to_v4());
397 boost::asio::ip::address operator~(const boost::asio::ip::address& addr1)
400 return ~(addr1.to_v6());
402 return ~(addr1.to_v4());
405 boost::asio::ip::address
406 route::prefix_t::mask() const
408 if (m_addr.is_v6()) {
409 boost::asio::ip::address_v6::bytes_type b =
410 boost::asio::ip::address_v6::any().to_bytes();
412 uint8_t n_bits = mask_width();
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--) {
424 return (boost::asio::ip::address_v6(b));
428 a = ~((1 << (32 - mask_width())) - 1);
430 return (boost::asio::ip::address_v4(a));
435 route::prefix_t::low() const
439 pfx.m_addr = pfx.m_addr & pfx.mask();
445 route::prefix_t::high() const
449 pfx.m_addr = pfx.m_addr | ~pfx.mask();
455 * The all Zeros prefix
457 const route::mprefix_t route::mprefix_t::ZERO;
458 const route::mprefix_t route::mprefix_t::ZEROv6;
460 route::mprefix_t::mprefix_t(const boost::asio::ip::address& gaddr, uint8_t len)
467 route::mprefix_t::mprefix_t(const boost::asio::ip::address& gaddr)
470 , m_len(VOM::mask_width(gaddr))
474 route::mprefix_t::mprefix_t(const boost::asio::ip::address& saddr,
475 const boost::asio::ip::address& gaddr)
478 , m_len(2 * VOM::mask_width(gaddr))
482 route::mprefix_t::mprefix_t(const boost::asio::ip::address& saddr,
483 const boost::asio::ip::address& gaddr,
491 route::mprefix_t::mprefix_t(const mprefix_t& o)
497 route::mprefix_t::mprefix_t()
504 route::mprefix_t::~mprefix_t()
508 const boost::asio::ip::address&
509 route::mprefix_t::grp_address() const
514 const boost::asio::ip::address&
515 route::mprefix_t::src_address() const
521 route::mprefix_t::mask_width() const
527 route::mprefix_t::l3_proto() const
529 if (m_gaddr.is_v6()) {
530 return (l3_proto_t::IPV6);
532 return (l3_proto_t::IPV4);
535 return (l3_proto_t::IPV4);
539 route::mprefix_t::operator=(const route::mprefix_t& o)
549 route::mprefix_t::operator<(const route::mprefix_t& o) const
551 if (m_len == o.m_len) {
552 if (m_saddr == o.m_saddr)
553 return (m_gaddr < o.m_gaddr);
555 return (m_saddr < o.m_saddr);
557 return (m_len < o.m_len);
562 route::mprefix_t::operator==(const route::mprefix_t& o) const
564 return (m_len == o.m_len && m_gaddr == o.m_gaddr && m_saddr == o.m_saddr);
568 route::mprefix_t::operator!=(const route::mprefix_t& o) const
570 return (!(*this == o));
574 route::mprefix_t::to_string() const
576 std::ostringstream s;
578 s << "(" << m_saddr.to_string() << "," << m_gaddr.to_string() << "/"
579 << std::to_string(m_len) << ")";
587 * fd.io coding-style-patch-verification: OFF
590 * eval: (c-set-style "mozilla")