From d3464b5b4aeea0804e6cc3e1b220673e98d9c4a5 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 7 Dec 2017 08:48:02 -0800 Subject: [PATCH 1/1] VOM: prefix bit fiddling Change-Id: I4fbf4a574f455628d56e78cefc1a76adc06bc801 Signed-off-by: Neale Ranns --- src/vpp-api/vom/prefix.cpp | 123 ++++++++++++++++++++++++++++++++++----- src/vpp-api/vom/prefix.hpp | 22 ++++++- src/vpp-api/vom/route_domain.cpp | 4 +- test/ext/vom_test.cpp | 40 ++++++++++++- 4 files changed, 169 insertions(+), 20 deletions(-) diff --git a/src/vpp-api/vom/prefix.cpp b/src/vpp-api/vom/prefix.cpp index 24fb57b34d2..269c28f1f54 100644 --- a/src/vpp-api/vom/prefix.cpp +++ b/src/vpp-api/vom/prefix.cpp @@ -281,32 +281,127 @@ boost::asio::ip::address_v4 operator~(const boost::asio::ip::address_v4& addr1) return (addr); } -boost::asio::ip::address_v4 -route::prefix_t::mask() const +boost::asio::ip::address_v6 +operator|(const boost::asio::ip::address_v6& addr1, + const boost::asio::ip::address_v6& addr2) { - uint32_t a; + boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes(); + boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes(); - a = ~((1 << mask_width()) - 1); - boost::asio::ip::address_v4 addr(a); + for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0; + ii < b1.max_size(); ii++) { + b1[ii] |= b2[ii]; + } + + boost::asio::ip::address_v6 addr(b1); return (addr); } -boost::asio::ip::address_v4 +boost::asio::ip::address_v6 operator&(const boost::asio::ip::address_v6& addr1, + const boost::asio::ip::address_v6& addr2) +{ + boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes(); + boost::asio::ip::address_v6::bytes_type b2 = addr2.to_bytes(); + + for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0; + ii < b1.max_size(); ii++) { + b1[ii] &= b2[ii]; + } + + boost::asio::ip::address_v6 addr(b1); + return (addr); +} + +boost::asio::ip::address_v6 operator~(const boost::asio::ip::address_v6& addr1) +{ + boost::asio::ip::address_v6::bytes_type b1 = addr1.to_bytes(); + + for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0; + ii < b1.max_size(); ii++) { + b1[ii] = ~b1[ii]; + } + + boost::asio::ip::address_v6 addr(b1); + return (addr); +} +boost::asio::ip::address +operator|(const boost::asio::ip::address& addr1, + const boost::asio::ip::address& addr2) +{ + if (addr1.is_v6()) + return (addr1.to_v6() | addr2.to_v6()); + else + return (addr1.to_v4() | addr2.to_v4()); +} + +boost::asio::ip::address operator&(const boost::asio::ip::address& addr1, + const boost::asio::ip::address& addr2) +{ + if (addr1.is_v6()) + return (addr1.to_v6() & addr2.to_v6()); + else + return (addr1.to_v4() & addr2.to_v4()); +} + +boost::asio::ip::address operator~(const boost::asio::ip::address& addr1) +{ + if (addr1.is_v6()) + return ~(addr1.to_v6()); + else + return ~(addr1.to_v4()); +} + +boost::asio::ip::address +route::prefix_t::mask() const +{ + if (m_addr.is_v6()) { + boost::asio::ip::address_v6::bytes_type b = + boost::asio::ip::address_v6::any().to_bytes(); + + uint8_t n_bits = mask_width(); + + for (boost::asio::ip::address_v6::bytes_type::size_type ii = 0; + ii < b.max_size(); ii++) { + for (int8_t bit = 7; bit >= 0 && n_bits; bit--) { + b[ii] |= (1 << bit); + n_bits--; + } + if (!n_bits) + break; + } + + return (boost::asio::ip::address_v6(b)); + } else { + uint32_t a; + + a = ~((1 << (32 - mask_width())) - 1); + + return (boost::asio::ip::address_v4(a)); + } +} + +route::prefix_t route::prefix_t::low() const { - boost::asio::ip::address_v4 low; - low = address().to_v4() & mask(); - return (low); + prefix_t pfx(*this); + + pfx.m_addr = pfx.m_addr & pfx.mask(); + + return (pfx); } -boost::asio::ip::address_v4 +route::prefix_t route::prefix_t::high() const { - boost::asio::ip::address_v4 high; - high = address().to_v4() | ~mask(); - return (high); -} + prefix_t pfx(*this); + + pfx.m_addr = pfx.m_addr | ~pfx.mask(); + + return (pfx); } + +}; // namespace VOM + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vpp-api/vom/prefix.hpp b/src/vpp-api/vom/prefix.hpp index 3277929bcce..e395e1760ca 100644 --- a/src/vpp-api/vom/prefix.hpp +++ b/src/vpp-api/vom/prefix.hpp @@ -170,17 +170,17 @@ public: /** * Return a address representation of the mask, e.g. 255.255.0.0 */ - boost::asio::ip::address_v4 mask() const; + boost::asio::ip::address mask() const; /** * get the lowest address in the prefix */ - boost::asio::ip::address_v4 low() const; + prefix_t low() const; /** * Get the highest address in the prefix */ - boost::asio::ip::address_v4 high() const; + prefix_t high() const; /** * Get the L3 protocol @@ -208,6 +208,22 @@ boost::asio::ip::address_v4 operator&(const boost::asio::ip::address_v4& addr1, boost::asio::ip::address_v4 operator~(const boost::asio::ip::address_v4& addr1); +boost::asio::ip::address_v6 operator|(const boost::asio::ip::address_v6& addr1, + const boost::asio::ip::address_v6& addr2); + +boost::asio::ip::address_v6 operator&(const boost::asio::ip::address_v6& addr1, + const boost::asio::ip::address_v6& addr2); + +boost::asio::ip::address_v6 operator~(const boost::asio::ip::address_v6& addr1); + +boost::asio::ip::address operator|(const boost::asio::ip::address& addr1, + const boost::asio::ip::address& addr2); + +boost::asio::ip::address operator&(const boost::asio::ip::address& addr1, + const boost::asio::ip::address& addr2); + +boost::asio::ip::address operator~(const boost::asio::ip::address& addr1); + /** * Ostream printer for prefix_t */ diff --git a/src/vpp-api/vom/route_domain.cpp b/src/vpp-api/vom/route_domain.cpp index c723f9f31b6..e8c1e598899 100644 --- a/src/vpp-api/vom/route_domain.cpp +++ b/src/vpp-api/vom/route_domain.cpp @@ -101,8 +101,8 @@ route_domain::to_string() const { std::ostringstream s; s << "route-domain:[" - << "table-id:" << m_table_id << " v4:" << m_hw_v4 << " v6:" << m_hw_v6 - << "]"; + << "table-id:" << m_table_id << " v4:" << m_hw_v4.to_string() + << " v6:" << m_hw_v6.to_string() << "]"; return (s.str()); } diff --git a/test/ext/vom_test.cpp b/test/ext/vom_test.cpp index f12f871a904..0a687c5017c 100644 --- a/test/ext/vom_test.cpp +++ b/test/ext/vom_test.cpp @@ -472,7 +472,7 @@ public: } }; -BOOST_AUTO_TEST_SUITE(VppOM_test) +BOOST_AUTO_TEST_SUITE(vom) #define TRY_CHECK_RC(stmt) \ { \ @@ -1594,4 +1594,42 @@ BOOST_AUTO_TEST_CASE(test_interface_route_domain_change) { TRY_CHECK(OM::remove(rene)); } +BOOST_AUTO_TEST_CASE(test_prefixes) { + route::prefix_t p6_s_16(boost::asio::ip::address::from_string("2001::"), 16); + + BOOST_CHECK(p6_s_16.mask() == boost::asio::ip::address::from_string("ffff::")); + + route::prefix_t p6_s_17(boost::asio::ip::address::from_string("2001:ff00::"), 17); + + BOOST_CHECK(p6_s_17.mask() == boost::asio::ip::address::from_string("ffff:8000::")); + BOOST_CHECK(p6_s_17.low().address() == boost::asio::ip::address::from_string("2001:8000::")); + + route::prefix_t p6_s_15(boost::asio::ip::address::from_string("2001:ff00::"), 15); + BOOST_CHECK(p6_s_15.mask() == boost::asio::ip::address::from_string("fffe::")); + BOOST_CHECK(p6_s_15.low().address() == boost::asio::ip::address::from_string("2000::")); + + route::prefix_t p4_s_16(boost::asio::ip::address::from_string("192.168.0.0"), 16); + + BOOST_CHECK(p4_s_16.mask() == boost::asio::ip::address::from_string("255.255.0.0")); + + route::prefix_t p4_s_17(boost::asio::ip::address::from_string("192.168.127.0"), 17); + + BOOST_CHECK(p4_s_17.mask() == boost::asio::ip::address::from_string("255.255.128.0")); + BOOST_CHECK(p4_s_17.low().address() == boost::asio::ip::address::from_string("192.168.0.0")); + BOOST_CHECK(p4_s_17.high().address() == boost::asio::ip::address::from_string("192.168.127.255")); + + route::prefix_t p4_s_15(boost::asio::ip::address::from_string("192.168.255.255"), 15); + + BOOST_CHECK(p4_s_15.mask() == boost::asio::ip::address::from_string("255.254.0.0")); + BOOST_CHECK(p4_s_15.low().address() == boost::asio::ip::address::from_string("192.168.0.0")); + BOOST_CHECK(p4_s_15.high().address() == boost::asio::ip::address::from_string("192.169.255.255")); + + route::prefix_t p4_s_32(boost::asio::ip::address::from_string("192.168.1.1"), 32); + + BOOST_CHECK(p4_s_32.mask() == boost::asio::ip::address::from_string("255.255.255.255")); + BOOST_CHECK(p4_s_32.low().address() == boost::asio::ip::address::from_string("192.168.1.1")); + BOOST_CHECK(p4_s_32.high().address() == boost::asio::ip::address::from_string("192.168.1.1")); + +} + BOOST_AUTO_TEST_SUITE_END() -- 2.16.6