You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2015/03/07 07:20:31 UTC

[2/4] mesos git commit: Added protocol family support in IP and IPNetwork.

Added protocol family support in IP and IPNetwork.

Review: https://reviews.apache.org/r/31471


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/d514e9fb
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/d514e9fb
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/d514e9fb

Branch: refs/heads/master
Commit: d514e9fb88168ef4adf530596d2516ed3d86ce5f
Parents: 0ae0bbc
Author: Evelina Dumitrescu <ev...@gmail.com>
Authored: Fri Mar 6 15:31:37 2015 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Mar 6 22:03:09 2015 -0800

----------------------------------------------------------------------
 .../3rdparty/stout/include/stout/ip.hpp         | 388 +++++++++++++------
 .../3rdparty/stout/include/stout/net.hpp        |  74 ++--
 .../3rdparty/stout/tests/ip_tests.cpp           | 102 +++--
 3 files changed, 358 insertions(+), 206 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/d514e9fb/3rdparty/libprocess/3rdparty/stout/include/stout/ip.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/ip.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/ip.hpp
index 1ce35cc..6fbbb4d 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/ip.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/ip.hpp
@@ -29,6 +29,8 @@
 #include <net/if_types.h>
 #endif
 
+#include <netinet/in.h>
+
 #include <sys/socket.h>
 #include <sys/types.h>
 
@@ -44,11 +46,12 @@
 #include "stringify.hpp"
 #include "strings.hpp"
 #include "try.hpp"
+#include "unreachable.hpp"
 
 
 namespace net {
 
-// Represents an IP address.
+// Represents an IP.
 class IP
 {
 public:
@@ -57,17 +60,77 @@ public:
   //   10.0.0.1
   //   192.168.1.100
   //   172.158.1.23
-  static Try<IP> parse(const std::string& value);
+  static Try<IP> parse(const std::string& value, int family);
+
+  // Creates an IP from a struct sockaddr_storage.
+  static Try<IP> create(const struct sockaddr_storage& _storage);
+
+  // Creates an IP from a struct sockaddr.
+  static Try<IP> create(const struct sockaddr& _storage);
+
+  // Creates an IP from struct in_addr. Note that by standard, struct
+  // in_addr stores the IP address in network order.
+  explicit IP(const struct in_addr& _storage)
+    : family_(AF_INET)
+  {
+     clear();
+     storage_.in_ = _storage;
+  }
+
+  // Creates an IP from a 32 bit unsigned integer. Note that the
+  // integer stores the IP address in host order.
+  explicit IP(uint32_t _storage)
+    : family_(AF_INET)
+  {
+     clear();
+     storage_.in_.s_addr = htonl(_storage);
+  }
 
-  // Constructs an IP address from an unsigned integer (in host order).
-  explicit IP(uint32_t _address) : address_(_address) {}
+  // Returns the family type.
+  int family() const
+  {
+    return family_;
+  }
 
-  // Returns the IP address (in host order).
-  uint32_t address() const { return address_; }
+  // Returns the struct in_addr storage.
+  Try<struct in_addr> in() const
+  {
+    if (family_ == AF_INET) {
+      return storage_.in_;
+    } else {
+      return Error("Unsupported family type: " + stringify(family_));
+    }
+  }
+
+  // Checks if this IP is for loopback (e.g., INADDR_LOOPBACK).
+  bool isLoopback() const
+  {
+    switch (family_) {
+      case AF_INET:
+        return storage_.in_.s_addr == htonl(INADDR_LOOPBACK);
+      default:
+        UNREACHABLE();
+    }
+  }
+
+  // Checks if this IP is for any incoming address (e.g., INADDR_ANY).
+  bool isAny() const
+  {
+    switch (family_) {
+      case AF_INET:
+        return storage_.in_.s_addr == htonl(INADDR_ANY);
+      default:
+        UNREACHABLE();
+    }
+  }
 
   bool operator == (const IP& that) const
   {
-    return address_ == that.address_;
+    if (family_ != that.family_) {
+      return false;
+    } else {
+      return memcmp(&storage_, &that.storage_, sizeof(storage_)) == 0;
+    }
   }
 
   bool operator != (const IP& that) const
@@ -75,88 +138,167 @@ public:
     return !operator == (that);
   }
 
+  bool operator < (const IP& that) const
+  {
+    if (family_ != that.family_) {
+      return family_ < that.family_;
+    } else {
+      return memcmp(&storage_, &that.storage_, sizeof(storage_)) < 0;
+    }
+  }
+
+  bool operator > (const IP& that) const
+  {
+    if (family_ != that.family_) {
+      return family_ > that.family_;
+    } else {
+      return memcmp(&storage_, &that.storage_, sizeof(storage_)) > 0;
+    }
+  }
+
 private:
-  // IP address (in host order).
-  uint32_t address_;
+  // NOTE: We need to clear the union when creating an IP because the
+  // equality check uses memcmp.
+  void clear()
+  {
+    memset(&storage_, 0, sizeof(storage_));
+  }
+
+  union Storage
+  {
+    struct in_addr in_;
+  };
+
+  int family_;
+  Storage storage_;
 };
 
 
