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)
37 return (*this == IPV6);
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)
100 * The all Zeros prefix
102 const route::prefix_t route::prefix_t::ZERO("0.0.0.0", 0);
103 const route::prefix_t route::prefix_t::ZEROv6("::", 0);
105 route::prefix_t::prefix_t(const boost::asio::ip::address& addr, uint8_t len)
111 route::prefix_t::prefix_t(const boost::asio::ip::address& addr)
113 , m_len(VOM::mask_width(addr))
117 route::prefix_t::prefix_t(const std::string& s, uint8_t len)
118 : m_addr(boost::asio::ip::address::from_string(s))
123 route::prefix_t::prefix_t(const prefix_t& o)
129 route::prefix_t::prefix_t()
135 route::prefix_t::~prefix_t()
140 route::prefix_t::operator=(const route::prefix_t& o)
148 const boost::asio::ip::address&
149 route::prefix_t::address() const
155 route::prefix_t::mask_width() const
161 route::prefix_t::operator<(const route::prefix_t& o) const
163 if (m_len == o.m_len) {
164 return (m_addr < o.m_addr);
166 return (m_len < o.m_len);
171 route::prefix_t::operator==(const route::prefix_t& o) const
173 return (m_len == o.m_len && m_addr == o.m_addr);
177 route::prefix_t::operator!=(const route::prefix_t& o) const
179 return (!(*this == o));
183 route::prefix_t::to_string() const
185 std::ostringstream s;
187 s << m_addr.to_string() << "/" << std::to_string(m_len);
192 boost::asio::ip::address
193 from_bytes(uint8_t is_ip6, uint8_t* bytes)
195 boost::asio::ip::address addr;
198 std::array<uint8_t, 16> a;
199 std::copy(bytes, bytes + 16, std::begin(a));
200 boost::asio::ip::address_v6 v6(a);
203 std::array<uint8_t, 4> a;
204 std::copy(bytes, bytes + 4, std::begin(a));
205 boost::asio::ip::address_v4 v4(a);
212 route::prefix_t::prefix_t(uint8_t is_ip6, uint8_t* addr, uint8_t len)
213 : m_addr(from_bytes(is_ip6, addr))
218 to_bytes(const boost::asio::ip::address_v6& addr, uint8_t* array)
220 memcpy(array, addr.to_bytes().data(), 16);
224 to_bytes(const boost::asio::ip::address_v4& addr, uint8_t* array)
226 memcpy(array, addr.to_bytes().data(), 4);
230 to_bytes(const boost::asio::ip::address& addr, uint8_t* is_ip6, uint8_t* array)
234 to_bytes(addr.to_v6(), array);
237 to_bytes(addr.to_v4(), array);
242 mask_width(const boost::asio::ip::address& addr)
251 route::prefix_t::to_vpp(uint8_t* is_ip6, uint8_t* addr, uint8_t* len) const
254 to_bytes(m_addr, is_ip6, addr);
258 route::prefix_t::l3_proto() const
260 if (m_addr.is_v6()) {
261 return (l3_proto_t::IPV6);
263 return (l3_proto_t::IPV4);
266 return (l3_proto_t::IPV4);
270 operator<<(std::ostream& os, const route::prefix_t& pfx)
272 os << pfx.to_string();
277 boost::asio::ip::address_v4
278 operator|(const boost::asio::ip::address_v4& addr1,
279 const boost::asio::ip::address_v4& addr2)
282 a = addr1.to_ulong() | addr2.to_ulong();
283 boost::asio::ip::address_v4 addr(a);
287 boost::asio::ip::address_v4 operator&(const boost::asio::ip::address_v4& addr1,
288 const boost::asio::ip::address_v4& addr2)
291 a = addr1.to_ulong() & addr2.to_ulong();
292 boost::asio::ip::address_v4 addr(a);
296 boost::asio::ip::address_v4 operator~(const boost::asio::ip::address_v4& addr1)
299 a = ~addr1.to_ulong();
300 boost::asio::ip::address_v4 addr(a);
304 boost::asio::ip::address_v6
305 operator|(const boost::asio::ip::address_v6& addr1,
306 const boost::asio::ip::address_v6& addr2)
308 boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
309 boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();
311 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
312 ii < b1.max_size(); ii++) {
316 boost::asio::ip::address_v6 addr(b1);
320 boost::asio::ip::address_v6 operator&(const boost::asio::ip::address_v6& addr1,
321 const boost::asio::ip::address_v6& addr2)
323 boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
324 boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();
326 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
327 ii < b1.max_size(); ii++) {
331 boost::asio::ip::address_v6 addr(b1);
335 boost::asio::ip::address_v6 operator~(const boost::asio::ip::address_v6& addr1)
337 boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
339 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
340 ii < b1.max_size(); ii++) {
344 boost::asio::ip::address_v6 addr(b1);
347 boost::asio::ip::address
348 operator|(const boost::asio::ip::address& addr1,
349 const boost::asio::ip::address& addr2)
352 return (addr1.to_v6() | addr2.to_v6());
354 return (addr1.to_v4() | addr2.to_v4());
357 boost::asio::ip::address operator&(const boost::asio::ip::address& addr1,
358 const boost::asio::ip::address& addr2)
361 return (addr1.to_v6() & addr2.to_v6());
363 return (addr1.to_v4() & addr2.to_v4());
366 boost::asio::ip::address operator~(const boost::asio::ip::address& addr1)
369 return ~(addr1.to_v6());
371 return ~(addr1.to_v4());
374 boost::asio::ip::address
375 route::prefix_t::mask() const
377 if (m_addr.is_v6()) {
378 boost::asio::ip::address_v6::bytes_type b =
379 boost::asio::ip::address_v6::any().to_bytes();
381 uint8_t n_bits = mask_width();
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--) {
393 return (boost::asio::ip::address_v6(b));
397 a = ~((1 << (32 - mask_width())) - 1);
399 return (boost::asio::ip::address_v4(a));
404 route::prefix_t::low() const
408 pfx.m_addr = pfx.m_addr & pfx.mask();
414 route::prefix_t::high() const
418 pfx.m_addr = pfx.m_addr | ~pfx.mask();
426 * fd.io coding-style-patch-verification: ON
429 * eval: (c-set-style "mozilla")