[ovs-dev] [PATCH 1/3] lib: Add ipv6 support for active and passive socket connections

Arun Sharma arun.sharma at calsoftinc.com
Mon Dec 9 12:21:21 UTC 2013


Allows all socket operations to use ipv6 network addresses,
except in-band control which  is not supported for ipv6

Signed-off-by: Nandan Nivgune <nandan.nivgune at calsoftinc.com>
Signed-off-by: Abhijit Bhopatkar <abhijit.bhopatkar at calsoftinc.com>
Signed-off-by: Arun Sharma <arun.sharma at calsoftinc.com>
---
 lib/packets.h                |   12 +++
 lib/rconn.c                  |   39 ++++++-
 lib/rconn.h                  |    3 +
 lib/socket-util.c            |  235 ++++++++++++++++++++++++++++--------------
 lib/socket-util.h            |    9 +-
 lib/stream-provider.h        |    4 +
 lib/stream-ssl.c             |   85 +++++++++++----
 lib/stream-tcp.c             |   66 +++++++++---
 lib/stream.c                 |   20 +++-
 lib/stream.h                 |    2 +-
 lib/vconn-provider.h         |    6 +-
 lib/vconn.c                  |   26 +++++
 lib/vconn.h                  |    3 +
 ofproto/connmgr.c            |    9 +-
 ofproto/ofproto-dpif-sflow.c |   26 +++--
 python/ovs/socket_util.py    |   36 +++++--
 tests/test-sflow.c           |    8 +-
 vswitchd/bridge.c            |    8 +-
 18 files changed, 449 insertions(+), 148 deletions(-)

diff --git a/lib/packets.h b/lib/packets.h
index d291c14..4823806 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -367,6 +367,18 @@ mpls_lse_to_bos(ovs_be32 mpls_lse)
     return (mpls_lse & htonl(MPLS_BOS_MASK)) != 0;
 }
 
+#define IP6_FMT "%"PRIx16":%"PRIx16":%"PRIx16":%"PRIx16":%"PRIx16   \
+    ":%"PRIx16":%"PRIx16":%"PRIx16
+#define IP6_ARGS(ip6)                                  \
+    ntohs(ip6[0]),                                     \
+    ntohs(ip6[1]),                                     \
+    ntohs(ip6[2]),                                     \
+    ntohs(ip6[3]),                                     \
+    ntohs(ip6[4]),                                     \
+    ntohs(ip6[5]),                                     \
+    ntohs(ip6[6]),                                     \
+    ntohs(ip6[7])
+
 #define IP_FMT "%"PRIu32".%"PRIu32".%"PRIu32".%"PRIu32
 #define IP_ARGS(ip)                             \
     ntohl(ip) >> 24,                            \
diff --git a/lib/rconn.c b/lib/rconn.c
index f7f90f7..65a8d66 100644
--- a/lib/rconn.c
+++ b/lib/rconn.c
@@ -21,12 +21,14 @@
 #include <stdlib.h>
 #include <string.h>
 #include "coverage.h"
+#include "jsonrpc.h"
 #include "ofp-msgs.h"
 #include "ofp-util.h"
 #include "ofpbuf.h"
 #include "openflow/openflow.h"
 #include "poll-loop.h"
 #include "sat-math.h"
+#include "socket-util.h"
 #include "timeval.h"
 #include "util.h"
 #include "vconn.h"
