VPP Object Model (VOM)
The VOM is a C++ library for use by clients/agents of VPP for programming
state. It uses the binary APIs to do so. Various other common client side
functions are also provided. Please see om.hpp for a more detailed description.
Change-Id: Ib756bfe99817093815a9e26ccf464aa5583fc523
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
Co-authored-by: Mohsin Kazmi <sykazmi@cisco.com>
diff --git a/src/vpp-api/vom/prefix.cpp b/src/vpp-api/vom/prefix.cpp
new file mode 100644
index 0000000..24fb57b
--- /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:
+ */