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 operator<<(std::ostream& os, const l3_proto_t& l3p)
59 os << l3p.to_string();
64 * Keep this in sync with VPP's dpo_proto_t
66 const nh_proto_t nh_proto_t::IPV4(0, "ipv4");
67 const nh_proto_t nh_proto_t::IPV6(1, "ipv6");
68 const nh_proto_t nh_proto_t::MPLS(2, "mpls");
69 const nh_proto_t nh_proto_t::ETHERNET(3, "ethernet");
71 nh_proto_t::nh_proto_t(int v, const std::string& s)
72 : enum_base<nh_proto_t>(v, s)
77 nh_proto_t::from_address(const boost::asio::ip::address& addr)
87 * The all Zeros prefix
89 const route::prefix_t route::prefix_t::ZERO("0.0.0.0", 0);
90 const route::prefix_t route::prefix_t::ZEROv6("::", 0);
92 route::prefix_t::prefix_t(const boost::asio::ip::address& addr, uint8_t len)
98 route::prefix_t::prefix_t(const boost::asio::ip::address& addr)
100 , m_len(VOM::mask_width(addr))
104 route::prefix_t::prefix_t(const std::string& s, uint8_t len)
105 : m_addr(boost::asio::ip::address::from_string(s))
110 route::prefix_t::prefix_t(const prefix_t& o)
116 route::prefix_t::prefix_t()
122 route::prefix_t::~prefix_t()
127 route::prefix_t::operator=(const route::prefix_t& o)
135 const boost::asio::ip::address&
136 route::prefix_t::address() const
142 route::prefix_t::mask_width() const
148 route::prefix_t::operator<(const route::prefix_t& o) const
150 if (m_len == o.m_len) {
151 return (m_addr < o.m_addr);
153 return (m_len < o.m_len);
158 route::prefix_t::operator==(const route::prefix_t& o) const
160 return (m_len == o.m_len && m_addr == o.m_addr);
164 route::prefix_t::operator!=(const route::prefix_t& o) const
166 return (!(*this == o));
170 route::prefix_t::to_string() const
172 std::ostringstream s;
174 s << m_addr.to_string() << "/" << std::to_string(m_len);
179 boost::asio::ip::address
180 from_bytes(uint8_t is_ip6, uint8_t* bytes)
182 boost::asio::ip::address addr;
185 std::array<uint8_t, 16> a;
186 std::copy(bytes, bytes + 16, std::begin(a));
187 boost::asio::ip::address_v6 v6(a);
190 std::array<uint8_t, 4> a;
191 std::copy(bytes, bytes + 4, std::begin(a));
192 boost::asio::ip::address_v4 v4(a);
199 route::prefix_t::prefix_t(uint8_t is_ip6, uint8_t* addr, uint8_t len)
200 : m_addr(from_bytes(is_ip6, addr))
205 to_bytes(const boost::asio::ip::address_v6& addr, uint8_t* array)
207 memcpy(array, addr.to_bytes().data(), 16);
211 to_bytes(const boost::asio::ip::address_v4& addr, uint8_t* array)
213 memcpy(array, addr.to_bytes().data(), 4);
217 to_bytes(const boost::asio::ip::address& addr, uint8_t* is_ip6, uint8_t* array)
221 to_bytes(addr.to_v6(), array);
224 to_bytes(addr.to_v4(), array);
229 mask_width(const boost::asio::ip::address& addr)
238 route::prefix_t::to_vpp(uint8_t* is_ip6, uint8_t* addr, uint8_t* len) const
241 to_bytes(m_addr, is_ip6, addr);
245 route::prefix_t::l3_proto() const
247 if (m_addr.is_v6()) {
248 return (l3_proto_t::IPV6);
250 return (l3_proto_t::IPV4);
253 return (l3_proto_t::IPV4);
257 operator<<(std::ostream& os, const route::prefix_t& pfx)
259 os << pfx.to_string();
264 boost::asio::ip::address_v4
265 operator|(const boost::asio::ip::address_v4& addr1,
266 const boost::asio::ip::address_v4& addr2)
269 a = addr1.to_ulong() | addr2.to_ulong();
270 boost::asio::ip::address_v4 addr(a);
274 boost::asio::ip::address_v4 operator&(const boost::asio::ip::address_v4& addr1,
275 const boost::asio::ip::address_v4& addr2)
278 a = addr1.to_ulong() & addr2.to_ulong();
279 boost::asio::ip::address_v4 addr(a);
283 boost::asio::ip::address_v4 operator~(const boost::asio::ip::address_v4& addr1)
286 a = ~addr1.to_ulong();
287 boost::asio::ip::address_v4 addr(a);
291 boost::asio::ip::address_v6
292 operator|(const boost::asio::ip::address_v6& addr1,
293 const boost::asio::ip::address_v6& addr2)
295 boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
296 boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();
298 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
299 ii < b1.max_size(); ii++) {
303 boost::asio::ip::address_v6 addr(b1);
307 boost::asio::ip::address_v6 operator&(const boost::asio::ip::address_v6& addr1,
308 const boost::asio::ip::address_v6& addr2)
310 boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes();
311 boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes();
313 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
314 ii < b1.max_size(); ii++) {
318 boost::asio::ip::address_v6 addr(b1);
322 boost::asio::ip::address_v6 operator~(const boost::asio::ip::address_v6& addr1)
324 boost::asio::ip::address_v6::bytes_type b1 = addr1.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);
334 boost::asio::ip::address
335 operator|(const boost::asio::ip::address& addr1,
336 const boost::asio::ip::address& addr2)
339 return (addr1.to_v6() | addr2.to_v6());
341 return (addr1.to_v4() | addr2.to_v4());
344 boost::asio::ip::address operator&(const boost::asio::ip::address& addr1,
345 const boost::asio::ip::address& addr2)
348 return (addr1.to_v6() & addr2.to_v6());
350 return (addr1.to_v4() & addr2.to_v4());
353 boost::asio::ip::address operator~(const boost::asio::ip::address& addr1)
356 return ~(addr1.to_v6());
358 return ~(addr1.to_v4());
361 boost::asio::ip::address
362 route::prefix_t::mask() const
364 if (m_addr.is_v6()) {
365 boost::asio::ip::address_v6::bytes_type b =
366 boost::asio::ip::address_v6::any().to_bytes();
368 uint8_t n_bits = mask_width();
370 for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0;
371 ii < b.max_size(); ii++) {
372 for (int8_t bit = 7; bit >= 0 && n_bits; bit--) {
380 return (boost::asio::ip::address_v6(b));
384 a = ~((1 << (32 - mask_width())) - 1);
386 return (boost::asio::ip::address_v4(a));
391 route::prefix_t::low() const
395 pfx.m_addr = pfx.m_addr & pfx.mask();
401 route::prefix_t::high() const
405 pfx.m_addr = pfx.m_addr | ~pfx.mask();
413 * fd.io coding-style-patch-verification: ON
416 * eval: (c-set-style "mozilla")