@@ -125,6 +127,7 @@ struct rconn {
      * We don't cache the local port, because that changes from one connection
      * attempt to the next. */
     ovs_be32 local_ip, remote_ip;
+    struct in6_addr local_ip6, remote_ip6;
     ovs_be16 remote_port;
     uint8_t dscp;
 
@@ -448,22 +451,40 @@ reconnect(struct rconn *rc)
     OVS_REQUIRES(rc->mutex)
 {
     int retval;
+    struct sockaddr_storage ss;
 
     if (rconn_logging_connection_attempts__(rc)) {
         VLOG_INFO("%s: connecting...", rc->name);
     }
     rc->n_attempted_connections++;
+    if (!strncmp(rc->target, "tcp:", 4) || (!strncmp(rc->target, "ssl:", 4))) {
+        if (!inet_parse_active(rc->target + 4, OVSDB_PORT, &ss)) {
+            VLOG_WARN("%s:failed to get address family", rc->name);
+            retval = -1;
+            goto exit;
+         }
+    }
+
     retval = vconn_open(rc->target, rc->allowed_versions, rc->dscp,
                         &rc->vconn);
     if (!retval) {
-        rc->remote_ip = vconn_get_remote_ip(rc->vconn);
-        rc->local_ip = vconn_get_local_ip(rc->vconn);
+        if (ss.ss_family == AF_INET) {
+            rc->remote_ip = vconn_get_remote_ip(rc->vconn);
+            rc->local_ip = vconn_get_local_ip(rc->vconn);
+        } else {
+            vconn_get_remote_ip6(rc->vconn, &rc->remote_ip6);
+            vconn_get_local_ip6(rc->vconn, &rc->local_ip6);
+        }
         rc->remote_port = vconn_get_remote_port(rc->vconn);
         rc->backoff_deadline = time_now() + rc->backoff;
         state_transition(rc, S_CONNECTING);
     } else {
         VLOG_WARN("%s: connection failed (%s)",
                   rc->name, ovs_strerror(retval));
+    }
+
+exit:
+    if (retval) {
         rc->backoff_deadline = TIME_MAX; /* Prevent resetting backoff. */
         disconnect(rc, retval);
     }
@@ -958,6 +979,20 @@ rconn_get_version__(const struct rconn *rconn)
     return rconn->vconn ? vconn_get_version(rconn->vconn) : -1;
 }
 
+/* Copies the IP address used to connect to the peer into 'ip'. */
+void
+rconn_get_remote_ip6(struct rconn *rconn, struct in6_addr *ip)
+{
+    memcpy(ip, &rconn->remote_ip6, sizeof rconn->remote_ip6);
+}
+
+/* Copies the IP address used to connect to the peer into 'ip'. */
+void
+rconn_get_local_ip6(struct rconn *rconn, struct in6_addr *ip)
+{
+    memcpy(ip, &rconn->local_ip6, sizeof rconn->local_ip6);
+}
+
 /* Returns the OpenFlow version negotiated with the peer, or -1 if there is
  * currently no connection or if version negotiation is not yet complete. */
 int
diff --git a/lib/rconn.h b/lib/rconn.h
index 408cec9..5e64c14 100644
--- a/lib/rconn.h
+++ b/lib/rconn.h
@@ -17,6 +17,7 @@
 #ifndef RCONN_H
 #define RCONN_H 1
 
+#include <netinet/in.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <time.h>
@@ -87,6 +88,8 @@ ovs_be32 rconn_get_remote_ip(const struct rconn *);
 ovs_be16 rconn_get_remote_port(const struct rconn *);
 ovs_be32 rconn_get_local_ip(const struct rconn *);
 ovs_be16 rconn_get_local_port(const struct rconn *);
+void rconn_get_remote_ip6(struct rconn *, struct in6_addr *remote_ip);
+void rconn_get_local_ip6(struct rconn *, struct in6_addr *local_ip);
 int rconn_get_version(const struct rconn *);
 
 const char *rconn_get_state(const struct rconn *);
diff --git a/lib/socket-util.c b/lib/socket-util.c
index bb48ade..1d8a8e3 100644
--- a/lib/socket-util.c
+++ b/lib/socket-util.c
@@ -67,6 +67,11 @@ VLOG_DEFINE_THIS_MODULE(socket_util);
 static int getsockopt_int(int fd, int level, int option, const char *optname,
                           int *valuep);
 
+static int do_getaddrinfo(const char *host, const char *port,
+                          struct sockaddr_storage *ssp);
+
+static void parse_active(char *target, const char **host, const char **port);
+
 /* Sets 'fd' to non-blocking mode.  Returns 0 if successful, otherwise a
  * positive errno value. */
 int
@@ -616,38 +621,34 @@ guess_netmask(ovs_be32 ip_)
  * <host> is required.  If 'default_port' is nonzero then <port> is optional
  * and defaults to 'default_port'.
  *
- * On success, returns true and stores the parsed remote address into '*sinp'.
- * On failure, logs an error, stores zeros into '*sinp', and returns false. */
+ * On success, returns true and stores the parsed remote address into '*ssp'.
+ * On failure, logs an error, stores zeros into '*ssp', and returns false. */
 bool
 inet_parse_active(const char *target_, uint16_t default_port,
-                  struct sockaddr_in *sinp)
+                  struct sockaddr_storage *ssp)
 {
     char *target = xstrdup(target_);
-    char *save_ptr = NULL;
+    char *save_ptr = target;
     const char *host_name;
     const char *port_string;
+    char default_port_str[6] = {'\0'};
     bool ok = false;
 
-    /* Defaults. */
-    sinp->sin_family = AF_INET;
-    sinp->sin_port = htons(default_port);
-
-    /* Tokenize. */
-    host_name = strtok_r(target, ":", &save_ptr);
-    port_string = strtok_r(NULL, ":", &save_ptr);
+    /* Parse IP address and port. */
+    parse_active(target, &host_name, &port_string);
     if (!host_name) {
-        VLOG_ERR("%s: bad peer name format", target_);
-        goto exit;
+         VLOG_ERR("%s: bad peer name format", target_);
+         goto exit;
     }
-
-    /* Look up IP, port. */
-    if (lookup_ip(host_name, &sinp->sin_addr)) {
-        goto exit;
+    if (port_string == NULL) {
+        if (!default_port) {
+            VLOG_ERR("%s: port number must be specified", target_);
+            goto exit;
+        }
+        sprintf(default_port_str, "%d", default_port);
+        port_string = default_port_str;
     }
-    if (port_string && atoi(port_string)) {
-        sinp->sin_port = htons(atoi(port_string));
-    } else if (!default_port) {
-        VLOG_ERR("%s: port number must be specified", target_);
+    if (do_getaddrinfo(host_name, port_string, ssp) == -1) {
         goto exit;
     }
 
@@ -655,16 +656,16 @@ inet_parse_active(const char *target_, uint16_t default_port,
 
 exit:
     if (!ok) {
-        memset(sinp, 0, sizeof *sinp);
+        memset(ssp, 0, sizeof *ssp);
     }
-    free(target);
+    free(save_ptr);
     return ok;
 }
 
-/* Opens a non-blocking IPv4 socket of the specified 'style' and connects to
- * 'target', which should be a string in the format "<host>[:<port>]".  <host>
- * is required.  If 'default_port' is nonzero then <port> is optional and
- * defaults to 'default_port'.
+/* Opens a non-blocking IPv4 or Ipv6 socket of the specified 'style' and
+ * connects to * 'target', which should be a string in the format
+ * "<host>[:<port>]".  <host> is required.  If 'default_port' is nonzero then
+ * <port> is optional and defaults to 'default_port'.
  *
  * 'style' should be SOCK_STREAM (for TCP) or SOCK_DGRAM (for UDP).
  *
@@ -673,28 +674,29 @@ exit:
  * into '*fdp'.  On failure, returns a positive errno value other than EAGAIN
  * and stores -1 into '*fdp'.
  *
- * If 'sinp' is non-null, then on success the target address is stored into
- * '*sinp'.
+ * If 'ssp' is non-null, then on success the target address is stored into
+ * '*ssp'.
  *
  * 'dscp' becomes the DSCP bits in the IP headers for the new connection.  It
  * should be in the range [0, 63] and will automatically be shifted to the
  * appropriately place in the IP tos field. */
 int
 inet_open_active(int style, const char *target, uint16_t default_port,
-                 struct sockaddr_in *sinp, int *fdp, uint8_t dscp)
+                 struct sockaddr_storage *ssp, int *fdp, uint8_t dscp)
 {
-    struct sockaddr_in sin;
+    struct sockaddr_storage sstorage;
     int fd = -1;
     int error;
+    socklen_t addrlen;
 
     /* Parse. */
-    if (!inet_parse_active(target, default_port, &sin)) {
+    if (!inet_parse_active(target, default_port, &sstorage)) {
         error = EAFNOSUPPORT;
         goto exit;
     }
 
     /* Create non-blocking socket. */
-    fd = socket(AF_INET, style, 0);
+    fd = socket(sstorage.ss_family, style, 0);
     if (fd < 0) {
         VLOG_ERR("%s: socket: %s", target, ovs_strerror(errno));
         error = errno;
@@ -714,16 +716,24 @@ inet_open_active(int style, const char *target, uint16_t default_port,
         goto exit;
     }
 
+    if (sstorage.ss_family == AF_INET) {
+        addrlen = sizeof (struct sockaddr_in);
+    } else {
+        addrlen = sizeof (struct sockaddr_in6);
+    }
+
     /* Connect. */
-    error = connect(fd, (struct sockaddr *) &sin, sizeof sin) == 0 ? 0 : errno;
+    error = connect(fd, (struct sockaddr *) &sstorage, addrlen) == 0
+                    ? 0
+                    : errno;
     if (error == EINPROGRESS) {
         error = EAGAIN;
     }
 
 exit:
     if (!error || error == EAGAIN) {
-        if (sinp) {
-            *sinp = sin;
+        if (ssp) {
+            *ssp = sstorage;
         }
     } else if (fd >= 0) {
         close(fd);
@@ -743,37 +753,33 @@ exit:
  *
  *      - If <ip> is omitted then the IP address is wildcarded.
  *
- * If successful, stores the address into '*sinp' and returns true; otherwise
- * zeros '*sinp' and returns false. */
+ * If successful, stores the address into '*ssp' and returns true; otherwise
+ * zeros '*ssp' and returns false. */
 bool
 inet_parse_passive(const char *target_, int default_port,
-                   struct sockaddr_in *sinp)
+                   struct sockaddr_storage *ssp)
 {
     char *target = xstrdup(target_);
     char *string_ptr = target;
     const char *host_name;
     const char *port_string;
+    char default_port_str[8] = {'\0'};
     bool ok = false;
-    int port;
 
-    /* Address defaults. */
-    memset(sinp, 0, sizeof *sinp);
-    sinp->sin_family = AF_INET;
-    sinp->sin_addr.s_addr = htonl(INADDR_ANY);
-    sinp->sin_port = htons(default_port);
+    memset(ssp, 0, sizeof *ssp);
 
-    /* Parse optional port number. */
     port_string = strsep(&string_ptr, ":");
-    if (port_string && str_to_int(port_string, 10, &port)) {
-        sinp->sin_port = htons(port);
-    } else if (default_port < 0) {
-        VLOG_ERR("%s: port number must be specified", target_);
-        goto exit;
+    host_name = string_ptr;
+    if (port_string == NULL) {
+        if (default_port == -1) {
+            VLOG_ERR("%s: port number must be specified", target_);
+            goto exit;
+        }
+        sprintf(default_port_str, "%d", default_port);
+        port_string = default_port_str;
     }
 
-    /* Parse optional bind IP. */
-    host_name = strsep(&string_ptr, ":");
-    if (host_name && host_name[0] && lookup_ip(host_name, &sinp->sin_addr)) {
+    if (do_getaddrinfo(host_name, port_string, ssp) == -1) {
         goto exit;
     }
 
@@ -781,14 +787,14 @@ inet_parse_passive(const char *target_, int default_port,
 
 exit:
     if (!ok) {
-        memset(sinp, 0, sizeof *sinp);
+        memset(ssp, 0, sizeof *ssp);
     }
     free(target);
     return ok;
 }
 
 
-/* Opens a non-blocking IPv4 socket of the specified 'style', binds to
+/* Opens a non-blocking IPv4 or IPv6 socket of the specified 'style', binds to
  * 'target', and listens for incoming connections.  Parses 'target' in the same
  * way was inet_parse_passive().
  *
@@ -799,27 +805,31 @@ exit:
  * On success, returns a non-negative file descriptor.  On failure, returns a
  * negative errno value.
  *
- * If 'sinp' is non-null, then on success the bound address is stored into
- * '*sinp'.
+ * If 'ssp' is non-null, then on success the bound address is stored into
+ * '*ssp'.
  *
  * 'dscp' becomes the DSCP bits in the IP headers for the new connection.  It
  * should be in the range [0, 63] and will automatically be shifted to the
  * appropriately place in the IP tos field. */
 int
 inet_open_passive(int style, const char *target, int default_port,
-                  struct sockaddr_in *sinp, uint8_t dscp)
+                  struct sockaddr_storage *ssp, uint8_t dscp)
 {
     bool kernel_chooses_port;
-    struct sockaddr_in sin;
+    struct sockaddr_storage ss;
+    struct sockaddr_in *sin_p;
+    struct sockaddr_in6 *sin6_p;
+    in_port_t port;
     int fd = 0, error;
     unsigned int yes = 1;
+    socklen_t addrlen;
 
-    if (!inet_parse_passive(target, default_port, &sin)) {
+    if (!inet_parse_passive(target, default_port, &ss)) {
         return -EAFNOSUPPORT;
     }
 
     /* Create non-blocking socket, set SO_REUSEADDR. */
-    fd = socket(AF_INET, style, 0);
+    fd = socket(ss.ss_family, style, 0);
     if (fd < 0) {
         error = errno;
         VLOG_ERR("%s: socket: %s", target, ovs_strerror(error));
@@ -837,8 +847,19 @@ inet_open_passive(int style, const char *target, int default_port,
         goto error;
     }
 
+    if (ss.ss_family == AF_INET) {
+        sin_p = (struct sockaddr_in *) &ss;
+        addrlen = sizeof (struct sockaddr_in);
+        port = sin_p->sin_port;
+    } else {
+        sin6_p = (struct sockaddr_in6 *) &ss;
+        addrlen = sizeof (struct sockaddr_in6);
+        port = sin6_p->sin6_port;
+    }
+
+    kernel_chooses_port = port == htons(0);
     /* Bind. */
-    if (bind(fd, (struct sockaddr *) &sin, sizeof sin) < 0) {
+    if (bind(fd, (struct sockaddr *) &ss, addrlen) < 0) {
         error = errno;
         VLOG_ERR("%s: bind: %s", target, ovs_strerror(error));
         goto error;
@@ -860,25 +881,20 @@ inet_open_passive(int style, const char *target, int default_port,
         goto error;
     }
 
-    kernel_chooses_port = sin.sin_port == htons(0);
-    if (sinp || kernel_chooses_port) {
-        socklen_t sin_len = sizeof sin;
-        if (getsockname(fd, (struct sockaddr *) &sin, &sin_len) < 0) {
+    if (ssp || kernel_chooses_port) {
+        socklen_t sin_len = addrlen;
+        if (getsockname(fd, (struct sockaddr *) &ss, &sin_len) < 0) {
             error = errno;
             VLOG_ERR("%s: getsockname: %s", target, ovs_strerror(error));
             goto error;
         }
-        if (sin.sin_family != AF_INET || sin_len != sizeof sin) {
-            error = EAFNOSUPPORT;
-            VLOG_ERR("%s: getsockname: invalid socket name", target);
-            goto error;
-        }
-        if (sinp) {
-            *sinp = sin;
+        if (ssp) {
+            *ssp = ss;
         }
+        sin_p = (struct sockaddr_in *) &ss;
         if (kernel_chooses_port) {
             VLOG_INFO("%s: listening on port %"PRIu16,
-                      target, ntohs(sin.sin_port));
+                      target, ntohs(sin_p->sin_port));
         }
     }
 
@@ -1060,6 +1076,68 @@ getsockopt_int(int fd, int level, int option, const char *optname, int *valuep)
     return error;
 }
 
+/* Wrapper for getaddrinfo().  On success, 0 is returnd else -1 is returned for
+ * in error.  If 'res' is not NULL, output address list is paased to caller. */
+static int
+do_getaddrinfo(const char *host, const char *port,
+               struct sockaddr_storage *ssp)
+{
+    struct addrinfo hint;
+    struct addrinfo *info;
+    struct addrinfo *addr;
+    int ret;
+
+    memset(&hint, 0, sizeof hint);
+    hint.ai_family = AF_UNSPEC;
+    hint.ai_socktype = SOCK_STREAM;
+    hint.ai_flags = AI_PASSIVE;
+    hint.ai_canonname = NULL;
+    hint.ai_addr = NULL;
+    hint.ai_next = NULL;
+
+    ret = getaddrinfo(host, port, &hint, &info);
+    if (ret) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+        VLOG_ERR_RL(&rl, "\"%s\" is not a valid IP address", host);
+        return -1;
+    }
+
+    for (addr = info; addr != NULL; addr = addr->ai_next) {
+         memcpy(ssp, addr->ai_addr, addr->ai_addrlen);
+         break;
+    }
+    if (addr == NULL) {
+        ret = -1;
+    }
+    if (info) {
+        freeaddrinfo(info);
+    }
+
+    return ret;
+}
+
+/* Parse IP address and port from string 'itarget'.
+ * If 'host' and 'port' are not NULL, parsed string values are stored in
+ * them. */
+static void
+parse_active(char *itarget, const char **host, const char **port)
+{
+    char *ptr = NULL;
+    char *start_ptr = itarget;
+
+    while (*itarget != '\0') {
+        if (*itarget == ':') {
+            ptr = itarget;
+        }
+        itarget++;
+    }
+    if (host && port) {
+        *port = ++ptr;
+        *(--ptr) = '\0';
+        *host = start_ptr;
+    }
+}
+
 static void
 describe_sockaddr(struct ds *string, int fd,
                   int (*getaddr)(int, struct sockaddr *, socklen_t *))
@@ -1074,6 +1152,13 @@ describe_sockaddr(struct ds *string, int fd,
             memcpy(&sin, &ss, sizeof sin);
             ds_put_format(string, IP_FMT":%"PRIu16,
                           IP_ARGS(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+        } else if (ss.ss_family == AF_INET6) {
+            struct sockaddr_in6 sin6;
+
+            memcpy(&sin6, &ss, sizeof sin6);
+            ds_put_format(string, IP6_FMT":%"PRIu16,
+                          IP6_ARGS(sin6.sin6_addr.s6_addr16),
+                          ntohs(sin6.sin6_port));
         } else if (ss.ss_family == AF_UNIX) {
             struct sockaddr_un sun;
             const char *null;
diff --git a/lib/socket-util.h b/lib/socket-util.h
index 670eeb3..13e66fd 100644
--- a/lib/socket-util.h
+++ b/lib/socket-util.h
@@ -25,6 +25,7 @@
 #include "openvswitch/types.h"
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
+#include <netdb.h>
 
 int set_nonblocking(int fd);
 void xset_nonblocking(int fd);
@@ -48,14 +49,14 @@ ovs_be32 guess_netmask(ovs_be32 ip);
 int get_null_fd(void);
 
 bool inet_parse_active(const char *target, uint16_t default_port,
-                       struct sockaddr_in *sinp);
+                       struct sockaddr_storage *ssp);
 int inet_open_active(int style, const char *target, uint16_t default_port,
-		     struct sockaddr_in *sinp, int *fdp, uint8_t dscp);
+                     struct sockaddr_storage *ssp, int *fdp, uint8_t dscp);
 
 bool inet_parse_passive(const char *target, int default_port,
-                        struct sockaddr_in *sinp);
+                        struct sockaddr_storage *ssp);
 int inet_open_passive(int style, const char *target, int default_port,
-                      struct sockaddr_in *sinp, uint8_t dscp);
+                      struct sockaddr_storage *ssp, uint8_t dscp);
 
 int read_fully(int fd, void *, size_t, size_t *bytes_read);
 int write_fully(int fd, const void *, size_t, size_t *bytes_written);
diff --git a/lib/stream-provider.h b/lib/stream-provider.h
index 43c63e8..7e7092d 100644
--- a/lib/stream-provider.h
+++ b/lib/stream-provider.h
@@ -33,14 +33,18 @@ struct stream {
     ovs_be16 remote_port;
     ovs_be32 local_ip;
     ovs_be16 local_port;
+    struct in6_addr remote_ip6;
+    struct in6_addr local_ip6;
     char *name;
 };
 
 void stream_init(struct stream *, const struct stream_class *,
                  int connect_status, const char *name);
 void stream_set_remote_ip(struct stream *, ovs_be32 remote_ip);
+void stream_set_remote_ip6(struct stream *, struct in6_addr ip);
 void stream_set_remote_port(struct stream *, ovs_be16 remote_port);
 void stream_set_local_ip(struct stream *, ovs_be32 local_ip);
+void stream_set_local_ip6(struct stream *, struct in6_addr ip);
 void stream_set_local_port(struct stream *, ovs_be16 local_port);
 static inline void stream_assert_class(const struct stream *stream,
                                        const struct stream_class *class)
diff --git a/lib/stream-ssl.c b/lib/stream-ssl.c
index f2bd513..78034e3 100644
--- a/lib/stream-ssl.c
+++ b/lib/stream-ssl.c
@@ -204,10 +204,12 @@ want_to_poll_events(int want)
 
 static int
 new_ssl_stream(const char *name, int fd, enum session_type type,
-               enum ssl_state state, const struct sockaddr_in *remote,
+               enum ssl_state state, const struct sockaddr_storage *remote,
                struct stream **streamp)
 {
-    struct sockaddr_in local;
+    struct sockaddr_storage local;
+    struct sockaddr_in *local_in;
+    struct sockaddr_in6 *local_in6;
     socklen_t local_len = sizeof local;
     struct ssl_stream *sslv;
     SSL *ssl = NULL;
@@ -270,10 +272,25 @@ new_ssl_stream(const char *name, int fd, enum session_type type,
     /* Create and return the ssl_stream. */
     sslv = xmalloc(sizeof *sslv);
     stream_init(&sslv->stream, &ssl_stream_class, EAGAIN, name);
-    stream_set_remote_ip(&sslv->stream, remote->sin_addr.s_addr);
-    stream_set_remote_port(&sslv->stream, remote->sin_port);
-    stream_set_local_ip(&sslv->stream, local.sin_addr.s_addr);
-    stream_set_local_port(&sslv->stream, local.sin_port);
+
+    if (remote->ss_family == AF_INET) {
+        struct sockaddr_in *remote_in = (struct sockaddr_in *) remote;
+        stream_set_remote_ip(&sslv->stream, remote_in->sin_addr.s_addr);
+        stream_set_remote_port(&sslv->stream, remote_in->sin_port);
+    } else {
+        struct sockaddr_in6 *remote_in6 = (struct sockaddr_in6 *) remote;
+        stream_set_remote_ip6(&sslv->stream, remote_in6->sin6_addr);
+        stream_set_remote_port(&sslv->stream, remote_in6->sin6_port);
+    }
+    if (local.ss_family == AF_INET) {
+        local_in = (struct sockaddr_in *) &local;
+        stream_set_local_ip(&sslv->stream, local_in->sin_addr.s_addr);
+        stream_set_local_port(&sslv->stream, local_in->sin_port);
+    } else {
+        local_in6 = (struct sockaddr_in6 *) &local;
+        stream_set_local_ip6(&sslv->stream, local_in6->sin6_addr);
+        stream_set_local_port(&sslv->stream, local_in6->sin6_port);
+    }
     sslv->state = state;
     sslv->type = type;
     sslv->fd = fd;
@@ -309,7 +326,7 @@ ssl_stream_cast(struct stream *stream)
 static int
 ssl_open(const char *name, char *suffix, struct stream **streamp, uint8_t dscp)
 {
-    struct sockaddr_in sin;
+    struct sockaddr_storage ss;
     int error, fd;
 
     error = ssl_init();
@@ -317,11 +334,11 @@ ssl_open(const char *name, char *suffix, struct stream **streamp, uint8_t dscp)
         return error;
     }
 
-    error = inet_open_active(SOCK_STREAM, suffix, OFP_OLD_PORT, &sin, &fd,
+    error = inet_open_active(SOCK_STREAM, suffix, OFP_OLD_PORT, &ss, &fd,
                              dscp);
     if (fd >= 0) {
         int state = error ? STATE_TCP_CONNECTING : STATE_SSL_CONNECTING;
-        return new_ssl_stream(name, fd, CLIENT, state, &sin, streamp);
+        return new_ssl_stream(name, fd, CLIENT, state, &ss, streamp);
     } else {
         VLOG_ERR("%s: connect: %s", name, ovs_strerror(error));
         return error;
@@ -787,7 +804,8 @@ pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
           uint8_t dscp)
 {
     struct pssl_pstream *pssl;
-    struct sockaddr_in sin;
+    struct sockaddr_storage ss;
+    in_port_t port;
     char bound_name[128];
     int retval;
     int fd;
@@ -797,16 +815,29 @@ pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
         return retval;
     }
 
-    fd = inet_open_passive(SOCK_STREAM, suffix, OFP_OLD_PORT, &sin, dscp);
+    fd = inet_open_passive(SOCK_STREAM, suffix, OFP_OLD_PORT, &ss, dscp);
     if (fd < 0) {
         return -fd;
     }
-    sprintf(bound_name, "pssl:%"PRIu16":"IP_FMT,
-            ntohs(sin.sin_port), IP_ARGS(sin.sin_addr.s_addr));
+
+    if (ss.ss_family == AF_INET) {
+        struct sockaddr_in *sin_addr = (struct sockaddr_in *) &ss;
+
+        port = sin_addr->sin_port;
+        sprintf(bound_name, "pssl:%"PRIu16":"IP_FMT,
+                ntohs(port), IP_ARGS(sin_addr->sin_addr.s_addr));
+    } else {
+        struct sockaddr_in6 *sin_addr6 = (struct sockaddr_in6 *) &ss;
+
+        port = sin_addr6->sin6_port;
+        sprintf(bound_name, "pssl:%"PRIu16":"IP6_FMT,
+                ntohs(port),
+                IP6_ARGS(sin_addr6->sin6_addr.s6_addr16));
+    }
 
     pssl = xmalloc(sizeof *pssl);
     pstream_init(&pssl->pstream, &pssl_pstream_class, bound_name);
-    pstream_set_bound_port(&pssl->pstream, sin.sin_port);
+    pstream_set_bound_port(&pssl->pstream, port);
     pssl->fd = fd;
     *pstreamp = &pssl->pstream;
     return 0;
@@ -824,13 +855,13 @@ static int
 pssl_accept(struct pstream *pstream, struct stream **new_streamp)
 {
     struct pssl_pstream *pssl = pssl_pstream_cast(pstream);
-    struct sockaddr_in sin;
-    socklen_t sin_len = sizeof sin;
+    struct sockaddr_storage ss;
+    socklen_t sin_len = sizeof ss;
     char name[128];
     int new_fd;
     int error;
 
-    new_fd = accept(pssl->fd, (struct sockaddr *) &sin, &sin_len);
+    new_fd = accept(pssl->fd, (struct sockaddr *) &ss, &sin_len);
     if (new_fd < 0) {
         error = errno;
         if (error != EAGAIN) {
@@ -845,11 +876,23 @@ pssl_accept(struct pstream *pstream, struct stream **new_streamp)
         return error;
     }
 
-    sprintf(name, "ssl:"IP_FMT, IP_ARGS(sin.sin_addr.s_addr));
-    if (sin.sin_port != htons(OFP_OLD_PORT)) {
-        sprintf(strchr(name, '\0'), ":%"PRIu16, ntohs(sin.sin_port));
+    if (ss.ss_family == AF_INET) {
+        struct sockaddr_in *sin_addr = (struct sockaddr_in *) &ss;
+
+        sprintf(name, "ssl:"IP_FMT, IP_ARGS(sin_addr->sin_addr.s_addr));
+        if (sin_addr->sin_port != htons(OFP_OLD_PORT)) {
+            sprintf(strchr(name, '\0'), ":%"PRIu16, ntohs(sin_addr->sin_port));
+        }
+    } else {
+        struct sockaddr_in6 *sin_addr6 = (struct sockaddr_in6 *) &ss;
+
+        sprintf(name, "ssl:"IP6_FMT, IP6_ARGS(sin_addr6->sin6_addr.s6_addr16));
+        if (sin_addr6->sin6_port != htons(OFP_OLD_PORT)) {
+            sprintf(strchr(name, '\0'), ":%"PRIu16,
+            ntohs(sin_addr6->sin6_port));
+        }
     }
-    return new_ssl_stream(name, new_fd, SERVER, STATE_SSL_CONNECTING, &sin,
+    return new_ssl_stream(name, new_fd, SERVER, STATE_SSL_CONNECTING, &ss,
                           new_streamp);
 }
 
diff --git a/lib/stream-tcp.c b/lib/stream-tcp.c
index a4cdf45..6445625 100644
--- a/lib/stream-tcp.c
+++ b/lib/stream-tcp.c
@@ -21,6 +21,7 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
+#include <netdb.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
@@ -38,9 +39,11 @@ VLOG_DEFINE_THIS_MODULE(stream_tcp);
 
 static int
 new_tcp_stream(const char *name, int fd, int connect_status,
-               const struct sockaddr_in *remote, struct stream **streamp)
+               const struct sockaddr_storage *remote, struct stream **streamp)
 {
-    struct sockaddr_in local;
+    struct sockaddr_storage local;
+    struct sockaddr_in *addr_in;
+    struct sockaddr_in6 *addr_in6;
     socklen_t local_len = sizeof local;
     int on = 1;
     int retval;
@@ -61,10 +64,25 @@ new_tcp_stream(const char *name, int fd, int connect_status,
     retval = new_fd_stream(name, fd, connect_status, streamp);
     if (!retval) {
         struct stream *stream = *streamp;
-        stream_set_remote_ip(stream, remote->sin_addr.s_addr);
-        stream_set_remote_port(stream, remote->sin_port);
-        stream_set_local_ip(stream, local.sin_addr.s_addr);
-        stream_set_local_port(stream, local.sin_port);
+
+        if (remote->ss_family == AF_INET) {
+            addr_in = (struct sockaddr_in *) remote;
+            stream_set_remote_ip(stream, addr_in->sin_addr.s_addr);
+            stream_set_remote_port(stream, addr_in->sin_port);
+        } else {
+            addr_in6 = (struct sockaddr_in6 *) remote;
+            stream_set_remote_ip6(stream, addr_in6->sin6_addr);
+            stream_set_remote_port(stream, addr_in6->sin6_port);
+        }
+        if (local.ss_family == AF_INET) {
+            addr_in = (struct sockaddr_in *) &local;
+            stream_set_local_ip(stream, addr_in->sin_addr.s_addr);
+            stream_set_local_port(stream, addr_in->sin_port);
+        } else {
+            addr_in6 = (struct sockaddr_in6 *) &local;
+            stream_set_local_ip6(stream, addr_in6->sin6_addr);
+            stream_set_local_port(stream, addr_in6->sin6_port);
+        }
     }
     return retval;
 }
@@ -72,12 +90,12 @@ new_tcp_stream(const char *name, int fd, int connect_status,
 static int
 tcp_open(const char *name, char *suffix, struct stream **streamp, uint8_t dscp)
 {
-    struct sockaddr_in sin;
+    struct sockaddr_storage ss;
     int fd, error;
 
-    error = inet_open_active(SOCK_STREAM, suffix, 0, &sin, &fd, dscp);
+    error = inet_open_active(SOCK_STREAM, suffix, 0, &ss, &fd, dscp);
     if (fd >= 0) {
-        return new_tcp_stream(name, fd, error, &sin, streamp);
+        return new_tcp_stream(name, fd, error, &ss, streamp);
     } else {
         VLOG_ERR("%s: connect: %s", name, ovs_strerror(error));
         return error;
@@ -106,22 +124,33 @@ static int
 ptcp_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
           uint8_t dscp)
 {
-    struct sockaddr_in sin;
+    struct sockaddr_storage ss;
+    in_port_t port;
     char bound_name[128];
     int error;
     int fd;
 
-    fd = inet_open_passive(SOCK_STREAM, suffix, -1, &sin, dscp);
+    fd = inet_open_passive(SOCK_STREAM, suffix, -1, &ss, dscp);
     if (fd < 0) {
         return -fd;
     }
 
-    sprintf(bound_name, "ptcp:%"PRIu16":"IP_FMT,
-            ntohs(sin.sin_port), IP_ARGS(sin.sin_addr.s_addr));
+    if (ss.ss_family == AF_INET) {
+        struct sockaddr_in *sin_addr = (struct sockaddr_in *) &ss;
+        port = sin_addr->sin_port;
+        sprintf(bound_name, "ptcp:%"PRIu16":"IP_FMT,
+                ntohs(sin_addr->sin_port), IP_ARGS(sin_addr->sin_addr.s_addr));
+    } else {
+        struct sockaddr_in6 *sin_addr6 = (struct sockaddr_in6 *) &ss;
+        port = sin_addr6->sin6_port;
+        sprintf(bound_name, "ptcp:%"PRIu16":"IP6_FMT,
+                ntohs(sin_addr6->sin6_port),
+                IP6_ARGS(sin_addr6->sin6_addr.s6_addr16));
+    }
     error = new_fd_pstream(bound_name, fd, ptcp_accept, set_dscp, NULL,
                            pstreamp);
     if (!error) {
-        pstream_set_bound_port(*pstreamp, sin.sin_port);
+        pstream_set_bound_port(*pstreamp, port);
     }
     return error;
 }
@@ -137,10 +166,13 @@ ptcp_accept(int fd, const struct sockaddr *sa, size_t sa_len,
     if (sa_len == sizeof(struct sockaddr_in) && sin->sin_family == AF_INET) {
         sprintf(name, "tcp:"IP_FMT, IP_ARGS(sin->sin_addr.s_addr));
         sprintf(strchr(name, '\0'), ":%"PRIu16, ntohs(sin->sin_port));
-    } else {
-        strcpy(name, "tcp");
+    } else if (sa_len == sizeof(struct sockaddr_in6)) {
+        const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *) sa;
+        sprintf(name, "tcp:"IP6_FMT, IP6_ARGS(sin6->sin6_addr.s6_addr16));
+        sprintf(strchr(name, '\0'), ":%"PRIu16, ntohs(sin->sin_port));
     }
-    return new_tcp_stream(name, fd, 0, sin, streamp);
+    return new_tcp_stream(name, fd, 0, (struct sockaddr_storage *) sa,
+                          streamp);
 }
 
 const struct pstream_class ptcp_pstream_class = {
diff --git a/lib/stream.c b/lib/stream.c
index 0442d84..227cd0d 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -687,6 +687,18 @@ stream_set_local_port(struct stream *stream, ovs_be16 port)
 }
 
 void
+stream_set_remote_ip6(struct stream *stream, struct in6_addr ip)
+{
+    memcpy(&stream->remote_ip6, &ip, sizeof ip);
+}
+
+void
+stream_set_local_ip6(struct stream *stream, struct in6_addr ip)
+{
+    memcpy(&stream->local_ip6, &ip, sizeof ip);
+}
+
+void
 pstream_init(struct pstream *pstream, const struct pstream_class *class,
             const char *name)
 {
@@ -776,18 +788,18 @@ pstream_open_with_default_port(const char *name_,
 /*
  * This function extracts IP address and port from the target string.
  *
- *     - On success, function returns true and fills *sin structure with port
+ *     - On success, function returns true and fills *ss structure with port
  *       and IP address. If port was absent in target string then it will use
  *       corresponding default port value.
- *     - On error, function returns false and *sin contains garbage.
+ *     - On error, function returns false and *ss contains garbage.
  */
 bool
 stream_parse_target_with_default_port(const char *target,
                                       uint16_t default_port,
-                                      struct sockaddr_in *sin)
+                                      struct sockaddr_storage *ss)
 {
     return ((!strncmp(target, "tcp:", 4) || !strncmp(target, "ssl:", 4))
-             && inet_parse_active(target + 4, default_port, sin));
+            && inet_parse_active(target + 4, default_port, ss));
 }
 
 /* Attempts to guess the content type of a stream whose first few bytes were
diff --git a/lib/stream.h b/lib/stream.h
index d966cde..3780ff9 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -81,7 +81,7 @@ int pstream_open_with_default_port(const char *name,
                                    uint8_t dscp);
 bool stream_parse_target_with_default_port(const char *target,
                                            uint16_t default_port,
-                                           struct sockaddr_in *sin);
+                                           struct sockaddr_storage *ss);
 int stream_or_pstream_needs_probes(const char *name);
 
 /* Error reporting. */
diff --git a/lib/vconn-provider.h b/lib/vconn-provider.h
index 640c5b6..1e628ae 100644
--- a/lib/vconn-provider.h
+++ b/lib/vconn-provider.h
@@ -19,7 +19,7 @@
 
 /* Provider interface to vconns, which provide a virtual connection to an
  * OpenFlow device. */
-
+#include <netdb.h>
 #include "vconn.h"
 #include "util.h"
 #include "openflow/openflow-common.h"
@@ -44,6 +44,8 @@ struct vconn {
     ovs_be16 remote_port;
     ovs_be32 local_ip;
     ovs_be16 local_port;
+    struct in6_addr remote_ip6;
+    struct in6_addr local_ip6;
 
     char *name;
 };
@@ -52,8 +54,10 @@ void vconn_init(struct vconn *, const struct vconn_class *, int connect_status,
                 const char *name, uint32_t allowed_versions);
 void vconn_free_data(struct vconn *vconn);
 void vconn_set_remote_ip(struct vconn *, ovs_be32 remote_ip);
+void vconn_set_remote_ip6(struct vconn *, struct in6_addr remote_ip);
 void vconn_set_remote_port(struct vconn *, ovs_be16 remote_port);
 void vconn_set_local_ip(struct vconn *, ovs_be32 local_ip);
+void vconn_set_local_ip6(struct vconn *, struct in6_addr local_ip);
 void vconn_set_local_port(struct vconn *, ovs_be16 local_port);
 static inline void vconn_assert_class(const struct vconn *vconn,
                                       const struct vconn_class *class)
diff --git a/lib/vconn.c b/lib/vconn.c
index 5708987..7a363d1 100644
--- a/lib/vconn.c
+++ b/lib/vconn.c
@@ -375,6 +375,20 @@ vconn_get_local_ip(const struct vconn *vconn)
     return vconn->local_ip;
 }
 
+/* Copies the IP address used to connect to the peer into 'ip'. */
+void
+vconn_get_remote_ip6(struct vconn *vconn, struct in6_addr *ip)
+{
+    memcpy(ip, &vconn->remote_ip6, sizeof vconn->remote_ip6);
+}
+
+/* Copies the IP address used to connect to the peer into 'ip'. */
+void
+vconn_get_local_ip6(struct vconn *vconn, struct in6_addr *ip)
+{
+    memcpy(ip, &vconn->local_ip6, sizeof vconn->local_ip6);
+}
+
 /* Returns the transport port used to connect to the peer, or 0 if the
  * connection does not contain a port or if the port is not yet known. */
 ovs_be16
@@ -1148,6 +1162,18 @@ vconn_set_local_port(struct vconn *vconn, ovs_be16 port)
 }
 
 void
+vconn_set_local_ip6(struct vconn *vconn, struct in6_addr ip)
+{
+    memcpy(&vconn->local_ip6, &ip, sizeof ip);
+}
+
+void
+vconn_set_remote_ip6(struct vconn *vconn, struct in6_addr ip)
+{
+    memcpy(&vconn->remote_ip6, &ip, sizeof ip);
+}
+
+void
 pvconn_init(struct pvconn *pvconn, const struct pvconn_class *class,
             const char *name, uint32_t allowed_versions)
 {
diff --git a/lib/vconn.h b/lib/vconn.h
index b15388c..8c8afe4 100644
--- a/lib/vconn.h
+++ b/lib/vconn.h
@@ -17,6 +17,7 @@
 #ifndef VCONN_H
 #define VCONN_H 1
 
+#include <netdb.h>
 #include <stdbool.h>
 #include "openvswitch/types.h"
 #include "openflow/openflow.h"
@@ -49,6 +50,8 @@ ovs_be32 vconn_get_remote_ip(const struct vconn *);
 ovs_be16 vconn_get_remote_port(const struct vconn *);
 ovs_be32 vconn_get_local_ip(const struct vconn *);
 ovs_be16 vconn_get_local_port(const struct vconn *);
+void vconn_get_remote_ip6(struct vconn *vconn, struct in6_addr *ip);
+void vconn_get_local_ip6(struct vconn *vconn, struct in6_addr *ip);
 
 int vconn_connect(struct vconn *);
 int vconn_recv(struct vconn *, struct ofpbuf **);
diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
index da25930..b632222 100644
--- a/ofproto/connmgr.c
+++ b/ofproto/connmgr.c
@@ -734,6 +734,7 @@ update_in_band_remotes(struct connmgr *mgr)
     /* Add all the remotes. */
     HMAP_FOR_EACH (ofconn, hmap_node, &mgr->controllers) {
         struct sockaddr_in *sin = &addrs[n_addrs];
+        struct sockaddr_storage sstorage;
         const char *target = rconn_get_target(ofconn->rconn);
 
         if (ofconn->band == OFPROTO_OUT_OF_BAND) {
@@ -742,8 +743,12 @@ update_in_band_remotes(struct connmgr *mgr)
 
         if (stream_parse_target_with_default_port(target,
                                                   OFP_OLD_PORT,
-                                                  sin)) {
-            n_addrs++;
+                                                  &sstorage)) {
+            if (sstorage.ss_family == AF_INET) {
+                /* Allow only IPv4 Address for in-band. */
+                n_addrs++;
+                memcpy(sin, &sstorage, sizeof *sin);
+            }
         }
     }
     for (i = 0; i < mgr->n_extra_remotes; i++) {
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index 158887f..1028ca4 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -242,6 +242,7 @@ sflow_choose_agent_address(const char *agent_device,
 {
     const char *target;
     struct in_addr in4;
+    struct sockaddr_storage ss;
 
     memset(agent_addr, 0, sizeof *agent_addr);
     agent_addr->type = SFLADDRESSTYPE_IP_V4;
@@ -253,13 +254,18 @@ sflow_choose_agent_address(const char *agent_device,
     }
 
     SSET_FOR_EACH (target, targets) {
-        struct sockaddr_in sin;
         char name[IFNAMSIZ];
 
-        if (inet_parse_active(target, SFL_DEFAULT_COLLECTOR_PORT, &sin)
-            && route_table_get_name(sin.sin_addr.s_addr, name)
-            && !netdev_get_in4_by_name(name, &in4)) {
-            goto success;
+        if (inet_parse_active(target, SFL_DEFAULT_COLLECTOR_PORT, &ss)) {
+            if (ss.ss_family == AF_INET) {
+                struct sockaddr_in *tsin = (struct sockaddr_in *) &ss;
+                if (route_table_get_name(tsin->sin_addr.s_addr, name)
+                    && !netdev_get_in4_by_name(name, &in4)) {
+                    goto success;
+                }
+            } else if (ss.ss_family == AF_INET6) {
+                goto success;
+            }
         }
     }
 
@@ -271,7 +277,15 @@ sflow_choose_agent_address(const char *agent_device,
     return false;
 
 success:
-    agent_addr->address.ip_v4.addr = (OVS_FORCE uint32_t) in4.s_addr;
+    if (ss.ss_family == AF_INET) {
+        agent_addr->address.ip_v4.addr = (OVS_FORCE uint32_t) in4.s_addr;
+    } else if (ss.ss_family == AF_INET6) {
+        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
+
+        memcpy(agent_addr->address.ip_v6.addr, sin6->sin6_addr.s6_addr16,
+               sizeof sin6->sin6_addr);
+        agent_addr->type = SFLADDRESSTYPE_IP_V6;
+    }
     return true;
 }
 
diff --git a/python/ovs/socket_util.py b/python/ovs/socket_util.py
index c657047..ff2a79c 100644
--- a/python/ovs/socket_util.py
+++ b/python/ovs/socket_util.py
@@ -177,24 +177,44 @@ def check_connection_completion(sock):
         return errno.EAGAIN
 
 
+def is_valid_ipv4_address(address):
+    try:
+        socket.inet_pton(socket.AF_INET, address)
+    except AttributeError:
+        try:
+            socket.inet_aton(address)
+        except socket.error:
+            return False
+    except socket.error:
+        return False
+
+    return True
+
+
 def inet_parse_active(target, default_port):
     address = target.split(":")
-    host_name = address[0]
-    if not host_name:
-        raise ValueError("%s: bad peer name format" % target)
     if len(address) >= 2:
-        port = int(address[1])
-    elif default_port:
-        port = default_port
+        host_name = ":".join(address[0:-1])
+        port = int(address[-1])
     else:
-        raise ValueError("%s: port number must be specified" % target)
+        if default_port:
+            port = default_port
+        else:
+            raise ValueError("%s: port number must be specified" % target)
+        host_name = address[0]
+    if not host_name:
+        raise ValueError("%s: bad peer name format" % target)
     return (host_name, port)
 
 
 def inet_open_active(style, target, default_port, dscp):
     address = inet_parse_active(target, default_port)
     try:
-        sock = socket.socket(socket.AF_INET, style, 0)
+        is_addr_inet = is_valid_ipv4_address(address[0])
+        if is_addr_inet:
+            sock = socket.socket(socket.AF_INET, style, 0)
+        else:
+            sock = socket.socket(socket.AF_INET6, style, 0)
     except socket.error, e:
         return get_exception_errno(e), None
 
diff --git a/tests/test-sflow.c b/tests/test-sflow.c
index cba01b9..2d830d8 100644
--- a/tests/test-sflow.c
+++ b/tests/test-sflow.c
@@ -325,12 +325,10 @@ process_datagram(struct sflow_xdr *x)
 
     /* Store the agent address as a string. */
     if (x->agentAddr.type == SFLOW_ADDRTYPE_IP6) {
+        ovs_be16 *addr=(ovs_be16 *) &x->agentAddr.a.ip6;
+
         snprintf(x->agentIPStr, SFLOW_MAX_AGENTIP_STRLEN,
-                 "%04x:%04x:%04x:%04x",
-                 x->agentAddr.a.ip6[0],
-                 x->agentAddr.a.ip6[1],
-                 x->agentAddr.a.ip6[2],
-                 x->agentAddr.a.ip6[3]);
+                 IP6_FMT, IP6_ARGS(addr));
     } else {
         snprintf(x->agentIPStr, SFLOW_MAX_AGENTIP_STRLEN,
                  IP_FMT, IP_ARGS(x->agentAddr.a.ip4));
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index c2307be..578df5d 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -473,11 +473,15 @@ collect_in_band_managers(const struct ovsrec_open_vswitch *ovs_cfg,
         managers = xmalloc(sset_count(&targets) * sizeof *managers);
         SSET_FOR_EACH (target, &targets) {
             struct sockaddr_in *sin = &managers[n_managers];
+            struct sockaddr_storage sstorage;
 
             if (stream_parse_target_with_default_port(target,
                                                       OVSDB_OLD_PORT,
-                                                      sin)) {
-                n_managers++;
+                                                      &sstorage)) {
+                if (sstorage.ss_family == AF_INET) {
+                    n_managers++;
+                    memcpy(sin, &sstorage, sizeof *sin);
+                }
             }
         }
     }
-- 
1.7.10.4




More information about the dev mailing list