VOM: prefix bit fiddling 54/9754/2
authorNeale Ranns <neale.ranns@cisco.com>
Thu, 7 Dec 2017 16:48:02 +0000 (08:48 -0800)
committerNeale Ranns <nranns@cisco.com>
Fri, 8 Dec 2017 08:27:38 +0000 (08:27 +0000)
Change-Id: I4fbf4a574f455628d56e78cefc1a76adc06bc801
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
src/vpp-api/vom/prefix.cpp
src/vpp-api/vom/prefix.hpp
src/vpp-api/vom/route_domain.cpp
test/ext/vom_test.cpp

index 24fb57b..269c28f 100644 (file)
@@ -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
  *
index 3277929..e395e17 100644 (file)
@@ -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
  */
index c723f9f..e8c1e59 100644 (file)
@@ -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());
 }
index f12f871..0a687c5 100644 (file)
@@ -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()