-inline Try<IP> IP::parse(const std::string& value)
+inline Try<IP> IP::parse(const std::string& value, int family)
+{
+  Storage storage;
+  switch (family) {
+    case AF_INET: {
+      if (inet_pton(AF_INET, value.c_str(), &storage.in_) == 0) {
+        return Error("Failed to parse the IP");
+      }
+      return IP(storage.in_);
+    }
+    default: {
+      return Error("Unsupported family type: " + stringify(family));
+    }
+  }
+}
+
+
+inline Try<IP> IP::create(const struct sockaddr_storage& _storage)
 {
-  struct in_addr in;
-  if (inet_aton(value.c_str(), &in) == 0) {
-    return Error("Failed to parse the IP address");
+  switch (_storage.ss_family) {
+    case AF_INET: {
+      struct sockaddr_in addr = *((struct sockaddr_in*) &_storage);
+      return IP(addr.sin_addr);
+    }
+    default: {
+      return Error(
+          "Unsupported family type: " +
+          stringify(_storage.ss_family));
+    }
   }
+}
 
-  return IP(ntohl(in.s_addr));
+
+inline Try<IP> IP::create(const struct sockaddr& _storage)
+{
+  return create(*((struct sockaddr_storage*) &_storage));
 }
 
 
-// Returns the string representation of the given IP address using the
+// Returns the string representation of the given IP using the
 // canonical dot-decimal form. For example: "10.0.0.1".
 inline std::ostream& operator << (std::ostream& stream, const IP& ip)
 {
-  char buffer[INET_ADDRSTRLEN];
-
-  struct in_addr addr;
-  addr.s_addr = htonl(ip.address());
-
-  const char* str = inet_ntop(AF_INET, &addr, buffer, sizeof(buffer));
-  if (str == NULL) {
-    // We do not expect inet_ntop to fail because all parameters
-    // passed in are valid.
-    const char *error_msg = strerror(errno);
-    ABORT("inet_ntop returns error for address " + stringify(ip.address()) +
-          ": " + error_msg);
+  switch (ip.family()) {
+    case AF_INET: {
+      char buffer[INET_ADDRSTRLEN];
+      struct in_addr in = ip.in().get();
+      if (inet_ntop(AF_INET, &in, buffer, sizeof(buffer)) == NULL) {
+        // We do not expect inet_ntop to fail because all parameters
+        // passed in are valid.
+        ABORT("Failed to get human-readable IP for " +
+              stringify(ntohl(in.s_addr)) +
+              ": " + strerror(errno));
+      }
+
+      stream << buffer;
+      return stream;
+    }
+    default: {
+      UNREACHABLE();
+    }
   }
+}
 
-  stream << str;
 
-  return stream;
+inline std::size_t hash_value(const IP& ip)
+{
+  size_t seed = 0;
+
+  switch (ip.family()) {
+     case AF_INET:
+       boost::hash_combine(seed, htonl(ip.in().get().s_addr));
+       return seed;
+     default:
+       UNREACHABLE();
+  }
 }
 
 
-// Represents an IP network composed from the IP address and the netmask
-// which defines the subnet.
+// Represents an IP network. We store the IP address and the IP
+// netmask which defines the subnet.
 class IPNetwork
 {
 public:
-  // Creates an IP network from the given string that has the dot-decimal
-  // format with subnet prefix). For example:
+  // Returns the IPv4 network for loopback (i.e., 127.0.0.1/8).
+  static IPNetwork LOOPBACK_V4();
+
+  // Creates an IP network from the given string that has the
+  // dot-decimal format with subnet prefix).
+  // For example:
   //   10.0.0.1/8
   //   192.168.1.100/24
   //   172.158.1.23
-  static Try<IPNetwork> parse(const std::string& value);
+  static Try<IPNetwork> parse(const std::string& value, int family);
 
-  // Creates an IP network from the given IP address
-  // and the given netmask.
+  // Creates an IP network from the given IP address and netmask.
   // Returns error if the netmask is not valid (e.g., not contiguous).
-  static Try<IPNetwork> fromAddressNetmask(
-      const IP& address,
-      const IP& netmask);
+  static Try<IPNetwork> create(const IP& address, const IP& netmask);
 
-  // Creates an IP network from an IP address and a subnet
-  // prefix (within [0,32]). Returns error if the prefix is not valid.
-  static Try<IPNetwork> fromAddressPrefix(const IP& address, int prefix);
+  // Creates an IP network from an IP address and a subnet prefix.
+  // Returns error if the prefix is not valid.
+  static Try<IPNetwork> create(const IP& address, int prefix);
 
-  // Returns the IP address.
   IP address() const { return address_; }
-
-  // Returns the netmask.
   IP netmask() const { return netmask_; }
 
-  // Returns the prefix of the subnet defined by the netmask.
+  // Returns the prefix of the subnet defined by the IP netmask.
   int prefix() const
   {
-    uint32_t mask = netmask_.address();
+    switch (netmask_.family()) {
+      case AF_INET: {
+        uint32_t mask = ntohl(netmask_.in().get().s_addr);
+        int value = 0;
+
+        while (mask != 0) {
+          value += mask & 1;
+          mask >>= 1;
+        }
 
-    int value = 0;
-    while (mask != 0) {
-      value += mask & 1;
-      mask >>= 1;
+        return value;
+      }
+      default: {
+        UNREACHABLE();
+      }
     }
-
-    return value;
   }
 
   bool operator == (const IPNetwork& that) const
@@ -170,30 +312,28 @@ public:
   }
 
 private:
-  // Constructs an IP with the given IP address and the given netmask.
   IPNetwork(const IP& _address, const IP& _netmask)
     : address_(_address), netmask_(_netmask) {}
 
-  // IP address.
   IP address_;
-
-  // Netmask.
   IP netmask_;
 };
 
 
-inline Try<IPNetwork> IPNetwork::parse(const std::string& value)
+inline Try<IPNetwork> IPNetwork::parse(const std::string& value, int family)
 {
   std::vector<std::string> tokens = strings::split(value, "/");
 
   if (tokens.size() != 2) {
-    return Error("Unexpected number of '/' detected: " + string(tokens.size()));
+    return Error(
+        "Unexpected number of '/' detected: " +
+        stringify(tokens.size()));
   }
 
   // Parse the IP address.
-  Try<IP> ip = IP::parse(tokens[0]);
-  if (ip.isError()) {
-    return Error(ip.error());
+  Try<IP> address = IP::parse(tokens[0], family);
+  if (address.isError()) {
+    return Error("Failed to parse the IP address: " + address.error());
   }
 
   // Parse the subnet prefix.
@@ -202,64 +342,78 @@ inline Try<IPNetwork> IPNetwork::parse(const std::string& value)
     return Error("Subnet prefix is not a number");
   }
 
-  return fromAddressPrefix(ip.get(), prefix.get());
+  return create(address.get(), prefix.get());
 }
 
 
-inline Try<IPNetwork> IPNetwork::fromAddressNetmask(
-    const IP& address,
-    const IP& netmask)
+inline IPNetwork IPNetwork::LOOPBACK_V4()
 {
-  uint32_t mask = netmask.address();
-  if (((~mask + 1) & (~mask)) != 0) {
-    return Error("Netmask is not valid");
-  }
-
-  return IPNetwork(address, netmask);
+  return parse("127.0.0.1/8", AF_INET).get();
 }
 
 
-inline Try<IPNetwork> IPNetwork::fromAddressPrefix(
-    const IP& address,
-    int prefix)
+inline Try<IPNetwork> IPNetwork::create(const IP& address, const IP& netmask)
 {
-  if (prefix > 32) {
-    return Error("Subnet prefix is larger than 32");
+  if (address.family() != netmask.family()) {
+    return Error(
+        "The network families of the IP address '" +
+        stringify(address.family()) + "' and the IP netmask '" +
+        stringify(netmask.family()) + "' do not match");
   }
 
-  if (prefix < 0) {
-    return Error("Subnet prefix is negative");
-  }
+  switch (address.family()) {
+    case AF_INET: {
+      uint32_t mask = ntohl(netmask.in().get().s_addr);
+      if (((~mask + 1) & (~mask)) != 0) {
+        return Error("Netmask is not valid");
+      }
 
-  return IPNetwork(address, IP(0xffffffff << (32 - prefix)));
+      return IPNetwork(address, netmask);
+    }
+    default: {
+      UNREACHABLE();
+    }
+  }
 }
 
 
-// Returns the string representation of the given IP network using the
-// canonical dot-decimal form with prefix. For example: "10.0.0.1/8".
-inline std::ostream& operator << (
-    std::ostream& stream,
-    const IPNetwork& network)
+inline Try<IPNetwork> IPNetwork::create(const IP& address, int prefix)
 {
-  stream << network.address() << "/" << network.prefix();
+  if (prefix < 0) {
+    return Error("Subnet prefix is negative");
+  }
 
-  return stream;
+  switch (address.family()) {
+    case AF_INET: {
+      if (prefix > 32) {
+        return Error("Subnet prefix is larger than 32");
+      }
+
+      return IPNetwork(address, IP(0xffffffff << (32 - prefix)));
+    }
+    default: {
+      UNREACHABLE();
+    }
+  }
 }
 
 
-// Returns the first available IP network of a given link device.
-// The link device is specified using its name (e.g., eth0).
-// Returns error if the link device is not found.
-// Returns none if the link device is found,
-// but does not have an IP network.
+// Returns the first available IP network of a given link device. The
+// link device is specified using its name (e.g., eth0). Returns error
+// if the link device is not found. Returns none if the link device is
+// found, but does not have an IP network.
 // TODO(jieyu): It is uncommon, but likely that a link device has
-// multiple IP networks. In that case, consider returning
-// the primary IP network instead of the first one.
-inline Result<IPNetwork> fromLinkDevice(const std::string& name)
+// multiple IP networks. In that case, consider returning the primary
+// IP network instead of the first one.
+inline Result<IPNetwork> fromLinkDevice(const std::string& name, int family)
 {
 #if !defined(__linux__) && !defined(__APPLE__)
   return Error("Not implemented");
 #else
+  if (family != AF_INET) {
+    return Error("Unsupported family type: " + stringify(family));
+  }
+
   struct ifaddrs* ifaddr = NULL;
   if (getifaddrs(&ifaddr) == -1) {
     return ErrnoError();
@@ -272,19 +426,16 @@ inline Result<IPNetwork> fromLinkDevice(const std::string& name)
     if (ifa->ifa_name != NULL && !strcmp(ifa->ifa_name, name.c_str())) {
       found = true;
 
-      if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_INET) {
-        struct sockaddr_in* addr = (struct sockaddr_in*) ifa->ifa_addr;
+      if (ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == family) {
+        IP address = IP::create(*ifa->ifa_addr).get();
 
         if (ifa->ifa_netmask != NULL &&
-            ifa->ifa_netmask->sa_family == AF_INET) {
-          struct sockaddr_in* netmask = (struct sockaddr_in*) ifa->ifa_netmask;
-
-          Try<IPNetwork> network = IPNetwork::fromAddressNetmask(
-              IP(ntohl(addr->sin_addr.s_addr)),
-              IP(ntohl(netmask->sin_addr.s_addr)));
+            ifa->ifa_netmask->sa_family == family) {
+          IP netmask = IP::create(*ifa->ifa_netmask).get();
 
           freeifaddrs(ifaddr);
 
+          Try<IPNetwork> network = IPNetwork::create(address, netmask);
           if (network.isError()) {
             return Error(network.error());
           }
@@ -292,19 +443,17 @@ inline Result<IPNetwork> fromLinkDevice(const std::string& name)
           return network.get();
         }
 
-        // Note that this is the case where netmask is not specified.
-        // A default /32 value is used.
-        // We've seen such cases when VPN is used.
-        Try<IPNetwork> ip = IPNetwork::fromAddressPrefix(
-            IP(ntohl(addr->sin_addr.s_addr)),
-            32);
-
         freeifaddrs(ifaddr);
-        if (ip.isError()) {
-          return Error(ip.error());
+
+        // Note that this is the case where netmask is not specified.
+        // We've seen such cases when VPN is used. In that case, a
+        // default /32 prefix is used.
+        Try<IPNetwork> network = IPNetwork::create(address, 32);
+        if (network.isError()) {
+          return Error(network.error());
         }
 
-        return ip.get();
+        return network.get();
       }
     }
   }
@@ -320,6 +469,17 @@ inline Result<IPNetwork> fromLinkDevice(const std::string& name)
 }
 
 
+// Returns the string representation of the given IP network using the
+// canonical dot-decimal form with prefix. For example: "10.0.0.1/8".
+inline std::ostream& operator << (
+    std::ostream& stream,
+    const IPNetwork& network)
+{
+  stream << network.address() << "/" << network.prefix();
+
+  return stream;
+}
+
 } // namespace net {
 
 #endif // __STOUT_IP_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/d514e9fb/3rdparty/libprocess/3rdparty/stout/include/stout/net.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/net.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/net.hpp
index 9635bbc..3622165 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/net.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/net.hpp
@@ -14,9 +14,6 @@
 #ifndef __STOUT_NET_HPP__
 #define __STOUT_NET_HPP__
 
-#if defined(__linux__) || defined(__APPLE__)
-#include <ifaddrs.h>
-#endif
 #include <netdb.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -24,13 +21,6 @@
 
 #include <arpa/inet.h>
 
-#ifdef __linux__
-#include <linux/if.h>
-#include <linux/if_packet.h>
-#endif
-
-#include <net/ethernet.h>
-
 #ifdef __APPLE__
 #include <net/if.h>
 #include <net/if_dl.h>
@@ -38,8 +28,6 @@
 #endif
 
 #include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/types.h>
 
 #include <curl/curl.h>
 
@@ -47,14 +35,11 @@
 #include <set>
 #include <string>
 
-#include "abort.hpp"
 #include "error.hpp"
-#include "none.hpp"
+#include "ip.hpp"
 #include "option.hpp"
 #include "os.hpp"
-#include "result.hpp"
 #include "stringify.hpp"
-#include "strings.hpp"
 #include "try.hpp"
 
 
@@ -73,16 +58,29 @@ inline struct addrinfo createAddrInfo(int socktype, int family, int flags)
 }
 
 
-// TODO(evelinad): Add createSockaddrIn6 when will support IPv6
-inline struct sockaddr_in createSockaddrIn(uint32_t ip, int port)
+// TODO(evelinad): Move this to Address.
+inline struct sockaddr_storage createSockaddrStorage(const IP& ip, int port)
 {
-  struct sockaddr_in addr;
-  memset(&addr, 0, sizeof(addr));
-  addr.sin_family = AF_INET;
-  addr.sin_addr.s_addr = ip;
-  addr.sin_port = htons(port);
+  struct sockaddr_storage storage;
+  memset(&storage, 0, sizeof(storage));
+
+  switch (ip.family()) {
+    case AF_INET: {
+      struct sockaddr_in addr;
+      memset(&addr, 0, sizeof(addr));
+      addr.sin_family = AF_INET;
+      addr.sin_addr = ip.in().get();
+      addr.sin_port = htons(port);
+
+      memcpy(&storage, &addr, sizeof(addr));
+      break;
+    }
+    default: {
+      ABORT("Unsupported family type: " + stringify(ip.family()));
+    }
+  }
 
-  return addr;
+  return storage;
 }
 
 
@@ -169,19 +167,20 @@ inline Try<std::string> hostname()
 // Returns a Try of the hostname for the provided IP. If the hostname
 // cannot be resolved, then a string version of the IP address is
 // returned.
-inline Try<std::string> getHostname(uint32_t ip)
+inline Try<std::string> getHostname(const IP& ip)
 {
-  sockaddr_in addr = createSockaddrIn(ip, 0);
-
+  struct sockaddr_storage storage = createSockaddrStorage(ip, 0);
   char hostname[MAXHOSTNAMELEN];
+
   int error = getnameinfo(
-      (sockaddr*)&addr,
-      sizeof(addr),
+      (struct sockaddr*) &storage,
+      sizeof(storage),
       hostname,
       MAXHOSTNAMELEN,
       NULL,
       0,
       0);
+
   if (error != 0) {
     return Error(std::string(gai_strerror(error)));
   }
@@ -190,13 +189,12 @@ inline Try<std::string> getHostname(uint32_t ip)
 }
 
 
-// Returns a Try of the IP for the provided hostname or an error if no
-// IP is obtained.
-inline Try<uint32_t> getIP(const std::string& hostname, sa_family_t family)
+// Returns a Try of the IP for the provided hostname or an error if no IP is
+// obtained.
+inline Try<IP> getIP(const std::string& hostname, int family)
 {
   struct addrinfo hints, *result;
   hints = createAddrInfo(SOCK_STREAM, family, 0);
-
   int error = getaddrinfo(hostname.c_str(), NULL, &hints, &result);
   if (error != 0 || result == NULL) {
     if (result != NULL ) {
@@ -209,10 +207,14 @@ inline Try<uint32_t> getIP(const std::string& hostname, sa_family_t family)
     return Error("Got no addresses for '" + hostname + "'");
   }
 
-  uint32_t ip = ((struct sockaddr_in*)(result->ai_addr))->sin_addr.s_addr;
-  freeaddrinfo(result);
+  Try<IP> ip = IP::create(*result->ai_addr);
+  if (ip.isError()) {
+    freeaddrinfo(result);
+    return Error("Unsupported family type: " + stringify(family));
+  }
 
-  return ip;
+  freeaddrinfo(result);
+  return ip.get();
 }
 
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/d514e9fb/3rdparty/libprocess/3rdparty/stout/tests/ip_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/tests/ip_tests.cpp b/3rdparty/libprocess/3rdparty/stout/tests/ip_tests.cpp
index 7eb85b7..165e29d 100644
--- a/3rdparty/libprocess/3rdparty/stout/tests/ip_tests.cpp
+++ b/3rdparty/libprocess/3rdparty/stout/tests/ip_tests.cpp
@@ -25,14 +25,14 @@ TEST(NetTest, LinkDevice)
   ASSERT_SOME(links);
 
   foreach(const string& link, links.get()) {
-    Result<net::IPNetwork> network = net::fromLinkDevice(link);
+    Result<net::IPNetwork> network = net::fromLinkDevice(link, AF_INET);
     EXPECT_FALSE(network.isError());
 
     if (network.isSome()) {
       string addr = stringify(network.get());
       string prefix = addr.substr(addr.find("/") + 1);
       ASSERT_SOME(numify<size_t>(prefix));
-      EXPECT_EQ(network.get().prefix().get(), numify<size_t>(prefix).get());
+      EXPECT_EQ(network.get().prefix(), numify<size_t>(prefix).get());
 
       vector<string> tokens =
         strings::split(addr.substr(0, addr.find("/")), ".");
@@ -47,71 +47,61 @@ TEST(NetTest, LinkDevice)
     }
   }
 
-  EXPECT_ERROR(net::fromLinkDevice("non-exist"));
+  EXPECT_ERROR(net::fromLinkDevice("non-exist", AF_INET));
 }
 
 
-TEST(NetTest, ConstructIP)
+TEST(NetTest, ConstructIPv4)
 {
-  EXPECT_SOME(net::IP::parse("127.0.0.1"));
-  EXPECT_SOME(net::IP::parse("01.02.03.04"));
+  EXPECT_SOME(net::IP::parse("127.0.0.1", AF_INET));
+  EXPECT_SOME(net::IP::parse("1.2.3.4", AF_INET));
 
-  EXPECT_ERROR(net::IP::parse("123.1.1..2"));
-  EXPECT_ERROR(net::IP::parse("121.2.3.5."));
-  EXPECT_ERROR(net::IP::parse("12.32.3.a"));
-  EXPECT_ERROR(net::IP::parse("hello world"));
+  EXPECT_ERROR(net::IP::parse("123.1.1..2", AF_INET));
+  EXPECT_ERROR(net::IP::parse("121.2.3.5.", AF_INET));
+  EXPECT_ERROR(net::IP::parse("12.32.3.a", AF_INET));
+  EXPECT_ERROR(net::IP::parse("hello world", AF_INET));
 }
 
 
-TEST(NetTest, ConstructIPNetwork)
+TEST(NetTest, ConstructIPv4Network)
 {
-  EXPECT_SOME(net::IPNetwork::parse("10.135.0.1/8"));
-  EXPECT_SOME(net::IPNetwork::parse("192.168.1.1/16"));
-  EXPECT_SOME(net::IPNetwork::parse("172.39.13.123/31"));
-
-  EXPECT_ERROR(net::IPNetwork::parse("123.1.1.2//23"));
-  EXPECT_ERROR(net::IPNetwork::parse("121.2.3.5/23/"));
-  EXPECT_ERROR(net::IPNetwork::parse("12.32.3.a/16"));
-  EXPECT_ERROR(net::IPNetwork::parse("hello moto/8"));
-
-  EXPECT_SOME(net::IPNetwork::fromAddressNetmask(
-      net::IP(0x12345678),
-      net::IP(0xffff0000)));
-  EXPECT_SOME(net::IPNetwork::fromAddressNetmask(
-      net::IP(0x12345678),
-      net::IP(0xf0000000)));
-  EXPECT_SOME(net::IPNetwork::fromAddressNetmask(
-      net::IP(0x12345678),
-      net::IP(0xffffffff)));
-  EXPECT_SOME(net::IPNetwork::fromAddressNetmask(
-      net::IP(0x12345678),
-      net::IP(0)));
-
-  EXPECT_ERROR(net::IPNetwork::fromAddressNetmask(
-      net::IP(0x087654321),
-      net::IP(0xff)));
-  EXPECT_ERROR(net::IPNetwork::fromAddressNetmask(
-      net::IP(0x087654321),
-      net::IP(0xff00ff00)));
-
-  EXPECT_SOME(net::IPNetwork::fromAddressPrefix(net::IP(0x12345678), 16));
-  EXPECT_SOME(net::IPNetwork::fromAddressPrefix(net::IP(0x12345678), 32));
-  EXPECT_SOME(net::IPNetwork::fromAddressPrefix(net::IP(0x12345678), 0));
-
-  EXPECT_ERROR(net::IPNetwork::fromAddressPrefix(net::IP(0x12345678), 123));
+  EXPECT_SOME(net::IPNetwork::parse("10.135.0.1/8", AF_INET));
+  EXPECT_SOME(net::IPNetwork::parse("192.168.1.1/16", AF_INET));
+  EXPECT_SOME(net::IPNetwork::parse("172.39.13.123/31", AF_INET));
+
+  EXPECT_ERROR(net::IPNetwork::parse("123.1.1.2//23", AF_INET));
+  EXPECT_ERROR(net::IPNetwork::parse("121.2.3.5/23/", AF_INET));
+  EXPECT_ERROR(net::IPNetwork::parse("12.32.3.a/16", AF_INET));
+  EXPECT_ERROR(net::IPNetwork::parse("hello moto/8", AF_INET));
+
+  EXPECT_SOME(net::IPNetwork::create(net::IP(0x12345678), net::IP(0xffff0000)));
+  EXPECT_SOME(net::IPNetwork::create(net::IP(0x12345678), net::IP(0xf0000000)));
+  EXPECT_SOME(net::IPNetwork::create(net::IP(0x12345678), net::IP(0xffffffff)));
+  EXPECT_SOME(net::IPNetwork::create(net::IP(0x12345678), net::IP(0)));
+
+  EXPECT_ERROR(net::IPNetwork::create(net::IP(0x87654321), net::IP(0xff)));
+  EXPECT_ERROR(net::IPNetwork::create(net::IP(0x87654321), net::IP(0xff00ff)));
+
+  EXPECT_SOME(net::IPNetwork::create(net::IP(0x12345678), 16));
+  EXPECT_SOME(net::IPNetwork::create(net::IP(0x12345678), 32));
+  EXPECT_SOME(net::IPNetwork::create(net::IP(0x12345678), 0));
+
+  EXPECT_ERROR(net::IPNetwork::create(net::IP(0x12345678), 123));
 
   uint32_t address = 0x01020304;
   uint32_t netmask = 0xff000000;
 
-  Try<net::IPNetwork> ip1 = net::IPNetwork::fromAddressNetmask(
-      net::IP(address),
-      net::IP(netmask));
-  ASSERT_SOME(ip1);
-  EXPECT_EQ(net::IP(address), ip1.get().address());
-  EXPECT_EQ(net::IP(netmask), ip1.get().netmask());
-  EXPECT_EQ("1.2.3.4/8", stringify(ip1.get()));
-
-  Try<net::IPNetwork> ip2 = net::IPNetwork::parse(stringify(ip1.get()));
-  ASSERT_SOME(ip2);
-  EXPECT_EQ(ip1.get(), ip2.get());
+  Try<net::IPNetwork> network1 =
+    net::IPNetwork::create(net::IP(address), net::IP(netmask));
+
+  ASSERT_SOME(network1);
+  EXPECT_EQ(net::IP(address), network1.get().address());
+  EXPECT_EQ(net::IP(netmask), network1.get().netmask());
+  EXPECT_EQ("1.2.3.4/8", stringify(network1.get()));
+
+  Try<net::IPNetwork> network2 =
+      net::IPNetwork::parse(stringify(network1.get()), AF_INET);
+
+  ASSERT_SOME(network2);
+  EXPECT_EQ(network1.get(), network2.get());
 }