diff options
Diffstat (limited to 'src/vpp-api/vom/prefix.cpp')
-rw-r--r-- | src/vpp-api/vom/prefix.cpp | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/src/vpp-api/vom/prefix.cpp b/src/vpp-api/vom/prefix.cpp new file mode 100644 index 00000000000..24fb57b34d2 --- /dev/null +++ b/src/vpp-api/vom/prefix.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <boost/algorithm/string.hpp> +#include <sstream> + +#include "vom/prefix.hpp" + +namespace VOM { +/* + * Keep this in sync with VPP's fib_protocol_t + */ +const l3_proto_t l3_proto_t::IPV4(0, "ipv4"); +const l3_proto_t l3_proto_t::IPV6(1, "ipv6"); +const l3_proto_t l3_proto_t::MPLS(2, "mpls"); + +l3_proto_t::l3_proto_t(int v, const std::string& s) + : enum_base<l3_proto_t>(v, s) +{ +} + +bool +l3_proto_t::is_ipv6() +{ + return (*this == IPV6); +} + +bool +l3_proto_t::is_ipv4() +{ + return (*this == IPV4); +} + +const l3_proto_t& +l3_proto_t::from_address(const boost::asio::ip::address& addr) +{ + if (addr.is_v6()) { + return IPV6; + } + + return IPV4; +} + +/* + * Keep this in sync with VPP's dpo_proto_t + */ +const nh_proto_t nh_proto_t::IPV4(0, "ipv4"); +const nh_proto_t nh_proto_t::IPV6(1, "ipv6"); +const nh_proto_t nh_proto_t::MPLS(2, "mpls"); +const nh_proto_t nh_proto_t::ETHERNET(3, "ethernet"); + +nh_proto_t::nh_proto_t(int v, const std::string& s) + : enum_base<nh_proto_t>(v, s) +{ +} + +const nh_proto_t& +nh_proto_t::from_address(const boost::asio::ip::address& addr) +{ + if (addr.is_v6()) { + return IPV6; + } + + return IPV4; +} + +/** + * The all Zeros prefix + */ +const route::prefix_t route::prefix_t::ZERO("0.0.0.0", 0); +const route::prefix_t route::prefix_t::ZEROv6("::", 0); + +route::prefix_t::prefix_t(const boost::asio::ip::address& addr, uint8_t len) + : m_addr(addr) + , m_len(len) +{ +} + +route::prefix_t::prefix_t(const boost::asio::ip::address& addr) + : m_addr(addr) + , m_len(VOM::mask_width(addr)) +{ +} + +route::prefix_t::prefix_t(const std::string& s, uint8_t len) + : m_addr(boost::asio::ip::address::from_string(s)) + , m_len(len) +{ +} + +route::prefix_t::prefix_t(const prefix_t& o) + : m_addr(o.m_addr) + , m_len(o.m_len) +{ +} + +route::prefix_t::prefix_t() + : m_addr() + , m_len(0) +{ +} + +route::prefix_t::~prefix_t() +{ +} + +route::prefix_t& +route::prefix_t::operator=(const route::prefix_t& o) +{ + m_addr = o.m_addr; + m_len = o.m_len; + + return (*this); +} + +const boost::asio::ip::address& +route::prefix_t::address() const +{ + return (m_addr); +} + +uint8_t +route::prefix_t::mask_width() const +{ + return (m_len); +} + +bool +route::prefix_t::operator<(const route::prefix_t& o) const +{ + if (m_len == o.m_len) { + return (m_addr < o.m_addr); + } else { + return (m_len < o.m_len); + } +} + +bool +route::prefix_t::operator==(const route::prefix_t& o) const +{ + return (m_len == o.m_len && m_addr == o.m_addr); +} + +bool +route::prefix_t::operator!=(const route::prefix_t& o) const +{ + return (!(*this == o)); +} + +std::string +route::prefix_t::to_string() const +{ + std::ostringstream s; + + s << m_addr.to_string() << "/" << std::to_string(m_len); + + return (s.str()); +} + +boost::asio::ip::address +from_bytes(uint8_t is_ip6, uint8_t* bytes) +{ + boost::asio::ip::address addr; + + if (is_ip6) { + std::array<uint8_t, 16> a; + std::copy(bytes, bytes + 16, std::begin(a)); + boost::asio::ip::address_v6 v6(a); + addr = v6; + } else { + std::array<uint8_t, 4> a; + std::copy(bytes, bytes + 4, std::begin(a)); + boost::asio::ip::address_v4 v4(a); + addr = v4; + } + + return (addr); +} + +route::prefix_t::prefix_t(uint8_t is_ip6, uint8_t* addr, uint8_t len) + : m_addr(from_bytes(is_ip6, addr)) + , m_len(len) +{ +} +void +to_bytes(const boost::asio::ip::address_v6& addr, uint8_t* array) +{ + memcpy(array, addr.to_bytes().data(), 16); +} + +void +to_bytes(const boost::asio::ip::address_v4& addr, uint8_t* array) +{ + memcpy(array, addr.to_bytes().data(), 4); +} + +void +to_bytes(const boost::asio::ip::address& addr, uint8_t* is_ip6, uint8_t* array) +{ + if (addr.is_v6()) { + *is_ip6 = 1; + to_bytes(addr.to_v6(), array); + } else { + *is_ip6 = 0; + to_bytes(addr.to_v4(), array); + } +} + +uint32_t +mask_width(const boost::asio::ip::address& addr) +{ + if (addr.is_v6()) { + return 128; + } + return 32; +} + +void +route::prefix_t::to_vpp(uint8_t* is_ip6, uint8_t* addr, uint8_t* len) const +{ + *len = m_len; + to_bytes(m_addr, is_ip6, addr); +} + +l3_proto_t +route::prefix_t::l3_proto() const +{ + if (m_addr.is_v6()) { + return (l3_proto_t::IPV6); + } else { + return (l3_proto_t::IPV4); + } + + return (l3_proto_t::IPV4); +} + +std::ostream& +operator<<(std::ostream& os, const route::prefix_t& pfx) +{ + os << pfx.to_string(); + + return (os); +} + +boost::asio::ip::address_v4 +operator|(const boost::asio::ip::address_v4& addr1, + const boost::asio::ip::address_v4& addr2) +{ + uint32_t a; + a = addr1.to_ulong() | addr2.to_ulong(); + boost::asio::ip::address_v4 addr(a); + return (addr); +} + +boost::asio::ip::address_v4 operator&(const boost::asio::ip::address_v4& addr1, + const boost::asio::ip::address_v4& addr2) +{ + uint32_t a; + a = addr1.to_ulong() & addr2.to_ulong(); + boost::asio::ip::address_v4 addr(a); + return (addr); +} + +boost::asio::ip::address_v4 operator~(const boost::asio::ip::address_v4& addr1) +{ + uint32_t a; + a = ~addr1.to_ulong(); + boost::asio::ip::address_v4 addr(a); + return (addr); +} + +boost::asio::ip::address_v4 +route::prefix_t::mask() const +{ + uint32_t a; + + a = ~((1 << mask_width()) - 1); + boost::asio::ip::address_v4 addr(a); + return (addr); +} + +boost::asio::ip::address_v4 +route::prefix_t::low() const +{ + boost::asio::ip::address_v4 low; + low = address().to_v4() & mask(); + return (low); +} + +boost::asio::ip::address_v4 +route::prefix_t::high() const +{ + boost::asio::ip::address_v4 high; + high = address().to_v4() | ~mask(); + return (high); +} +} +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "mozilla") + * End: + */ |