Socket/Protocols: Replace uint64 with EUI64 in address classes
g0dil [Sun, 17 May 2009 22:18:20 +0000 (22:18 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1213 270642c3-0616-0410-b53a-bc976706d245

Socket/Protocols/INet/INet6Address.cci
Socket/Protocols/INet/INet6Address.hh
Socket/Protocols/INet/INet6Address.test.cc
Socket/Protocols/Raw/EUI64.cci
Socket/Protocols/Raw/EUI64.hh
Socket/Protocols/Raw/EUI64.test.cc
Socket/Protocols/Raw/MACAddress.cc
Socket/Protocols/Raw/MACAddress.hh
Socket/Protocols/Raw/MACAddress.test.cc

index 9a71c7b..f94c0d7 100644 (file)
@@ -88,32 +88,25 @@ prefix_ senf::INet6Address senf::INet6Address::from_mac(senf::MACAddress const &
     return addr;
 }
 
-prefix_ boost::uint64_t senf::INet6Address::network()
+prefix_ senf::INet6Address senf::INet6Address::from_eui64(senf::EUI64 const & eui)
+{
+    INet6Address addr;
+    addr[0] = 0xfe;
+    addr[1] = 0x80;
+    std::copy(eui.begin(), eui.end(), addr.begin()+8);
+    return addr;
+}
+
+prefix_ senf::INet6Network senf::INet6Address::network()
     const
 {
-    return
-        ((boost::uint64_t((*this)[0]) & 0xff) << 56 ) |
-        ((boost::uint64_t((*this)[1]) & 0xff) << 48 ) |
-        ((boost::uint64_t((*this)[2]) & 0xff) << 40 ) |
-        ((boost::uint64_t((*this)[3]) & 0xff) << 32 ) |
-        ((boost::uint64_t((*this)[4]) & 0xff) << 24 ) |
-        ((boost::uint64_t((*this)[5]) & 0xff) << 16 ) |
-        ((boost::uint64_t((*this)[6]) & 0xff) <<  8 ) |
-        ((boost::uint64_t((*this)[7]) & 0xff)       );
+    return senf::INet6Network(*this, 64);
 }
 
-prefix_ boost::uint64_t senf::INet6Address::id()
+prefix_ senf::EUI64 senf::INet6Address::id()
     const
 {
-    return
-        ((boost::uint64_t((*this)[ 8]) & 0xff) << 56 ) |
-        ((boost::uint64_t((*this)[ 9]) & 0xff) << 48 ) |
-        ((boost::uint64_t((*this)[10]) & 0xff) << 40 ) |
-        ((boost::uint64_t((*this)[11]) & 0xff) << 32 ) |
-        ((boost::uint64_t((*this)[12]) & 0xff) << 24 ) |
-        ((boost::uint64_t((*this)[13]) & 0xff) << 16 ) |
-        ((boost::uint64_t((*this)[14]) & 0xff) <<  8 ) |
-        ((boost::uint64_t((*this)[15]) & 0xff)       );
+    return senf::EUI64::from_data(begin()+8);
 }
 
 prefix_ bool senf::INet6Address::universalId()
@@ -166,7 +159,7 @@ prefix_ bool senf::INet6Address::unicast()
     return ! multicast();
 }
 
-prefix_ bool senf::INet6Address::hasEuid64()
+prefix_ bool senf::INet6Address::hasEUI64()
     const
 {
     return unicast() && ((*this)[0]&0xE0u) != 0u;
index 3eb7094..a80e0ad 100644 (file)
@@ -38,6 +38,7 @@
 #include "INet4Address.hh"
 #include "../AddressExceptions.hh"
 #include "../Raw/MACAddress.hh"
+#include "../Raw/EUI64.hh"
 
 //#include "INet6Address.mpp"
 #include "INet6Address.ih"
@@ -45,6 +46,8 @@
 
 namespace senf {
 
+    class INet6Network;
+
     /** \brief INet6 network address
 
         This implementation of an INet6 address is based strictly on
@@ -208,6 +211,11 @@ namespace senf {
                                         ///< Construct a link-local INet6 address
                                         /**< This will construct a link local address of the form
                                              <tt>fe80::xxxx:xxff:fexx:xxxx</tt>. */
+
+        static INet6Address from_eui64(senf::EUI64 const & eui);
+                                        ///< Construct link-local INet6 address
+                                        /**< This will construct a link local address of the form
+                                             <tt>fe80::xxxx:xxxx:xxxx:xxxx</tt>. */
         
         in6_addr toin6_addr() const;    ///< get the linux in6_addr struct (convinience only)
 
@@ -216,9 +224,9 @@ namespace senf {
         ///\name Accessors
         ///@{
 
-        boost::uint64_t network() const; ///< Return 64bit network part
-        bool hasEuid64() const;         ///< \c true, if address is based on an EUID-64
-        boost::uint64_t id() const;     ///< Return interface id (EUID-64)
+        INet6Network network() const; ///< Return <tt>/64</tt> Network of this address
+        bool hasEUI64() const;          ///< \c true, if address is based on an EUID-64
+        EUI64 id() const;               ///< Return interface id (EUID-64)
         bool universalId() const;       ///< \c true, if the id() is universally assigned
         bool groupId() const;           ///< \c true, if the id()'s \a group bit is set
 
index f56ce6e..241eeda 100644 (file)
@@ -86,10 +86,11 @@ BOOST_AUTO_UNIT_TEST(inet6Address)
 
     {
         INet6Address addr (INet6Address::from_string("2001:dead:beef::1002:3004"));
-        BOOST_CHECK_EQUAL( addr.network(), 0x2001deadbeef0000llu );
-        BOOST_CHECK_EQUAL( addr.id(), 0x0000000010023004llu );
-        BOOST_CHECK( addr.hasEuid64() );
-        BOOST_CHECK( ! INet6Address::from_inet4address(INet4Address(0x01020304)).hasEuid64() );
+        BOOST_CHECK_EQUAL( addr.network(), senf::INet6Network(
+                               senf::INet6Address(0x2001u,0xdeadu, 0xbeef),64) );
+        BOOST_CHECK_EQUAL( addr.id(), senf::EUI64(0x0000000010023004llu) );
+        BOOST_CHECK( addr.hasEUI64() );
+        BOOST_CHECK( ! INet6Address::from_inet4address(INet4Address(0x01020304)).hasEUI64() );
         BOOST_CHECK( ! addr.universalId() );
         BOOST_CHECK( ! addr.groupId() );
         BOOST_CHECK( addr.unicast() );
index 6b40b7f..6f51aa1 100644 (file)
@@ -68,6 +68,18 @@ prefix_ bool senf::EUI64::isMACCompatible()
     return (*this)[3] == 0xffu && (*this)[4] == 0xfeu;
 }
 
+prefix_ bool senf::EUI64::local()
+    const
+{
+    return (*this)[0]&0x02;
+}
+
+prefix_ bool senf::EUI64::group()
+    const
+{
+    return (*this)[0]&0x01;
+}
+
 prefix_ bool senf::EUI64::boolean_test()
     const
 {
index f1fc844..aa70d01 100644 (file)
@@ -52,7 +52,7 @@ namespace senf {
         <tr><td><tt>std::string</tt></td>
                 <td><tt>senf::EUI64::from_string("1a:2b:3c:4d-5f:60:71:82")</tt><br/>
                     <tt>senf::str(</tt><i>eui64</i><tt>)</tt></td></tr>
-        <tr><td><i>raw data</i></td>
+        <tr><td><i>raw data</i><br/>&nbsp;&nbsp;&nbsp;&nbsp;(8 bytes)</td>
                 <td><tt>senf::EUI64::from_data(</tt><i>iterator</i><tt>)</tt><br/>
                     <i>eui64</i><tt>.begin()</tt></td></tr>
         <tr><td>senf::MACAddress<br/>&nbsp;&nbsp;&nbsp;&nbsp;(aka EUI-48)</td>
@@ -60,7 +60,16 @@ namespace senf {
                     <tt>senf::MACAddress::from_eui64(</tt><i>eui64</i><tt>)</tt></td></tr>
         </table>
 
-        Additionally, a senf::MACAddress can be converted into an EUI64 and vice versa.
+        Since senf::EUI64 is based on \c boost::array, you can access the raw data bytes of the
+        address using \c begin(), \c end() or \c operator[]:
+        \code
+        senf::EUI64 eui64 (...);
+        std::vector<char> data;
+        data.resize(8);
+        std::copy(eui64.begin(), eui64.end(), data.begin()); // Copy 8 bytes
+        \endcode
+
+        \see <a href="http://tools.ietf.org/html/rfc4291">RFC 4291</a>
 
         \ingroup addr_group
      */
@@ -86,7 +95,8 @@ namespace senf {
         static EUI64 from_string(std::string const & s);
                                         ///< Construct EUI-64 from string representation
                                         /**< The string representation consists of 8 octets in
-                                             hexadecimal notation spearated by ':' or '-' */
+                                             hexadecimal notation spearated by ':' or '-'
+                                             \throws senf::AddressSyntaxException */
         template <class InputIterator>
         static EUI64 from_data(InputIterator i);
                                         ///< Construct EUI-64 from 8 data octets
@@ -99,6 +109,13 @@ namespace senf {
         bool isMACCompatible() const;   ///< \c true, if EUI64 is MAC compatible, \c false otherwise
                                         /**< An EUI64 is MAC compatible if bytes 4th and 5th byte
                                              (in network byte order) are 0xfffe. */
+        bool local() const;             ///< \c true if the \e local bit is set, \c false otherwise
+                                        /**< The \e local bit is the second least significant bit of
+                                             the first octet (bit 6 in standard RFC bit numbering).
+                                          */
+        bool group() const;             ///< \c true if the \e group bit is set, \c false otherwise
+                                        /**< The \e group bit is the least significant bit of the
+                                             first octed (bit 7 in standard RFC bit numbering). */
         bool boolean_test() const;      ///< \c true, if EUI64 is != 0, \c false otherwise
         boost::uint64_t uint64() const; ///< Return EUI64 as integer number
     };
index 3c53281..a36051d 100644 (file)
@@ -46,6 +46,8 @@ BOOST_AUTO_UNIT_TEST(eui64)
     BOOST_CHECK_EQUAL_COLLECTIONS( eui.begin(), eui.end(), data, data+sizeof(data)/sizeof(data[0]) );
     BOOST_CHECK( eui );
     BOOST_CHECK( eui.isMACCompatible() );
+    BOOST_CHECK( ! eui.local() );
+    BOOST_CHECK( ! eui.group() );
     BOOST_CHECK_EQUAL( eui.uint64(), 0x102030fffe405060ull );
 
     BOOST_CHECK_EQUAL( eui, senf::EUI64::from_data(data) );
index 43a2882..53a96fb 100644 (file)
@@ -32,6 +32,7 @@
 #include <sstream>
 #include <boost/io/ios_state.hpp>
 #include "ParseString.hh"
+#include "EUI64.hh"
 
 //#include "MACAddress.mpp"
 #define prefix_
@@ -47,17 +48,17 @@ prefix_ senf::MACAddress::MACAddress senf::MACAddress::from_string(std::string c
     return mac;
 }
 
-prefix_ senf::MACAddress senf::MACAddress::from_eui64(boost::uint64_t v)
+prefix_ senf::MACAddress senf::MACAddress::from_eui64(senf::EUI64 const & eui)
 {
-    if ( boost::uint16_t(v>>24)  != 0xfffe )
+    if (eui[3] != 0xffu || eui[4] != 0xfeu)
         throw AddressSyntaxException();
     MACAddress mac (senf::noinit);
-    mac[0] = boost::uint8_t( v>>56 );
-    mac[1] = boost::uint8_t( v>>48 );
-    mac[2] = boost::uint8_t( v>>40 );
-    mac[3] = boost::uint8_t( v>>16 );
-    mac[4] = boost::uint8_t( v>> 8 );
-    mac[5] = boost::uint8_t( v     );
+    mac[0] = eui[0];
+    mac[1] = eui[1];
+    mac[2] = eui[2];
+    mac[3] = eui[5];
+    mac[4] = eui[6];
+    mac[5] = eui[7];
     return mac;
 }
 
index 64049dd..cc4a6ba 100644 (file)
 
 namespace senf {
 
+    class EUI64;
+
     /** \brief Ethernet MAC address
 
-        The Ethernet MAC is modelled as a fixed-size container/sequence of 6 bytes.
-
-        The following statements all create the same MAC address <code>00:1A:2B:3C:4D:5F</code>
-        \code
-        // Used to construct constant MAC addresses
-        MACAddress(0x001A2B3C4D5Full)
-
-        // Construct a MAC address from it's string representation:
-        MACAddress::from_string("00:1a:2b:3c:4d:5f")   // case is ignored
-        MACAddress::from_string("00-1A-2B-3C-4D-5F")   // '-' as separator is allowed too
-
-        // Construct a MAC address from raw data.  'from_data' takes an arbitrary iterator (e.g. a
-        // pointer) as argument. Here we use a fixed array but normally you will need this to build
-        // a MAC address in a packet parser
-        char rawBytes[] = { 0x00, 0x1A, 0x2B, 0x3C, 0x4D, 0x5F };
-        MACAddress::from_data(rawBytes)
-
-        // Construct a MAC from the EUID64 as used by INet6 interfaces.  The eui64 will come from an
-        // INet6 address:
-        MACAddress::from_eui64(0x001A2BFFFE3C4D5Full)
-        MACAddress::from_eui64(
-            INet6Address(0x2001u,0xDB8u,0x1u,0x0u,0x001Au,0x2BFFu,0xFE3Cu,0x3D5Fu).id())
-        \endcode
+        The Ethernet MAC is modelled as a fixed-size container/sequence of 6 bytes. A MACAddress can
+        be converted from/to the following representations
+
+        <table class="senf">
+        <tr><td><tt>boost::uint64_t</tt></td>
+                <td><tt>senf::MACAddress(0x112233445566ull)</tt><br/>
+                    <i>mac</i><tt>.uint64()</tt></td></tr>
+        <tr><td><tt>std::string</tt></td>
+                <td><tt>senf::MACAddress::from_string("11:22:33:44:55:66")</tt><br/>
+                    <tt>senf::str(</tt><i>mac</i><tt>)</tt></td></tr>
+        <tr><td><i>raw data</i><br/>&nbsp;&nbsp;&nbsp;&nbsp;(6 bytes)</td>
+                <td><tt>senf::MACAddress::from_data(</tt><i>iterator</i><tt>)</tt><br/>
+                    <i>mac</i><tt>.begin()</tt></td></tr>
+        <tr><td>senf::EUI64</td>
+                <td><tt>senf::MACAddress::from_eui64(</tt><i>eui64</i><tt>)</tt><br/>
+                    <tt>senf::EUI64::from_mac(</tt><i>mac</i><tt>)</tt></td></tr>
+        </table>
 
         Since MACAddress is based on \c boost::array, you can access the raw data bytes of the
         address using \c begin(), \c end() or \c operator[]:
         \code
-        MACAddress mac = ...;
-        Packet::iterator i = ...;
-
-        std::copy(mac.begin(), mac.end(), i); // Copies 6 bytes
+        senf::MACAddress mac (...);
+        std::vector<char> data;
+        data.resize(6);
+        std::copy(mac.begin(), mac.end(), data.begin()); // Copy 6 bytes
         \endcode
 
         \implementation We awkwardly need to use static named constructors (<tt>from_</tt> members)
@@ -110,7 +106,7 @@ namespace senf {
                                              \pre The input range at \a i must have a size of at
                                                  least 6 elements. */
 
-        static MACAddress from_eui64(boost::uint64_t v);
+        static MACAddress from_eui64(senf::EUI64 const & eui);
                                         ///< Construct address from EUI-64
                                         /**< This constructor takes an EUI-64 value and converts it
                                              to a MAC address. This conversion is only possible, if
@@ -120,7 +116,7 @@ namespace senf {
                                                  compatible EUI-64. */
 
         bool local() const;             ///< \c true, if address is locally administered
-        bool multicast() const;             ///< \c true, if address is a group/multicast address
+        bool multicast() const;         ///< \c true, if address is a group/multicast address
         bool broadcast() const;         ///< \c true, if address is the broadcast address
         bool boolean_test() const;      ///< \c true, if address is not the zero address
 
index 5dd8691..34749b0 100644 (file)
@@ -30,6 +30,7 @@
 #include <sstream>
 #include "MACAddress.hh"
 #include "../../../Utils/String.hh"
+#include "EUI64.hh"
 
 #include "../../../Utils/auto_unit_test.hh"
 #include <boost/test/test_tools.hpp>
@@ -100,8 +101,9 @@ BOOST_AUTO_UNIT_TEST(macAddress)
     BOOST_CHECK_THROW( MACAddress::from_string("01:02:03:04:05:@6"), AddressSyntaxException );
     BOOST_CHECK_THROW( MACAddress::from_string("01:02:03:04:05:[6"), AddressSyntaxException );
 
-    BOOST_CHECK_EQUAL( mac, MACAddress::from_eui64(0xa1b2c3fffed4e5f6llu) );
-    BOOST_CHECK_THROW( MACAddress::from_eui64(0u), AddressSyntaxException );
+    BOOST_CHECK_EQUAL( mac, MACAddress::from_eui64(senf::EUI64(0xa1b2c3fffed4e5f6llu)) );
+    BOOST_CHECK_THROW( MACAddress::from_eui64(senf::EUI64(0ull)),
+                       AddressSyntaxException );
 
     BOOST_CHECK_EQUAL( MACAddress(0x1a2b3c4d5e6fULL).uint64(), 0x1a2b3c4d5e6fULL);
 }