2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-01 14:55:18 +00:00

Add IPv6 support for OpenFlow, OVSDB, NetFlow, and sFlow.

Does not add IPv6 support for in-band control.

Co-authored-by: Ben Pfaff <blp@nicira.com>
Signed-off-by: Nandan Nivgune <nandan.nivgune@calsoftinc.com>
Signed-off-by: Abhijit Bhopatkar <abhijit.bhopatkar@calsoftinc.com>
Signed-off-by: Arun Sharma <arun.sharma@calsoftinc.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Arun Sharma
2014-02-06 16:04:05 -08:00
committed by Ben Pfaff
parent 978188b242
commit e731d71bf4
26 changed files with 773 additions and 443 deletions

1
NEWS
View File

@@ -64,6 +64,7 @@ v2.1.0 - xx xxx xxxx
hard limit on the number of flows in the datapath. It defaults to 200,000
flows. OVS automatically adjusts this number depending on network
conditions.
- Added IPv6 support for active and passive socket communications.
v2.0.0 - 15 Oct 2013

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2013 Nicira, Inc.
* Copyright (c) 2011, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,6 +48,15 @@ struct in6_addr {
extern const struct in6_addr in6addr_any;
/* Ditto, for IPv6. */
struct sockaddr_in6 {
sa_family_t sin6_family;
in_port_t sin6_port; /* Transport layer port # */
uint32_t sin6_flowinfo; /* IPv6 flow information */
struct in6_addr sin6_addr; /* IPv6 address */
uint32_t sin6_scope_id; /* IPv6 scope-id */
};
#define IPPROTO_IP 0
#define IPPROTO_HOPOPTS 0
#define IPPROTO_ICMP 1
@@ -84,6 +93,7 @@ extern const struct in6_addr in6addr_any;
#define INADDR_ANY 0x00000000
#define INADDR_BROADCAST 0xffffffff
#define INADDR_LOOPBACK 0x7f000001
#define INADDR_NONE 0xffffffff
#define INET6_ADDRSTRLEN 46

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -612,59 +612,125 @@ guess_netmask(ovs_be32 ip_)
: htonl(0)); /* ??? */
}
/* Parses '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'.
/* This is like strsep() except:
*
* On success, returns true and stores the parsed remote address into '*sinp'.
* On failure, logs an error, stores zeros into '*sinp', and returns false. */
bool
inet_parse_active(const char *target_, uint16_t default_port,
struct sockaddr_in *sinp)
* - The separator string is ":".
*
* - Square brackets [] quote ":" separators and are removed from the
* tokens. */
static char *
parse_bracketed_token(char **pp)
{
char *target = xstrdup(target_);
char *save_ptr = NULL;
const char *host_name;
const char *port_string;
bool ok = false;
char *p = *pp;
/* Defaults. */
sinp->sin_family = AF_INET;
sinp->sin_port = htons(default_port);
if (p == NULL) {
return NULL;
} else if (*p == '\0') {
*pp = NULL;
return p;
} else if (*p == '[') {
char *start = p + 1;
char *end = start + strcspn(start, "]");
*pp = (*end == '\0' ? NULL
: end[1] == ':' ? end + 2
: end + 1);
*end = '\0';
return start;
} else {
char *start = p;
char *end = start + strcspn(start, ":");
*pp = *end == '\0' ? NULL : end + 1;
*end = '\0';
return start;
}
}
/* Tokenize. */
host_name = strtok_r(target, ":", &save_ptr);
port_string = strtok_r(NULL, ":", &save_ptr);
if (!host_name) {
VLOG_ERR("%s: bad peer name format", target_);
goto exit;
static bool
parse_sockaddr_components(struct sockaddr_storage *ss,
const char *host_s,
const char *port_s, uint16_t default_port,
const char *s)
{
struct sockaddr_in *sin = ALIGNED_CAST(struct sockaddr_in *, ss);
int port;
if (port_s && port_s[0]) {
if (!str_to_int(port_s, 10, &port) || port < 0 || port > 65535) {
VLOG_ERR("%s: bad port number \"%s\"", s, port_s);
}
} else {
port = default_port;
}
/* Look up IP, port. */
if (lookup_ip(host_name, &sinp->sin_addr)) {
goto exit;
}
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_);
goto exit;
memset(ss, 0, sizeof *ss);
if (strchr(host_s, ':')) {
struct sockaddr_in6 *sin6
= ALIGNED_CAST(struct sockaddr_in6 *, ss);
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(port);
if (!inet_pton(AF_INET6, host_s, sin6->sin6_addr.s6_addr)) {
VLOG_ERR("%s: bad IPv6 address \"%s\"", s, host_s);
goto exit;
}
} else {
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
if (!inet_pton(AF_INET, host_s, &sin->sin_addr.s_addr)) {
VLOG_ERR("%s: bad IPv4 address \"%s\"", s, host_s);
goto exit;
}
}
ok = true;
return true;
exit:
memset(ss, 0, sizeof *ss);
return false;
}
/* Parses 'target', which should be a string in the format "<host>[:<port>]".
* <host>, which is required, may be an IPv4 address or an IPv6 address
* enclosed in square brackets. 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 '*ss'.
* On failure, logs an error, stores zeros into '*ss', and returns false. */
bool
inet_parse_active(const char *target_, uint16_t default_port,
struct sockaddr_storage *ss)
{
char *target = xstrdup(target_);
const char *port;
const char *host;
char *p;
bool ok;
p = target;
host = parse_bracketed_token(&p);
port = parse_bracketed_token(&p);
if (!host) {
VLOG_ERR("%s: host must be specified", target_);
ok = false;
} else if (!port && !default_port) {
VLOG_ERR("%s: port must be specified", target_);
ok = false;
} else {
ok = parse_sockaddr_components(ss, host, port, default_port, target_);
}
if (!ok) {
memset(sinp, 0, sizeof *sinp);
memset(ss, 0, sizeof *ss);
}
free(target);
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>, which is required, may be an IPv4 address or an
* IPv6 address enclosed in square brackets. 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 +739,27 @@ 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 'ss' is non-null, then on success stores the target address into '*ss'.
*
* '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 ss;
int fd = -1;
int error;
/* Parse. */
if (!inet_parse_active(target, default_port, &sin)) {
if (!inet_parse_active(target, default_port, &ss)) {
error = EAFNOSUPPORT;
goto exit;
}
/* Create non-blocking socket. */
fd = socket(AF_INET, style, 0);
fd = socket(ss.ss_family, style, 0);
if (fd < 0) {
VLOG_ERR("%s: socket: %s", target, ovs_strerror(errno));
error = errno;
@@ -705,8 +770,8 @@ inet_open_active(int style, const char *target, uint16_t default_port,
goto exit;
}
/* The dscp bits must be configured before connect() to ensure that the TOS
* field is set during the connection establishment. If set after
/* The dscp bits must be configured before connect() to ensure that the
* TOS field is set during the connection establishment. If set after
* connect(), the handshake SYN frames will be sent with a TOS of 0. */
error = set_dscp(fd, dscp);
if (error) {
@@ -715,25 +780,32 @@ inet_open_active(int style, const char *target, uint16_t default_port,
}
/* Connect. */
error = connect(fd, (struct sockaddr *) &sin, sizeof sin) == 0 ? 0 : errno;
error = connect(fd, (struct sockaddr *) &ss, ss_length(&ss)) == 0
? 0
: errno;
if (error == EINPROGRESS) {
error = EAGAIN;
}
exit:
if (!error || error == EAGAIN) {
if (sinp) {
*sinp = sin;
if (error && error != EAGAIN) {
if (ssp) {
memset(ssp, 0, sizeof *ssp);
}
if (fd >= 0) {
close(fd);
fd = -1;
}
} else {
if (ssp) {
*ssp = ss;
}
} else if (fd >= 0) {
close(fd);
fd = -1;
}
*fdp = fd;
return error;
}
/* Parses 'target', which should be a string in the format "[<port>][:<ip>]":
/* Parses 'target', which should be a string in the format "[<port>][:<host>]":
*
* - If 'default_port' is -1, then <port> is required. Otherwise, if
* <port> is omitted, then 'default_port' is used instead.
@@ -741,54 +813,41 @@ exit:
* - If <port> (or 'default_port', if used) is 0, then no port is bound
* and the TCP/IP stack will select a port.
*
* - If <ip> is omitted then the IP address is wildcarded.
* - <host> is optional. If supplied, it may be an IPv4 address or an
* IPv6 address enclosed in square brackets. If omitted, 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 '*ss' and returns true; otherwise
* zeros '*ss' and returns false. */
bool
inet_parse_passive(const char *target_, int default_port,
struct sockaddr_in *sinp)
struct sockaddr_storage *ss)
{
char *target = xstrdup(target_);
char *string_ptr = target;
const char *host_name;
const char *port_string;
bool ok = false;
int port;
const char *port;
const char *host;
char *p;
bool ok;
/* 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);
/* 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;
p = target;
port = parse_bracketed_token(&p);
host = parse_bracketed_token(&p);
if (!port && default_port < 0) {
VLOG_ERR("%s: port must be specified", target_);
ok = false;
} else {
ok = parse_sockaddr_components(ss, host ? host : "0.0.0.0",
port, default_port, target_);
}
/* Parse optional bind IP. */
host_name = strsep(&string_ptr, ":");
if (host_name && host_name[0] && lookup_ip(host_name, &sinp->sin_addr)) {
goto exit;
}
ok = true;
exit:
if (!ok) {
memset(sinp, 0, sizeof *sinp);
memset(ss, 0, sizeof *ss);
}
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 +858,27 @@ 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 'ss' is non-null, then on success stores the bound address into '*ss'.
*
* '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;
int fd = 0, error;
unsigned int yes = 1;
if (!inet_parse_passive(target, default_port, &sin)) {
if (!inet_parse_passive(target, default_port, &ss)) {
return -EAFNOSUPPORT;
}
kernel_chooses_port = ss_get_port(&ss) == 0;
/* 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));
@@ -838,7 +897,7 @@ inet_open_passive(int style, const char *target, int default_port,
}
/* Bind. */
if (bind(fd, (struct sockaddr *) &sin, sizeof sin) < 0) {
if (bind(fd, (struct sockaddr *) &ss, ss_length(&ss)) < 0) {
error = errno;
VLOG_ERR("%s: bind: %s", target, ovs_strerror(error));
goto error;
@@ -860,31 +919,28 @@ 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 ss_len = sizeof ss;
if (getsockname(fd, (struct sockaddr *) &ss, &ss_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 (kernel_chooses_port) {
VLOG_INFO("%s: listening on port %"PRIu16,
target, ntohs(sin.sin_port));
target, ss_get_port(&ss));
}
if (ssp) {
*ssp = ss;
}
}
return fd;
error:
if (ssp) {
memset(ssp, 0, sizeof *ssp);
}
close(fd);
return -error;
}
@@ -1060,12 +1116,12 @@ describe_sockaddr(struct ds *string, int fd,
socklen_t len = sizeof ss;
if (!getaddr(fd, (struct sockaddr *) &ss, &len)) {
if (ss.ss_family == AF_INET) {
struct sockaddr_in sin;
if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) {
char addrbuf[SS_NTOP_BUFSIZE];
memcpy(&sin, &ss, sizeof sin);
ds_put_format(string, IP_FMT":%"PRIu16,
IP_ARGS(sin.sin_addr.s_addr), ntohs(sin.sin_port));
ds_put_format(string, "%s:%"PRIu16,
ss_format_address(&ss, addrbuf, sizeof addrbuf),
ss_get_port(&ss));
} else if (ss.ss_family == AF_UNIX) {
struct sockaddr_un sun;
const char *null;
@@ -1225,4 +1281,66 @@ af_inet_ifreq_ioctl(const char *name, struct ifreq *ifr, unsigned long int cmd,
}
return error;
}
/* sockaddr_storage helpers. */
/* Returns the IPv4 or IPv6 port in 'ss'. */
uint16_t
ss_get_port(const struct sockaddr_storage *ss)
{
if (ss->ss_family == AF_INET) {
const struct sockaddr_in *sin
= ALIGNED_CAST(const struct sockaddr_in *, ss);
return ntohs(sin->sin_port);
} else if (ss->ss_family == AF_INET6) {
const struct sockaddr_in6 *sin6
= ALIGNED_CAST(const struct sockaddr_in6 *, ss);
return ntohs(sin6->sin6_port);
} else {
OVS_NOT_REACHED();
}
}
/* Formats the IPv4 or IPv6 address in 'ss' into the 'bufsize' bytes in 'buf'.
* If 'ss' is an IPv6 address, puts square brackets around the address.
* 'bufsize' should be at least SS_NTOP_BUFSIZE.
*
* Returns 'buf'. */
char *
ss_format_address(const struct sockaddr_storage *ss,
char *buf, size_t bufsize)
{
ovs_assert(bufsize >= SS_NTOP_BUFSIZE);
if (ss->ss_family == AF_INET) {
const struct sockaddr_in *sin
= ALIGNED_CAST(const struct sockaddr_in *, ss);
snprintf(buf, bufsize, IP_FMT, IP_ARGS(sin->sin_addr.s_addr));
} else if (ss->ss_family == AF_INET6) {
const struct sockaddr_in6 *sin6
= ALIGNED_CAST(const struct sockaddr_in6 *, ss);
buf[0] = '[';
inet_ntop(AF_INET6, sin6->sin6_addr.s6_addr, buf + 1, bufsize - 1);
strcpy(strchr(buf, '\0'), "]");
} else {
OVS_NOT_REACHED();
}
return buf;
}
size_t
ss_length(const struct sockaddr_storage *ss)
{
switch (ss->ss_family) {
case AF_INET:
return sizeof(struct sockaddr_in);
case AF_INET6:
return sizeof(struct sockaddr_in6);
default:
OVS_NOT_REACHED();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,14 +48,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);
@@ -79,4 +79,12 @@ int af_inet_ioctl(unsigned long int command, const void *arg);
int af_inet_ifreq_ioctl(const char *name, struct ifreq *,
unsigned long int cmd, const char *cmd_name);
/* Functions for working with sockaddr_storage that might contain an IPv4 or
* IPv6 address. */
uint16_t ss_get_port(const struct sockaddr_storage *);
#define SS_NTOP_BUFSIZE (1 + INET6_ADDRSTRLEN + 1)
char *ss_format_address(const struct sockaddr_storage *,
char *buf, size_t bufsize);
size_t ss_length(const struct sockaddr_storage *);
#endif /* socket-util.h */

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2009, 2010, 2012, 2013 Nicira, Inc.
* Copyright (c) 2008, 2009, 2010, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -148,7 +148,7 @@ struct fd_pstream
{
struct pstream pstream;
int fd;
int (*accept_cb)(int fd, const struct sockaddr *, size_t sa_len,
int (*accept_cb)(int fd, const struct sockaddr_storage *, size_t ss_len,
struct stream **);
int (*set_dscp_cb)(int fd, uint8_t dscp);
char *unlink_path;
@@ -179,8 +179,8 @@ fd_pstream_cast(struct pstream *pstream)
* implementation never fails.) */
int
new_fd_pstream(const char *name, int fd,
int (*accept_cb)(int fd, const struct sockaddr *sa,
size_t sa_len, struct stream **streamp),
int (*accept_cb)(int fd, const struct sockaddr_storage *ss,
size_t ss_len, struct stream **streamp),
int (*set_dscp_cb)(int fd, uint8_t dscp),
char *unlink_path, struct pstream **pstreamp)
{
@@ -227,8 +227,7 @@ pfd_accept(struct pstream *pstream, struct stream **new_streamp)
return retval;
}
return ps->accept_cb(new_fd, (const struct sockaddr *) &ss, ss_len,
new_streamp);
return ps->accept_cb(new_fd, &ss, ss_len, new_streamp);
}
static void

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2009, 2012 Nicira, Inc.
* Copyright (c) 2008, 2009, 2012, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,13 +23,13 @@
struct stream;
struct pstream;
struct sockaddr;
struct sockaddr_storage;
int new_fd_stream(const char *name, int fd, int connect_status,
struct stream **streamp);
int new_fd_pstream(const char *name, int fd,
int (*accept_cb)(int fd, const struct sockaddr *,
size_t sa_len, struct stream **),
int (*accept_cb)(int fd, const struct sockaddr_storage *ss,
size_t ss_len, struct stream **),
int (*set_dscp_cb)(int fd, uint8_t dscp),
char *unlink_path,
struct pstream **pstreamp);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -206,7 +206,7 @@ static int
new_ssl_stream(const char *name, int fd, enum session_type type,
enum ssl_state state, struct stream **streamp)
{
struct sockaddr_in local;
struct sockaddr_storage local;
socklen_t local_len = sizeof local;
struct ssl_stream *sslv;
SSL *ssl = NULL;
@@ -780,9 +780,11 @@ static int
pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
uint8_t dscp)
{
char bound_name[SS_NTOP_BUFSIZE + 16];
char addrbuf[SS_NTOP_BUFSIZE];
struct sockaddr_storage ss;
struct pssl_pstream *pssl;
struct sockaddr_in sin;
char bound_name[128];
uint16_t port;
int retval;
int fd;
@@ -791,16 +793,18 @@ 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));
port = ss_get_port(&ss);
snprintf(bound_name, sizeof bound_name, "ptcp:%"PRIu16":%s",
port, ss_format_address(&ss, addrbuf, sizeof addrbuf));
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, htons(port));
pssl->fd = fd;
*pstreamp = &pssl->pstream;
return 0;
@@ -818,13 +822,14 @@ 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;
char name[128];
char name[SS_NTOP_BUFSIZE + 16];
char addrbuf[SS_NTOP_BUFSIZE];
struct sockaddr_storage ss;
socklen_t ss_len = sizeof ss;
int new_fd;
int error;
new_fd = accept(pssl->fd, (struct sockaddr *) &sin, &sin_len);
new_fd = accept(pssl->fd, (struct sockaddr *) &ss, &ss_len);
if (new_fd < 0) {
error = errno;
if (error != EAGAIN) {
@@ -839,10 +844,9 @@ 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));
}
snprintf(name, sizeof name, "tcp:%s:%"PRIu16,
ss_format_address(&ss, addrbuf, sizeof addrbuf),
ss_get_port(&ss));
return new_ssl_stream(name, new_fd, SERVER, STATE_SSL_CONNECTING,
new_streamp);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2009, 2010, 2012, 2013 Nicira, Inc.
* Copyright (c) 2008, 2009, 2010, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,10 +21,12 @@
#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>
#include <unistd.h>
#include "dynamic-string.h"
#include "packets.h"
#include "socket-util.h"
#include "util.h"
@@ -40,13 +42,13 @@ static int
new_tcp_stream(const char *name, int fd, int connect_status,
struct stream **streamp)
{
struct sockaddr_in local;
struct sockaddr_storage local;
socklen_t local_len = sizeof local;
int on = 1;
int retval;
/* Get the local IP and port information */
retval = getsockname(fd, (struct sockaddr *)&local, &local_len);
retval = getsockname(fd, (struct sockaddr *) &local, &local_len);
if (retval) {
memset(&local, 0, sizeof local);
}
@@ -90,47 +92,47 @@ const struct stream_class tcp_stream_class = {
/* Passive TCP. */
static int ptcp_accept(int fd, const struct sockaddr *sa, size_t sa_len,
struct stream **streamp);
static int ptcp_accept(int fd, const struct sockaddr_storage *,
size_t, struct stream **streamp);
static int
ptcp_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
uint8_t dscp)
{
struct sockaddr_in sin;
char bound_name[128];
char bound_name[SS_NTOP_BUFSIZE + 16];
char addrbuf[SS_NTOP_BUFSIZE];
struct sockaddr_storage ss;
uint16_t port;
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));
port = ss_get_port(&ss);
snprintf(bound_name, sizeof bound_name, "ptcp:%"PRIu16":%s",
port, ss_format_address(&ss, addrbuf, sizeof addrbuf));
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, htons(port));
}
return error;
}
static int
ptcp_accept(int fd, const struct sockaddr *sa, size_t sa_len,
struct stream **streamp)
ptcp_accept(int fd, const struct sockaddr_storage *ss,
size_t ss_len OVS_UNUSED, struct stream **streamp)
{
const struct sockaddr_in *sin = ALIGNED_CAST(const struct sockaddr_in *,
sa);
char name[128];
char name[SS_NTOP_BUFSIZE + 16];
char addrbuf[SS_NTOP_BUFSIZE];
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");
}
snprintf(name, sizeof name, "tcp:%s:%"PRIu16,
ss_format_address(ss, addrbuf, sizeof addrbuf),
ss_get_port(ss));
return new_tcp_stream(name, fd, 0, streamp);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -75,8 +75,8 @@ const struct stream_class unix_stream_class = {
/* Passive UNIX socket. */
static int punix_accept(int fd, const struct sockaddr *sa, size_t sa_len,
struct stream **streamp);
static int punix_accept(int fd, const struct sockaddr_storage *ss,
size_t ss_len, struct stream **streamp);
static int
punix_open(const char *name OVS_UNUSED, char *suffix,
@@ -105,11 +105,11 @@ punix_open(const char *name OVS_UNUSED, char *suffix,
}
static int
punix_accept(int fd, const struct sockaddr *sa, size_t sa_len,
punix_accept(int fd, const struct sockaddr_storage *ss, size_t ss_len,
struct stream **streamp)
{
const struct sockaddr_un *sun = (const struct sockaddr_un *) sa;
int name_len = get_unix_name_len(sa_len);
const struct sockaddr_un *sun = (const struct sockaddr_un *) ss;
int name_len = get_unix_name_len(ss_len);
char name[128];
if (name_len > 0) {

View File

@@ -720,18 +720,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

View File

@@ -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. */

View File

@@ -1,9 +1,10 @@
.IP "\fBssl:\fIip\fR[\fB:\fIport\fR]"
.IQ "\fBtcp:\fIip\fR[\fB:\fIport\fR]"
The specified \fIport\fR on the host at the given \fIip\fR, which must
be expressed as an IP address (not a DNS name). For \fBssl\fR, the
\fB\-\-private\-key\fR, \fB\-\-certificate\fR, and \fB\-\-ca\-cert\fR
options are mandatory.
be expressed as an IP address (not a DNS name) in IPv4 or IPv6 address
format. Wrap IPv6 addresses in square brackets,
e.g. \fBtcp:[::1]:6633\fR. For \fBssl\fR, the \fB\-\-private\-key\fR,
\fB\-\-certificate\fR, and \fB\-\-ca\-cert\fR options are mandatory.
.IP
If \fIport\fR is not specified, it currently defaults to 6633. In the
future, the default will change to 6653, which is the IANA-defined

View File

@@ -1,14 +1,14 @@
.IP "\fBpssl:\fR[\fIport\fR][\fB:\fIip\fR]"
.IQ "\fBptcp:\fR[\fIport\fR][\fB:\fIip\fR]"
Listens for OpenFlow connections on \fIport\fR. By
default, connections are not bound to a particular local IP address, but
\fIip\fR may be specified to listen only for connections to the given
\fIip\fR. For \fBpssl\fR, the \fB\-\-private\-key\fR,
\fB\-\-certificate\fR, and \fB\-\-ca\-cert\fR options are mandatory.
Listens for OpenFlow connections on \fIport\fR. The default
\fIport\fR is 6633, but a future version of Open vSwitch will change
the default to the IANA-defined port 6653. By default, connections
are allowed from any IPv4 address. Specify \fIip\fR as an IPv4
address or a bracketed IPv6 address (e.g. \fBptcp:6633:[::1]\fR). DNS
names may not be used. For \fBpssl\fR, the
\fB\-\-private\-key\fR,\fB\-\-certificate\fR, and \fB\-\-ca\-cert\fR
options are mandatory.
.IP
If \fIport\fR is not specified, it currently defaults to 6633. In the
future, the default will change to 6653, which is the IANA-defined
value.
.
.IP "\fBpunix:\fIfile\fR"
Listens for OpenFlow connections on the Unix domain server socket

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -734,17 +734,13 @@ 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];
const char *target = rconn_get_target(ofconn->rconn);
struct sockaddr_storage ss;
if (ofconn->band == OFPROTO_OUT_OF_BAND) {
continue;
}
if (stream_parse_target_with_default_port(target,
OFP_OLD_PORT,
sin)) {
n_addrs++;
if (ofconn->band == OFPROTO_IN_BAND
&& stream_parse_target_with_default_port(target, OFP_OLD_PORT, &ss)
&& ss.ss_family == AF_INET) {
addrs[n_addrs++] = *(struct sockaddr_in *) &ss;
}
}
for (i = 0; i < mgr->n_extra_remotes; i++) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
* Copyright (c) 2009 InMon Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -253,13 +253,16 @@ sflow_choose_agent_address(const char *agent_device,
}
SSET_FOR_EACH (target, targets) {
struct sockaddr_in sin;
struct sockaddr_storage ss;
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)
&& ss.ss_family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
if (route_table_get_name(sin->sin_addr.s_addr, name)
&& !netdev_get_in4_by_name(name, &in4)) {
goto success;
}
}
}

View File

@@ -1,11 +1,15 @@
.IP "\fBssl:\fIip\fB:\fIport\fR"
The specified SSL \fIport\fR on the host at the given \fIip\fR, which
must be expressed as an IP address (not a DNS name). The
\fB\-\-private\-key\fR, \fB\-\-certificate\fR, and \fB\-\-ca\-cert\fR
must be expressed as an IP address (not a DNS name) in IPv4 or IPv6 address
format. If \fIip\fR is an IPv6 address, then wrap \fIip\fR with square
brackets, e.g.: \fBssl:[::1]:6632\fR.
The \fB\-\-private\-key\fR, \fB\-\-certificate\fR, and \fB\-\-ca\-cert\fR
options are mandatory when this form is used.
.
.IP "\fBtcp:\fIip\fB:\fIport\fR"
Connect to the given TCP \fIport\fR on \fIip\fR.
Connect to the given TCP \fIport\fR on \fIip\fR, where \fIip\fR can be IPv4
or IPv6 address. If \fIip\fR is an IPv6 address, then wrap \fIip\fR with
square brackets, e.g.: \fBtcp:[::1]:6632\fR.
.
.IP "\fBunix:\fIfile\fR"
Connect to the Unix domain server socket named \fIfile\fR.

View File

@@ -1,15 +1,22 @@
.IP "\fBpssl:\fIport\fR[\fB:\fIip\fR]"
Listen on the given SSL \fIport\fR for a connection. By default,
connections are not bound to a particular local IP address, but
connections are not bound to a particular local IP address and
it listens only on IPv4 (but not IPv6) addresses, but
specifying \fIip\fR limits connections to those from the given
\fIip\fR. The \fB\-\-private\-key\fR, \fB\-\-certificate\fR, and
\fB\-\-ca\-cert\fR options are mandatory when this form is used.
\fIip\fR, either IPv4 or IPv6 address. If \fIip\fR is
an IPv6 address, then wrap \fIip\fR with square brackets, e.g.:
\fBpssl:6632:[::1]\fR. The \fB\-\-private\-key\fR,
\fB\-\-certificate\fR, and \fB\-\-ca\-cert\fR options are mandatory
when this form is used.
.
.IP "\fBptcp:\fIport\fR[\fB:\fIip\fR]"
Listen on the given TCP \fIport\fR for a connection. By default,
connections are not bound to a particular local IP address, but
connections are not bound to a particular local IP address and
it listens only on IPv4 (but not IPv6) addresses, but
\fIip\fR may be specified to listen only for connections to the given
\fIip\fR.
\fIip\fR, either IPv4 or IPv6 address. If \fIip\fR is
an IPv6 address, then wrap \fIip\fR with square brackets, e.g.:
\fBptcp:6632:[::1]\fR.
.
.IP "\fBpunix:\fIfile\fR"
Listen on the Unix domain server socket named \fIfile\fR for a

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2010, 2012 Nicira, Inc.
# Copyright (c) 2010, 2012, 2014 Nicira, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -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 len(address) >= 2:
host_name = ":".join(address[0:-1]).lstrip('[').rstrip(']')
port = int(address[-1])
else:
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)
if len(address) >= 2:
port = int(address[1])
elif default_port:
port = default_port
else:
raise ValueError("%s: port number must be specified" % 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

View File

@@ -1829,55 +1829,58 @@ AT_CHECK_UNQUOTED([ovs-appctl fdb/show br0 | sed 's/[[0-9]]\{1,\}$/?/' | sort],
OVS_VSWITCHD_STOP
AT_CLEANUP
dnl Test that sFlow samples packets correctly.
AT_SETUP([ofproto-dpif - sFlow packet sampling])
OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
# CHECK_SFLOW_SAMPLING_PACKET(LOOPBACK_ADDR, ADDR_WITHOUT_BRACKETS)
#
# Test that sFlow samples packets correctly using IPv4/IPv6 sFlow collector
#
# IP_VERSION_TYPE is used in AT_SETUP
m4_define([CHECK_SFLOW_SAMPLING_PACKET],
[AT_SETUP([ofproto-dpif - sFlow packet sampling - $2 collector])
OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
ON_EXIT([kill `cat test-sflow.pid`])
AT_CHECK([test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([sflow.log])
SFLOW_PORT=`parse_listening_port < test-sflow.log`
ON_EXIT([kill `cat test-sflow.pid`])
AT_CHECK([test-sflow --log-file --detach --no-chdir --pidfile 0:$1 > sflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([sflow.log])
SFLOW_PORT=`parse_listening_port < test-sflow.log`
ovs-appctl time/stop
ovs-appctl time/stop
ADD_OF_PORTS([br0], 1, 2)
ovs-vsctl \
set Interface br0 options:ifindex=1002 -- \
set Interface p1 options:ifindex=1004 -- \
set Interface p2 options:ifindex=1003 -- \
set Bridge br0 sflow=@sf -- \
--id=@sf create sflow targets=\"$1:$SFLOW_PORT\" \
header=128 sampling=1 polling=1 agent=lo
ADD_OF_PORTS([br0], 1, 2)
ovs-vsctl \
set Interface br0 options:ifindex=1002 -- \
set Interface p1 options:ifindex=1004 -- \
set Interface p2 options:ifindex=1003 -- \
set Bridge br0 sflow=@sf -- \
--id=@sf create sflow targets=\"127.0.0.1:$SFLOW_PORT\" \
header=128 sampling=1 polling=1
dnl open with ARP packets to seed the bridge-learning. The output
dnl ifIndex numbers should be reported predictably after that.
dnl Since we set sampling=1 we should see all of these packets
dnl reported. Sorting the output by data-source and seqNo makes
dnl it deterministic. Ensuring that we send at least two packets
dnl into each port means we get to check the seq nos are
dnl incrementing correctly.
dnl because packets from different ports can be handled by separate
dnl threads, put some sleeps
dnl open with ARP packets to seed the bridge-learning. The output
dnl ifIndex numbers should be reported predictably after that.
dnl Since we set sampling=1 we should see all of these packets
dnl reported. Sorting the output by data-source and seqNo makes
dnl it deterministic. Ensuring that we send at least two packets
dnl into each port means we get to check the seq nos are
dnl incrementing correctly.
ovs-appctl netdev-dummy/receive p1 'in_port(2),eth(src=50:54:00:00:00:05,dst=FF:FF:FF:FF:FF:FF),eth_type(0x0806),arp(sip=192.168.0.2,tip=192.168.0.1,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)'
sleep 1
ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=FF:FF:FF:FF:FF:FF),eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:07,tha=00:00:00:00:00:00)'
sleep 1
ovs-appctl netdev-dummy/receive p1 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
sleep 1
ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'
ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x86dd),ipv6(src=fe80::1,dst=fe80::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no)'
dnl because packets from different ports can be handled by separate
dnl threads, put some sleeps
dnl sleep long enough to get more than one counter sample
dnl from each datasource so we can check sequence numbers
for i in `seq 1 30`; do
ovs-appctl time/warp 100
done
OVS_VSWITCHD_STOP
ovs-appctl -t test-sflow exit
ovs-appctl netdev-dummy/receive p1 'in_port(2),eth(src=50:54:00:00:00:05,dst=FF:FF:FF:FF:FF:FF),eth_type(0x0806),arp(sip=192.168.0.2,tip=192.168.0.1,op=1,sha=50:54:00:00:00:05,tha=00:00:00:00:00:00)'
sleep 1
ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=FF:FF:FF:FF:FF:FF),eth_type(0x0806),arp(sip=192.168.0.1,tip=192.168.0.2,op=1,sha=50:54:00:00:00:07,tha=00:00:00:00:00:00)'
sleep 1
ovs-appctl netdev-dummy/receive p1 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
sleep 1
ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'
ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x86dd),ipv6(src=fe80::1,dst=fe80::2,label=0,proto=10,tclass=0x70,hlimit=128,frag=no)'
dnl sleep long enough to get more than one counter sample
dnl from each datasource so we can check sequence numbers
for i in `seq 1 30`; do
ovs-appctl time/warp 100
done
OVS_VSWITCHD_STOP
ovs-appctl -t test-sflow exit
AT_CHECK([[sort sflow.log | $EGREP 'HEADER|ERROR' | sed 's/ /\
AT_CHECK_UNQUOTED([[sort sflow.log | $EGREP 'HEADER|ERROR' | sed 's/ /\
/g']], [0], [dnl
HEADER
dgramSeqNo=1
@@ -1981,7 +1984,7 @@ HEADER
hdr=50-54-00-00-00-05-50-54-00-00-00-07-86-DD-67-00-00-00-00-00-0A-80-FE-80-00-00-00-00-00-00-00-00-00-00-00-00-00-01-FE-80-00-00-00-00-00-00-00-00-00-00-00-00-00-02-00-00-00-00-00-00
])
AT_CHECK([[sort sflow.log | $EGREP 'IFCOUNTERS|ERROR' | head -6 | sed 's/ /\
AT_CHECK_UNQUOTED([[sort sflow.log | $EGREP 'IFCOUNTERS|ERROR' | head -6 | sed 's/ /\
/g']], [0], [dnl
IFCOUNTERS
dgramSeqNo=2
@@ -2122,128 +2125,144 @@ IFCOUNTERS
out_errors=0
promiscuous=0
])
AT_CLEANUP
AT_CLEANUP])
CHECK_SFLOW_SAMPLING_PACKET([127.0.0.1], [IPv4])
CHECK_SFLOW_SAMPLING_PACKET([[[::1]]], [IPv6])
# CHECK_NETFLOW_EXPIRATION(LOOPBACK_ADDR, IP_VERSION_TYPE)
#
# Test that basic NetFlow reports flow statistics correctly:
# The initial packet of a flow are correctly accounted.
# Later packets within a flow are correctly accounted.
# Flow actions changing (in this case, due to MAC learning)
# cause a record to be sent.
#
# IP_VERSION_TYPE is used in AT_SETUP
m4_define([CHECK_NETFLOW_EXPIRATION],
[AT_SETUP([ofproto-dpif - NetFlow flow expiration - $2 collector])
OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
ADD_OF_PORTS([br0], 1, 2)
dnl Test that basic NetFlow reports flow statistics correctly:
dnl - The initial packet of a flow are correctly accounted.
dnl - Later packets within a flow are correctly accounted.
dnl - Flow actions changing (in this case, due to MAC learning)
dnl cause a record to be sent.
AT_SETUP([ofproto-dpif - NetFlow flow expiration])
ovs-appctl time/stop
ON_EXIT([kill `cat test-netflow.pid`])
AT_CHECK([test-netflow --log-file --detach --no-chdir --pidfile 0:$1 > netflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([netflow.log])
NETFLOW_PORT=`parse_listening_port < test-netflow.log`
OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
ADD_OF_PORTS([br0], 1, 2)
ovs-vsctl \
set Bridge br0 netflow=@nf -- \
--id=@nf create NetFlow targets=\"$1:$NETFLOW_PORT\" \
engine_id=1 engine_type=2 active_timeout=30 add-id-to-interface=false
ovs-appctl time/stop
ON_EXIT([kill `cat test-netflow.pid`])
AT_CHECK([test-netflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > netflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([netflow.log])
NETFLOW_PORT=`parse_listening_port < test-netflow.log`
for delay in 1000 30000; do
ovs-appctl netdev-dummy/receive p1 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'
ovs-vsctl \
set Bridge br0 netflow=@nf -- \
--id=@nf create NetFlow targets=\"127.0.0.1:$NETFLOW_PORT\" \
engine_id=1 engine_type=2 active_timeout=30 add-id-to-interface=false
ovs-appctl time/warp $delay
done
for delay in 1000 30000; do
ovs-appctl netdev-dummy/receive p1 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'
ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'
ovs-appctl time/warp 6000
sleep 1
OVS_VSWITCHD_STOP
ovs-appctl -t test-netflow exit
ovs-appctl time/warp $delay
done
AT_CHECK([test `grep "192.168.0.1 > 192.168.0.2, if 1 > 65535, 1 pkts, 60 bytes, ICMP 8:0" netflow.log | wc -l` -eq 1])
ovs-appctl time/warp 6000
sleep 1
OVS_VSWITCHD_STOP
ovs-appctl -t test-netflow exit
AT_CHECK([test `grep "192.168.0.1 > 192.168.0.2, if 1 > 2, 1 pkts, 60 bytes, ICMP 8:0" netflow.log | wc -l` -eq 1])
AT_CHECK([test `grep "192.168.0.1 > 192.168.0.2, if 1 > 65535, 1 pkts, 60 bytes, ICMP 8:0" netflow.log | wc -l` -eq 1])
combined=`grep "192.168.0.2 > 192.168.0.1, if 2 > 1, 2 pkts, 120 bytes, ICMP 0:0" netflow.log | wc -l`
separate=`grep "192.168.0.2 > 192.168.0.1, if 2 > 1, 1 pkts, 60 bytes, ICMP 0:0" netflow.log | wc -l`
AT_CHECK([test $separate = 2 || test $combined = 1], [0])
AT_CHECK([test `grep "192.168.0.1 > 192.168.0.2, if 1 > 2, 1 pkts, 60 bytes, ICMP 8:0" netflow.log | wc -l` -eq 1])
AT_CLEANUP])
combined=`grep "192.168.0.2 > 192.168.0.1, if 2 > 1, 2 pkts, 120 bytes, ICMP 0:0" netflow.log | wc -l`
separate=`grep "192.168.0.2 > 192.168.0.1, if 2 > 1, 1 pkts, 60 bytes, ICMP 0:0" netflow.log | wc -l`
AT_CHECK([test $separate = 2 || test $combined = 1], [0])
CHECK_NETFLOW_EXPIRATION([127.0.0.1], [IPv4])
CHECK_NETFLOW_EXPIRATION([[[::1]]], [IPv6])
AT_CLEANUP
# CHECK_NETFLOW_ACTIVE_EXPIRATION(LOOPBACK_ADDR, IP_VERSION_TYPE)
#
# Test that basic NetFlow reports active expirations correctly.
#
# IP_VERSION_TYPE is used in AT_SETUP
m4_define([CHECK_NETFLOW_ACTIVE_EXPIRATION],
[AT_SETUP([ofproto-dpif - NetFlow active expiration - $2 collector])
dnl Test that basic NetFlow reports active expirations correctly.
AT_SETUP([ofproto-dpif - NetFlow active expiration])
OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
ADD_OF_PORTS([br0], 1, 2)
OVS_VSWITCHD_START([set Bridge br0 fail-mode=standalone])
ADD_OF_PORTS([br0], 1, 2)
ON_EXIT([kill `cat test-netflow.pid`])
AT_CHECK([test-netflow --log-file --detach --no-chdir --pidfile 0:$1 > netflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([netflow.log])
NETFLOW_PORT=`parse_listening_port < test-netflow.log`
ON_EXIT([kill `cat test-netflow.pid`])
AT_CHECK([test-netflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > netflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([netflow.log])
NETFLOW_PORT=`parse_listening_port < test-netflow.log`
ovs-vsctl \
set Bridge br0 netflow=@nf -- \
--id=@nf create NetFlow targets=\"$1:$NETFLOW_PORT\" \
engine_id=1 engine_type=2 active_timeout=10 add-id-to-interface=false
ovs-vsctl \
set Bridge br0 netflow=@nf -- \
--id=@nf create NetFlow targets=\"127.0.0.1:$NETFLOW_PORT\" \
engine_id=1 engine_type=2 active_timeout=10 add-id-to-interface=false
AT_CHECK([ovs-appctl time/stop])
n=1
while test $n -le 60; do
n=`expr $n + 1`
AT_CHECK([ovs-appctl time/stop])
n=1
while test $n -le 60; do
n=`expr $n + 1`
ovs-appctl netdev-dummy/receive p1 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=1234,dst=80)'
ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=6,tos=0,ttl=64,frag=no),tcp(src=80,dst=1234)'
ovs-appctl netdev-dummy/receive p1 'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=6,tos=0,ttl=64,frag=no),tcp(src=1234,dst=80)'
ovs-appctl netdev-dummy/receive p2 'in_port(1),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=6,tos=0,ttl=64,frag=no),tcp(src=80,dst=1234)'
ovs-appctl time/warp 1000
done
ovs-appctl time/warp 1000
done
ovs-appctl time/warp 10000
ovs-appctl time/warp 10000
sleep 1
OVS_VSWITCHD_STOP
ovs-appctl -t test-netflow exit
sleep 1
OVS_VSWITCHD_STOP
ovs-appctl -t test-netflow exit
# Count the number of reported packets:
# - From source to destination before MAC learning kicks in (just one).
# - From source to destination after that.
# - From destination to source.
n_learn=0
n_in=0
n_out=0
n_other=0
n_recs=0
none=0
while read line; do
pkts=`echo "$line" | sed 's/.*, \([[0-9]]*\) pkts,.*/\1/'`
case $pkts in
[[0-9]]*) ;;
*) continue ;;
esac
# Count the number of reported packets:
# - From source to destination before MAC learning kicks in (just one).
# - From source to destination after that.
# - From destination to source.
n_learn=0
n_in=0
n_out=0
n_other=0
n_recs=0
none=0
while read line; do
pkts=`echo "$line" | sed 's/.*, \([[0-9]]*\) pkts,.*/\1/'`
case $pkts in
[[0-9]]*) ;;
*) continue ;;
esac
case $line in
"seq "*": 192.168.0.1 > 192.168.0.2, if 1 > 65535, "*" pkts, "*" bytes, TCP 1234 > 80, time "*)
counter=n_learn
;;
"seq "*": 192.168.0.1 > 192.168.0.2, if 1 > 2, "*" pkts, "*" bytes, TCP 1234 > 80, time "*)
counter=n_in
;;
"seq "*": 192.168.0.2 > 192.168.0.1, if 2 > 1, "*" pkts, "*" bytes, TCP 80 > 1234, time "*)
counter=n_out
;;
*)
counter=n_other
;;
esac
eval $counter=\`expr \$$counter + \$pkts\`
n_recs=`expr $n_recs + 1`
done < netflow.log
case $line in
"seq "*": 192.168.0.1 > 192.168.0.2, if 1 > 65535, "*" pkts, "*" bytes, TCP 1234 > 80, time "*)
counter=n_learn
;;
"seq "*": 192.168.0.1 > 192.168.0.2, if 1 > 2, "*" pkts, "*" bytes, TCP 1234 > 80, time "*)
counter=n_in
;;
"seq "*": 192.168.0.2 > 192.168.0.1, if 2 > 1, "*" pkts, "*" bytes, TCP 80 > 1234, time "*)
counter=n_out
;;
*)
counter=n_other
;;
esac
eval $counter=\`expr \$$counter + \$pkts\`
n_recs=`expr $n_recs + 1`
done < netflow.log
# There should be exactly 1 MAC learning packet,
# exactly 59 other packets in that direction,
# and exactly 60 packets in the other direction.
AT_CHECK([echo $n_learn $n_in $n_out $n_other], [0], [1 59 60 0
# There should be exactly 1 MAC learning packet,
# exactly 59 other packets in that direction,
# and exactly 60 packets in the other direction.
AT_CHECK([echo $n_learn $n_in $n_out $n_other], [0], [1 59 60 0
])
AT_CLEANUP
AT_CLEANUP])
CHECK_NETFLOW_ACTIVE_EXPIRATION([127.0.0.1], [IPv4])
CHECK_NETFLOW_ACTIVE_EXPIRATION([[[::1]]], [IPv6])
AT_SETUP([idle_age and hard_age increase over time])
OVS_VSWITCHD_START
@@ -2700,30 +2719,37 @@ skb_priority(0),in_port(1),eth(src=50:54:00:00:00:0b/ff:ff:ff:ff:ff:ff,dst=50:54
OVS_VSWITCHD_STOP
AT_CLEANUP
AT_SETUP([ofproto-dpif megaflow - netflow])
OVS_VSWITCHD_START
ADD_OF_PORTS([br0], [1], [2])
# CHECK_MEGAFLOW_NETFLOW(LOOPBACK_ADDR, IP_VERSION_TYPE)
#
# IP_VERSION_TYPE is used in AT_SETUP
m4_define([CHECK_MEGAFLOW_NETFLOW],
[AT_SETUP([ofproto-dpif megaflow - netflow - $2 collector])
OVS_VSWITCHD_START
ADD_OF_PORTS([br0], [1], [2])
dnl NetFlow configuration disables wildcarding relevant fields
ON_EXIT([kill `cat test-netflow.pid`])
AT_CHECK([test-netflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > netflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([netflow.log])
NETFLOW_PORT=`parse_listening_port < test-netflow.log`
ovs-vsctl \
set Bridge br0 netflow=@nf -- \
--id=@nf create NetFlow targets=\"127.0.0.1:$NETFLOW_PORT\" \
engine_id=1 engine_type=2 active_timeout=30 add-id-to-interface=false
dnl NetFlow configuration disables wildcarding relevant fields
ON_EXIT([kill `cat test-netflow.pid`])
AT_CHECK([test-netflow --log-file --detach --no-chdir --pidfile 0:$1 > netflow.log], [0], [], [ignore])
AT_CAPTURE_FILE([netflow.log])
NETFLOW_PORT=`parse_listening_port < test-netflow.log`
ovs-vsctl \
set Bridge br0 netflow=@nf -- \
--id=@nf create NetFlow targets=\"$1:$NETFLOW_PORT\" \
engine_id=1 engine_type=2 active_timeout=30 add-id-to-interface=false
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([ovs-appctl dpif/dump-flows br0 | STRIP_XOUT], [0], [dnl
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
sleep 1
AT_CHECK([ovs-appctl dpif/dump-flows br0 | STRIP_XOUT], [0], [dnl
skb_priority(0),in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2/255.255.255.255,dst=10.0.0.1/255.255.255.255,proto=1/0xff,tos=0/0xfc,ttl=64/0,frag=no/0xff),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions: <del>
skb_priority(0),in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4/255.255.255.255,dst=10.0.0.3/255.255.255.255,proto=1/0xff,tos=0/0xfc,ttl=64/0,frag=no/0xff),icmp(type=8,code=0), packets:0, bytes:0, used:never, actions: <del>
])
OVS_VSWITCHD_STOP
AT_CLEANUP
OVS_VSWITCHD_STOP
AT_CLEANUP])
CHECK_MEGAFLOW_NETFLOW([127.0.0.1], [IPv4])
CHECK_MEGAFLOW_NETFLOW([[[::1]]], [IPv6])
AT_SETUP([ofproto-dpif megaflow - normal, active-backup bonding])
OVS_VSWITCHD_START(

View File

@@ -21,7 +21,7 @@ s/ hard_age=[0-9]*,//
# log, given that the server was told to listen on a kernel-chosen
# port, file provided on stdin, and prints the port number on stdout.
# You should specify the listening remote as ptcp:0:127.0.0.1 or
# pssl:0:127.0.0.1.
# pssl:0:127.0.0.1, or the equivalent with [::1] instead of 127.0.0.1.
#
# Here's an example of how to use this with ovsdb-server:
#
@@ -29,7 +29,7 @@ s/ hard_age=[0-9]*,//
# ovsdb-server --log-file --remote=ptcp:0:127.0.0.1 ...
# TCP_PORT=`parse_listening_port < ovsdb-server.log`
parse_listening_port () {
sed -n 's/.*0:127\.0\.0\.1: listening on port \([0-9]*\)$/\1/p'
sed -n 's/.*0:.*: listening on port \([0-9]*\)$/\1/p'
}]
m4_divert_pop([PREPARE_TESTS])

View File

@@ -177,7 +177,7 @@ OVSDB_CHECK_EXECUTION([duplicate uuid-name not allowed],
[[[{"uuid":["uuid","<0>"]},{"details":"This \"uuid-name\" appeared on an earlier \"insert\" operation.","error":"duplicate uuid-name","syntax":"\"x\""}]
]])
m4_define([EXECUTION_EXAMPLES], [
m4_define([ONE_EXECUTION_EXAMPLE], [dnl
dnl At one point the "commit" code ignored new rows with all-default values,
dnl so this checks for that problem.
OVSDB_CHECK_EXECUTION([insert default row, query table],
@@ -193,7 +193,10 @@ OVSDB_CHECK_EXECUTION([insert default row, query table],
[[[{"uuid":["uuid","<0>"]}]
[{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<1>"],"name":"","number":0}]}]
]])
])
m4_define([EXECUTION_EXAMPLES], [
ONE_EXECUTION_EXAMPLE
OVSDB_CHECK_EXECUTION([insert row, query table],
[ordinal_schema],
[[[["ordinals",

View File

@@ -72,10 +72,33 @@ m4_define([OVSDB_CHECK_IDL_TCP_PY],
OVSDB_SERVER_SHUTDOWN
AT_CLEANUP])
# same as OVSDB_CHECK_IDL but uses the Python IDL implementation with tcp6
m4_define([OVSDB_CHECK_IDL_TCP6_PY],
[AT_SETUP([$1 - Python tcp6])
AT_SKIP_IF([test $HAVE_PYTHON = no])
AT_KEYWORDS([ovsdb server idl positive Python with tcp6 socket $5])
OVS_RUNDIR=`pwd`; export OVS_RUNDIR
OVS_LOGDIR=`pwd`; export OVS_LOGDIR
AT_CHECK([ovsdb-tool create db $abs_srcdir/idltest.ovsschema],
[0], [stdout], [ignore])
AT_CHECK([ovsdb-server --log-file '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=ptcp:0:[[::1]] --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
TCP_PORT=`parse_listening_port < ovsdb-server.log`
echo "TCP_PORT=$TCP_PORT"
m4_if([$2], [], [],
[AT_CHECK([ovsdb-client transact "tcp:[[::1]]:$TCP_PORT" $2], [0], [ignore], [ignore], [kill `cat pid`])])
AT_CHECK([strace $PYTHON $srcdir/test-ovsdb.py -t10 idl $srcdir/idltest.ovsschema tcp:[[::1]]:$TCP_PORT $3],
[0], [stdout], [ignore], [kill `cat pid`])
AT_CHECK([sort stdout | ${PERL} $srcdir/uuidfilt.pl]m4_if([$6],,, [[| $6]]),
[0], [$4], [], [kill `cat pid`])
OVSDB_SERVER_SHUTDOWN
AT_CLEANUP])
m4_define([OVSDB_CHECK_IDL],
[OVSDB_CHECK_IDL_C($@)
OVSDB_CHECK_IDL_PY($@)
OVSDB_CHECK_IDL_TCP_PY($@)])
OVSDB_CHECK_IDL_TCP_PY($@)
OVSDB_CHECK_IDL_TCP6_PY($@)])
OVSDB_CHECK_IDL([simple idl, initially empty, no ops],
[],

View File

@@ -748,7 +748,7 @@ for i in `seq 1 100`; do
done
AT_CLEANUP
AT_BANNER([OVSDB -- ovsdb-server transactions (SSL sockets)])
AT_BANNER([OVSDB -- ovsdb-server transactions (SSL IPv4 sockets)])
# OVSDB_CHECK_EXECUTION(TITLE, SCHEMA, TRANSACTIONS, OUTPUT, [KEYWORDS])
#
@@ -787,7 +787,46 @@ cat stdout >> output
EXECUTION_EXAMPLES
AT_BANNER([OVSDB -- ovsdb-server transactions (TCP sockets)])
AT_BANNER([OVSDB -- ovsdb-server transactions (SSL IPv6 sockets)])
# OVSDB_CHECK_EXECUTION(TITLE, SCHEMA, TRANSACTIONS, OUTPUT, [KEYWORDS])
#
# Creates a database with the given SCHEMA, starts an ovsdb-server on
# that database, and runs each of the TRANSACTIONS (which should be a
# quoted list of quoted strings) against it with ovsdb-client one at a
# time.
#
# Checks that the overall output is OUTPUT, but UUIDs in the output
# are replaced by markers of the form <N> where N is a number. The
# first unique UUID is replaced by <0>, the next by <1>, and so on.
# If a given UUID appears more than once it is always replaced by the
# same marker.
#
# TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS.
m4_define([OVSDB_CHECK_EXECUTION],
[AT_SETUP([$1])
AT_KEYWORDS([ovsdb server positive ssl6 $5])
AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
OVS_RUNDIR=`pwd`; export OVS_RUNDIR
OVS_LOGDIR=`pwd`; export OVS_LOGDIR
$2 > schema
PKIDIR=$abs_top_builddir/tests
AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
AT_CHECK([ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid --private-key=$PKIDIR/testpki-privkey2.pem --certificate=$PKIDIR/testpki-cert2.pem --ca-cert=$PKIDIR/testpki-cacert.pem --remote=pssl:0:[[::1]] --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
SSL_PORT=`parse_listening_port < ovsdb-server.log`
m4_foreach([txn], [$3],
[AT_CHECK([ovsdb-client --private-key=$PKIDIR/testpki-privkey.pem --certificate=$PKIDIR/testpki-cert.pem --ca-cert=$PKIDIR/testpki-cacert.pem transact ssl:[[::1]]:$SSL_PORT 'txn'], [0], [stdout], [ignore],
[test ! -e pid || kill `cat pid`])
cat stdout >> output
])
AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0], [$4], [ignore],
[test ! -e pid || kill `cat pid`])
OVSDB_SERVER_SHUTDOWN
AT_CLEANUP])
ONE_EXECUTION_EXAMPLE
AT_BANNER([OVSDB -- ovsdb-server transactions (TCP IPv4 sockets)])
AT_SETUP([ovsdb-client get-schema-version - tcp socket])
AT_KEYWORDS([ovsdb server positive tcp])
@@ -836,6 +875,42 @@ cat stdout >> output
AT_CLEANUP])
EXECUTION_EXAMPLES
# OVSDB_CHECK_EXECUTION(TITLE, SCHEMA, TRANSACTIONS, OUTPUT, [KEYWORDS])
#
# Creates a database with the given SCHEMA, starts an ovsdb-server on
# that database, and runs each of the TRANSACTIONS (which should be a
# quoted list of quoted strings) against it with ovsdb-client one at a
# time.
#
# Checks that the overall output is OUTPUT, but UUIDs in the output
# are replaced by markers of the form <N> where N is a number. The
# first unique UUID is replaced by <0>, the next by <1>, and so on.
# If a given UUID appears more than once it is always replaced by the
# same marker.
#
# TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS.
m4_define([OVSDB_CHECK_EXECUTION],
[AT_SETUP([$1])
AT_KEYWORDS([ovsdb server positive tcp6 $5])
OVS_RUNDIR=`pwd`; export OVS_RUNDIR
OVS_LOGDIR=`pwd`; export OVS_LOGDIR
$2 > schema
PKIDIR=$abs_top_builddir/tests
AT_CHECK([ovsdb-tool create db schema], [0], [stdout], [ignore])
AT_CHECK([ovsdb-server --log-file --detach --no-chdir --pidfile="`pwd`"/pid --remote=ptcp:0:[[::1]] --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
TCP_PORT=`parse_listening_port < ovsdb-server.log`
m4_foreach([txn], [$3],
[AT_CHECK([ovsdb-client transact tcp:[[::1]]:$TCP_PORT 'txn'], [0], [stdout], [ignore],
[test ! -e pid || kill `cat pid`])
cat stdout >> output
])
AT_CHECK([${PERL} $srcdir/uuidfilt.pl output], [0], [$4], [ignore],
[test ! -e pid || kill `cat pid`])
OVSDB_SERVER_SHUTDOWN
AT_CLEANUP])
ONE_EXECUTION_EXAMPLE
AT_BANNER([OVSDB -- transactions on transient ovsdb-server])

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, 2013 Nicira, Inc.
* Copyright (c) 2011, 2012, 2013, 2014 Nicira, Inc.
* Copyright (c) 2013 InMon Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -44,7 +44,6 @@ static unixctl_cb_func test_sflow_exit;
/* Datagram. */
#define SFLOW_VERSION_5 5
#define SFLOW_MIN_LEN 36
#define SFLOW_MAX_AGENTIP_STRLEN 64
/* Sample tag numbers. */
#define SFLOW_FLOW_SAMPLE 1
@@ -82,7 +81,7 @@ struct sflow_xdr {
/* Agent. */
struct sflow_addr agentAddr;
char agentIPStr[SFLOW_MAX_AGENTIP_STRLEN];
char agentIPStr[INET6_ADDRSTRLEN + 2];
uint32_t subAgentId;
uint32_t uptime_mS;
@@ -325,14 +324,12 @@ process_datagram(struct sflow_xdr *x)
/* Store the agent address as a string. */
if (x->agentAddr.type == SFLOW_ADDRTYPE_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]);
char ipstr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, (const void *) &x->agentAddr.a.ip6,
ipstr, INET6_ADDRSTRLEN);
snprintf(x->agentIPStr, sizeof x->agentIPStr, "[%s]", ipstr);
} else {
snprintf(x->agentIPStr, SFLOW_MAX_AGENTIP_STRLEN,
snprintf(x->agentIPStr, sizeof x->agentIPStr,
IP_FMT, IP_ARGS(x->agentAddr.a.ip4));
}

View File

@@ -466,12 +466,12 @@ 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 ss;
if (stream_parse_target_with_default_port(target,
OVSDB_OLD_PORT,
sin)) {
n_managers++;
if (stream_parse_target_with_default_port(target, OVSDB_OLD_PORT,
&ss)
&& ss.ss_family == AF_INET) {
managers[n_managers++] = *(struct sockaddr_in *) &ss;
}
}
}

View File

@@ -3000,12 +3000,18 @@
</dd>
<dt><code>tcp:<var>ip</var></code>[<code>:<var>port</var></code>]</dt>
<dd>
<p>The specified TCP <var>port</var> on the host at the
given <var>ip</var>, which must be expressed as an IP
address (not a DNS name).</p>
<p>If <var>port</var> is not specified, it currently
defaults to 6633. In the future, the default will change to
6653, which is the IANA-defined value.</p>
<p>
The specified TCP <var>port</var> on the host at the given
<var>ip</var>, which must be expressed as an IP address (not a
DNS name), where <var>ip</var> can be IPv4 or IPv6 address. If
<var>ip</var> is an IPv6 address, wrap it in square brackets,
e.g. <code>tcp:[::1]:6632</code>.
</p>
<p>
If <var>port</var> is not specified, it currently defaults to
6633. In the future, the default will change to 6653, which is
the IANA-defined value.
</p>
</dd>
</dl>
<p>
@@ -3015,29 +3021,48 @@
<dl>
<dt><code>pssl:</code>[<var>port</var>][<code>:<var>ip</var></code>]</dt>
<dd>
<p> Listens for SSL connections on the specified TCP
<var>port</var>. If <var>ip</var>, which must be expressed
as an IP address (not a DNS name), is specified, then
connections are restricted to the specified local IP
address. The <ref table="Open_vSwitch" column="ssl"/>
column in the <ref table="Open_vSwitch"/> table must point
to a valid SSL configuration when this form is used.</p>
<p>If <var>port</var> is not specified, it currently
defaults to 6633. In the future, the default will change to
6653, which is the IANA-defined value.</p>
<p>SSL support is an optional feature that is not always built as
part of Open vSwitch.</p>
<p>
Listens for SSL connections on the specified TCP <var>port</var>.
If <var>ip</var>, which must be expressed as an IP address (not a
DNS name), is specified, then connections are restricted to the
specified local IP address (either IPv4 or IPv6). If
<var>ip</var> is an IPv6 address, wrap it in square brackets,
e.g. <code>pssl:6632:[::1]</code>.
</p>
<p>
If <var>port</var> is not specified, it currently defaults to
6633. If <var>ip</var> is not specified then it listens only on
IPv4 (but not IPv6) addresses. The
<ref table="Open_vSwitch" column="ssl"/>
column in the <ref table="Open_vSwitch"/> table must point to a
valid SSL configuration when this form is used.
</p>
<p>
If <var>port</var> is not specified, it currently defaults to
6633. In the future, the default will change to 6653, which is
the IANA-defined value.
</p>
<p>
SSL support is an optional feature that is not always built as
part of Open vSwitch.
</p>
</dd>
<dt><code>ptcp:</code>[<var>port</var>][<code>:<var>ip</var></code>]</dt>
<dd>
<p>Listens for connections on the specified TCP
<var>port</var>. If <var>ip</var>, which must be expressed
as an IP address (not a DNS name), is specified, then
connections are restricted to the specified local IP
address.</p>
<p>If <var>port</var> is not specified, it currently
defaults to 6633. In the future, the default will change to
6653, which is the IANA-defined value.</p>
<p>
Listens for connections on the specified TCP <var>port</var>. If
<var>ip</var>, which must be expressed as an IP address (not a
DNS name), is specified, then connections are restricted to the
specified local IP address (either IPv4 or IPv6). If
<var>ip</var> is an IPv6 address, wrap it in square brackets,
e.g. <code>ptcp:6632:[::1]</code>. If <var>ip</var> is not
specified then it listens only on IPv4 addresses.
</p>
<p>
If <var>port</var> is not specified, it currently defaults to
6633. In the future, the default will change to 6653, which is
the IANA-defined value.
</p>
</dd>
</dl>
<p>When multiple controllers are configured for a single bridge, the
@@ -3331,8 +3356,10 @@
<dd>
<p>
The specified TCP <var>port</var> on the host at the given
<var>ip</var>, which must be expressed as an IP address
(not a DNS name).
<var>ip</var>, which must be expressed as an IP address (not a
DNS name), where <var>ip</var> can be IPv4 or IPv6 address. If
<var>ip</var> is an IPv6 address, wrap it in square brackets,
e.g. <code>tcp:[::1]:6632</code>.
</p>
<p>
If <var>port</var> is not specified, it currently defaults
@@ -3343,13 +3370,16 @@
<dt><code>pssl:</code>[<var>port</var>][<code>:<var>ip</var></code>]</dt>
<dd>
<p>
Listens for SSL connections on the specified TCP
<var>port</var>. Specify 0 for <var>port</var> to have
the kernel automatically choose an available port. If
<var>ip</var>, which must be expressed as an IP address
(not a DNS name), is specified, then connections are
restricted to the specified local IP address. The <ref
table="Open_vSwitch" column="ssl"/> column in the <ref
Listens for SSL connections on the specified TCP <var>port</var>.
Specify 0 for <var>port</var> to have the kernel automatically
choose an available port. If <var>ip</var>, which must be
expressed as an IP address (not a DNS name), is specified, then
connections are restricted to the specified local IP address
(either IPv4 or IPv6 address). If <var>ip</var> is an IPv6
address, wrap in square brackets,
e.g. <code>pssl:6632:[::1]</code>. If <var>ip</var> is not
specified then it listens only on IPv4 (but not IPv6) addresses.
The <ref table="Open_vSwitch" column="ssl"/> column in the <ref
table="Open_vSwitch"/> table must point to a valid SSL
configuration when this form is used.
</p>
@@ -3366,12 +3396,15 @@
<dt><code>ptcp:</code>[<var>port</var>][<code>:<var>ip</var></code>]</dt>
<dd>
<p>
Listens for connections on the specified TCP
<var>port</var>. Specify 0 for <var>port</var> to have
the kernel automatically choose an available port. If
<var>ip</var>, which must be expressed as an IP address
(not a DNS name), is specified, then connections are
restricted to the specified local IP address.
Listens for connections on the specified TCP <var>port</var>.
Specify 0 for <var>port</var> to have the kernel automatically
choose an available port. If <var>ip</var>, which must be
expressed as an IP address (not a DNS name), is specified, then
connections are restricted to the specified local IP address
(either IPv4 or IPv6 address). If <var>ip</var> is an IPv6
address, wrap it in square brackets,
e.g. <code>ptcp:6632:[::1]</code>. If <var>ip</var> is not
specified then it listens only on IPv4 addresses.
</p>
<p>
If <var>port</var> is not specified, it currently defaults