From: Gurucharan Shetty Date: Fri, 4 Apr 2014 21:13:32 +0000 (-0700) Subject: stream: Introduce [p]windows_[p]stream_class. X-Git-Tag: sliver-openvswitch-2.2.90-1~3^2~99 X-Git-Url: http://git.onelab.eu/?p=sliver-openvswitch.git;a=commitdiff_plain;h=e3f512b07c11de6b297050bb969fd0d8a07f9357 stream: Introduce [p]windows_[p]stream_class. On Linux, we heavily use --remote=punix:* to listen for connections through unix domain sockets. We also use, unix:* to connect to a daemon that is listening on unix domain sockets. Many times, we create default unix domain sockets for listening and many utilities connect to these sockets by default. Windows does not have unix domain sockets. So far, we could just use ptcp:* and tcp:* for listening and initiating connections respectively. The drawback here is that one has to provide a specific TCP port. For unit tests, it looks useful to let kernel choose that port. As such, we can let that chosen kernel port be stored in the file specified with punix:* and unix:*. For this purpose, introduce a new [p]windows_[p]stream_class. Since it is just a wrapper around [p]tcp_[p]stream_class, add it to stream-tcp.c. commit cb54a8c (unixctl: Add support for Windows.) used the above concept for only control channel connections (i.e., --unixctl for daemons and its interaction with ovs-appctl). This commit adds the same support for all unix domain sockets. Now that we have a separate class [p]stream_class for hiding kernel assigned TCP port inside a file meant for unix domain sockets in windows, make unixctl use it. Signed-off-by: Gurucharan Shetty Acked-by: Ben Pfaff --- diff --git a/lib/stream-provider.h b/lib/stream-provider.h index 44d75d333..8347ac6f5 100644 --- a/lib/stream-provider.h +++ b/lib/stream-provider.h @@ -191,8 +191,13 @@ struct pstream_class { /* Active and passive stream classes. */ extern const struct stream_class tcp_stream_class; extern const struct pstream_class ptcp_pstream_class; +#ifndef _WIN32 extern const struct stream_class unix_stream_class; extern const struct pstream_class punix_pstream_class; +#else +extern const struct stream_class windows_stream_class; +extern const struct pstream_class pwindows_pstream_class; +#endif #ifdef HAVE_OPENSSL extern const struct stream_class ssl_stream_class; extern const struct pstream_class pssl_pstream_class; diff --git a/lib/stream-tcp.c b/lib/stream-tcp.c index d62e9c37e..74db2f1e7 100644 --- a/lib/stream-tcp.c +++ b/lib/stream-tcp.c @@ -91,6 +91,62 @@ const struct stream_class tcp_stream_class = { NULL, /* run_wait */ NULL, /* wait */ }; + +#ifdef _WIN32 +static int +windows_open(const char *name, char *suffix, struct stream **streamp, + uint8_t dscp) +{ + int error, port; + FILE *file; + char *suffix_new, *path; + + /* If the path does not contain a ':', assume it is relative to + * OVS_RUNDIR. */ + if (!strchr(suffix, ':')) { + path = xasprintf("%s/%s", ovs_rundir(), suffix); + } else { + path = strdup(suffix); + } + + file = fopen(path, "r"); + if (!file) { + error = errno; + VLOG_DBG("%s: could not open %s (%s)", name, suffix, + ovs_strerror(error)); + return error; + } + + error = fscanf(file, "%d", &port); + if (error != 1) { + VLOG_ERR("failed to read port from %s", suffix); + fclose(file); + return EINVAL; + } + fclose(file); + + suffix_new = xasprintf("127.0.0.1:%d", port); + + error = tcp_open(name, suffix_new, streamp, dscp); + + free(suffix_new); + free(path); + return error; +} + +const struct stream_class windows_stream_class = { + "unix", /* name */ + false, /* needs_probes */ + windows_open, /* open */ + NULL, /* close */ + NULL, /* connect */ + NULL, /* recv */ + NULL, /* send */ + NULL, /* run */ + NULL, /* run_wait */ + NULL, /* wait */ +}; +#endif /* Passive TCP. */ @@ -148,3 +204,60 @@ const struct pstream_class ptcp_pstream_class = { NULL, }; +#ifdef _WIN32 +static int +pwindows_open(const char *name OVS_UNUSED, char *suffix, + struct pstream **pstreamp, uint8_t dscp) +{ + int error; + char *suffix_new, *path; + FILE *file; + struct pstream *listener; + + suffix_new = xstrdup("0:127.0.0.1"); + error = ptcp_open(name, suffix_new, pstreamp, dscp); + if (error) { + goto exit; + } + listener = *pstreamp; + + /* If the path does not contain a ':', assume it is relative to + * OVS_RUNDIR. */ + if (!strchr(suffix, ':')) { + path = xasprintf("%s/%s", ovs_rundir(), suffix); + } else { + path = strdup(suffix); + } + + file = fopen(path, "w"); + if (!file) { + error = errno; + VLOG_DBG("could not open %s (%s)", path, ovs_strerror(error)); + goto exit; + } + + fprintf(file, "%d\n", ntohs(listener->bound_port)); + if (fflush(file) == EOF) { + error = EIO; + VLOG_ERR("write failed for %s", path); + fclose(file); + goto exit; + } + fclose(file); + free(path); + +exit: + free(suffix_new); + return error; +} + +const struct pstream_class pwindows_pstream_class = { + "punix", + false, + pwindows_open, + NULL, + NULL, + NULL, + NULL, +}; +#endif diff --git a/lib/stream.c b/lib/stream.c index fa5b6d604..55632fe3a 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -55,6 +55,8 @@ static const struct stream_class *stream_classes[] = { &tcp_stream_class, #ifndef _WIN32 &unix_stream_class, +#else + &windows_stream_class, #endif #ifdef HAVE_OPENSSL &ssl_stream_class, @@ -65,6 +67,8 @@ static const struct pstream_class *pstream_classes[] = { &ptcp_pstream_class, #ifndef _WIN32 &punix_pstream_class, +#else + &pwindows_pstream_class, #endif #ifdef HAVE_OPENSSL &pssl_pstream_class, diff --git a/lib/unixctl.c b/lib/unixctl.c index 20acc3c9c..c982214ad 100644 --- a/lib/unixctl.c +++ b/lib/unixctl.c @@ -211,28 +211,31 @@ unixctl_server_create(const char *path, struct unixctl_server **serverp) { struct unixctl_server *server; struct pstream *listener; - char *punix_path, *abs_path = NULL; + char *punix_path; int error; -#ifdef _WIN32 - FILE *file; -#endif *serverp = NULL; if (path && !strcmp(path, "none")) { return 0; } -#ifndef _WIN32 if (path) { + char *abs_path; +#ifndef _WIN32 abs_path = abs_file_name(ovs_rundir(), path); +#else + abs_path = strdup(path); +#endif punix_path = xasprintf("punix:%s", abs_path); + free(abs_path); } else { +#ifndef _WIN32 punix_path = xasprintf("punix:%s/%s.%ld.ctl", ovs_rundir(), program_name, (long int) getpid()); - } #else - punix_path = xstrdup("ptcp:0:127.0.0.1"); + punix_path = xasprintf("punix:%s/%s.ctl", ovs_rundir(), program_name); #endif + } error = pstream_open(punix_path, &listener, 0); if (error) { @@ -240,30 +243,6 @@ unixctl_server_create(const char *path, struct unixctl_server **serverp) goto exit; } -#ifdef _WIN32 - if (path) { - abs_path = xstrdup(path); - } else { - abs_path = xasprintf("%s/%s.ctl", ovs_rundir(), program_name); - } - - file = fopen(abs_path, "w"); - if (!file) { - error = errno; - ovs_error(error, "could not open %s", abs_path); - goto exit; - } - - fprintf(file, "%d\n", ntohs(listener->bound_port)); - if (fflush(file) == EOF) { - error = EIO; - ovs_error(error, "write failed for %s", abs_path); - fclose(file); - goto exit; - } - fclose(file); -#endif - unixctl_command_register("help", "", 0, 0, unixctl_help, NULL); unixctl_command_register("version", "", 0, 0, unixctl_version, NULL); @@ -273,9 +252,6 @@ unixctl_server_create(const char *path, struct unixctl_server **serverp) *serverp = server; exit: - if (abs_path) { - free(abs_path); - } free(punix_path); return error; } @@ -460,32 +436,13 @@ unixctl_client_create(const char *path, struct jsonrpc **client) char *abs_path, *unix_path; struct stream *stream; int error; -#ifdef _WIN32 - FILE *file; - int port; +#ifdef _WIN32 abs_path = strdup(path); - file = fopen(abs_path, "r"); - if (!file) { - int error = errno; - ovs_error(error, "could not open %s", abs_path); - free(abs_path); - return error; - } - - error = fscanf(file, "%d", &port); - if (error != 1) { - ovs_error(errno, "failed to read port from %s", abs_path); - free(abs_path); - return EINVAL; - } - fclose(file); - - unix_path = xasprintf("tcp:127.0.0.1:%d", port); #else abs_path = abs_file_name(ovs_rundir(), path); - unix_path = xasprintf("unix:%s", abs_path); #endif + unix_path = xasprintf("unix:%s", abs_path); *client = NULL; diff --git a/lib/vconn-active.man b/lib/vconn-active.man index c1e9281e0..b0c4acea8 100644 --- a/lib/vconn-active.man +++ b/lib/vconn-active.man @@ -11,4 +11,6 @@ future, the default will change to 6653, which is the IANA-defined value. .TP \fBunix:\fIfile\fR -The Unix domain server socket named \fIfile\fR. +On POSIX, a Unix domain server socket named \fIfile\fR. +.IP +On Windows, a localhost TCP port written in \fIfile\fR. diff --git a/ovsdb/remote-active.man b/ovsdb/remote-active.man index 419b1c835..5facf0aea 100644 --- a/ovsdb/remote-active.man +++ b/ovsdb/remote-active.man @@ -12,4 +12,7 @@ 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. +On POSIX, connect to the Unix domain server socket named \fIfile\fR. +.IP +On Windows, connect to a localhost TCP port whose value is written in +\fIfile\fR. diff --git a/ovsdb/remote-passive.man b/ovsdb/remote-passive.man index 200651ba6..e5e5c9886 100644 --- a/ovsdb/remote-passive.man +++ b/ovsdb/remote-passive.man @@ -19,5 +19,8 @@ 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 +On POSIX, listen on the Unix domain server socket named \fIfile\fR for a connection. +.IP +On Windows, listen on a kernel chosen TCP port on the localhost. The kernel +chosen TCP port value is written in \fIfile\fR.