ovsdb-server: Announce bound listening ports as status:bound_port.
authorBen Pfaff <blp@nicira.com>
Thu, 18 Apr 2013 23:37:05 +0000 (16:37 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 18 Apr 2013 23:43:15 +0000 (16:43 -0700)
The administrator can request that OVSDB bind any available TCP port, but
in that case there is no easy way to find out what port it has bound.  This
commit adds that information as the "bound_port" key in the "status"
column.

Signed-off-by: Ben Pfaff <blp@nicira.com>
lib/stream-provider.h
lib/stream-ssl.c
lib/stream-tcp.c
lib/stream.c
lib/stream.h
ovsdb/jsonrpc-server.c
ovsdb/jsonrpc-server.h
ovsdb/ovsdb-server.c
tests/ofproto-dpif.at
tests/ofproto-macros.at
vswitchd/vswitch.xml

index 1db3735..43c63e8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -139,9 +139,11 @@ struct stream_class {
 struct pstream {
     const struct pstream_class *class;
     char *name;
+    ovs_be16 bound_port;
 };
 
 void pstream_init(struct pstream *, const struct pstream_class *, const char *name);
+void pstream_set_bound_port(struct pstream *, ovs_be16 bound_port);
 static inline void pstream_assert_class(const struct pstream *pstream,
                                         const struct pstream_class *class)
 {
index 23c5591..ddf65a3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -808,6 +808,7 @@ pssl_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
 
     pssl = xmalloc(sizeof *pssl);
     pstream_init(&pssl->pstream, &pssl_pstream_class, bound_name);
+    pstream_set_bound_port(&pssl->pstream, sin.sin_port);
     pssl->fd = fd;
     *pstreamp = &pssl->pstream;
     return 0;
index 0384c42..1767fe4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -108,6 +108,7 @@ ptcp_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
 {
     struct sockaddr_in sin;
     char bound_name[128];
+    int error;
     int fd;
 
     fd = inet_open_passive(SOCK_STREAM, suffix, -1, &sin, dscp);
@@ -117,8 +118,12 @@ ptcp_open(const char *name OVS_UNUSED, char *suffix, struct pstream **pstreamp,
 
     sprintf(bound_name, "ptcp:%"PRIu16":"IP_FMT,
             ntohs(sin.sin_port), IP_ARGS(sin.sin_addr.s_addr));
-    return new_fd_pstream(bound_name, fd, ptcp_accept, set_dscp, NULL,
-                          pstreamp);
+    error = new_fd_pstream(bound_name, fd, ptcp_accept, set_dscp, NULL,
+                           pstreamp);
+    if (!error) {
+        pstream_set_bound_port(*pstreamp, sin.sin_port);
+    }
+    return error;
 }
 
 static int
index 0c6a8c1..da089ae 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -621,6 +621,14 @@ pstream_set_dscp(struct pstream *pstream, uint8_t dscp)
     }
     return 0;
 }
+
+/* Returns the transport port on which 'pstream' is listening, or 0 if the
+ * concept doesn't apply. */
+ovs_be16
+pstream_get_bound_port(const struct pstream *pstream)
+{
+    return pstream->bound_port;
+}
 \f
 /* Initializes 'stream' as a new stream named 'name', implemented via 'class'.
  * The initial connection status, supplied as 'connect_status', is interpreted
@@ -681,9 +689,16 @@ void
 pstream_init(struct pstream *pstream, const struct pstream_class *class,
             const char *name)
 {
+    memset(pstream, 0, sizeof *pstream);
     pstream->class = class;
     pstream->name = xstrdup(name);
 }
+
+void
+pstream_set_bound_port(struct pstream *pstream, ovs_be16 port)
+{
+    pstream->bound_port = port;
+}
 \f
 static int
 count_fields(const char *s_)
index d2f2ebb..aa3fa9d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -66,6 +66,8 @@ int pstream_accept(struct pstream *, struct stream **);
 int pstream_accept_block(struct pstream *, struct stream **);
 void pstream_wait(struct pstream *);
 int pstream_set_dscp(struct pstream *, uint8_t dscp);
+
+ovs_be16 pstream_get_bound_port(const struct pstream *);
 \f
 /* Convenience functions. */
 
index febc351..9f99d64 100644 (file)
@@ -597,6 +597,10 @@ ovsdb_jsonrpc_session_get_status(const struct ovsdb_jsonrpc_remote *remote,
     struct reconnect_stats rstats;
     struct ds locks_held, locks_waiting, locks_lost;
 
+    status->bound_port = (remote->listener
+                          ? pstream_get_bound_port(remote->listener)
+                          : htons(0));
+
     if (list_is_empty(&remote->sessions)) {
         return false;
     }
index bf2a2fc..f2395fc 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 #define OVSDB_JSONRPC_SERVER_H 1
 
 #include <stdbool.h>
+#include "openvswitch/types.h"
 
 struct ovsdb;
 struct shash;
@@ -50,6 +51,7 @@ struct ovsdb_jsonrpc_remote_status {
     char *locks_waiting;
     char *locks_lost;
     int n_connections;
+    ovs_be16 bound_port;
 };
 bool ovsdb_jsonrpc_server_get_remote_status(
     const struct ovsdb_jsonrpc_server *, const char *target,
index 61095e2..a8daf1f 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <errno.h>
 #include <getopt.h>
+#include <inttypes.h>
 #include <signal.h>
 #include <unistd.h>
 
@@ -683,7 +684,7 @@ update_remote_row(const struct ovsdb_row *row, struct ovsdb_txn *txn,
     struct ovsdb_jsonrpc_remote_status status;
     struct ovsdb_row *rw_row;
     const char *target;
-    char *keys[8], *values[8];
+    char *keys[9], *values[9];
     size_t n = 0;
 
     /* Get the "target" (protocol/host/port) spec. */
@@ -730,6 +731,10 @@ update_remote_row(const struct ovsdb_row *row, struct ovsdb_txn *txn,
         keys[n] = xstrdup("n_connections");
         values[n++] = xasprintf("%d", status.n_connections);
     }
+    if (status.bound_port != htons(0)) {
+        keys[n] = xstrdup("bound_port");
+        values[n++] = xasprintf("%"PRIu16, ntohs(status.bound_port));
+    }
     write_string_string_column(rw_row, "status", keys, values, n);
 
     ovsdb_jsonrpc_server_free_remote_status(&status);
index 0de941e..fef5f95 100644 (file)
@@ -1210,6 +1210,7 @@ dnl Test that sFlow samples packets correctly.
 AT_SETUP([ofproto-dpif - sFlow packet sampling])
 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`
@@ -1224,7 +1225,6 @@ ovs-vsctl \
    set Bridge br0 sflow=@sf -- \
    --id=@sf create sflow targets=\"127.0.0.1:$SFLOW_PORT\" \
      header=128 sampling=1 polling=1
-ON_EXIT([kill `cat test-sflow.pid`])
 
 dnl open with ARP packets to seed the bridge-learning.  The output
 dnl ifIndex numbers should be reported predictably after that.
index cad0080..73c6c28 100644 (file)
@@ -17,17 +17,17 @@ s/ hard_age=[0-9]*,//
 
 # parse_listening_port [SERVER]
 #
-# Parses the TCP or SSL port on which a server is listening from the 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.
+# Parses the TCP or SSL port on which a server is listening from the
+# 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.
 #
 # Here's an example of how to use this with ovsdb-server:
 #
 #    OVS_LOGDIR=`pwd`; export OVS_LOGDIR
 #    ovsdb-server --log-file --remote=ptcp:0:127.0.0.1 ...
 #    TCP_PORT=`parse_listening_port < ovsdb-server.log`
-#
-# (Also works with pssl: in place of ptcp:.)
 parse_listening_port () {
     sed -n 's/.*0:127\.0\.0\.1: listening on port \([0-9]*\)$/\1/p'
 }]
index 2af04bd..21bcbc2 100644 (file)
           <dd>
             <p>
               Listens for SSL connections on the specified TCP <var>port</var>
-              (default: 6632).  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.
+              (default: 6632).  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.
             </p>
             <p>
               The <ref table="Open_vSwitch" column="ssl"/> column in the <ref
           <dt><code>ptcp:</code>[<var>port</var>][<code>:<var>ip</var></code>]</dt>
           <dd>
             Listens for connections on the specified TCP <var>port</var>
-            (default: 6632).  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.
+            (default: 6632).  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.
           </dd>
         </dl>
         <p>When multiple managers are configured, the <ref column="target"/>
           chosen connection.
         </p>
       </column>
+
+      <column name="status" key="bound_port" type='{"type": "integer"}'>
+          When <ref column="target"/> is <code>ptcp:</code> or
+          <code>pssl:</code>, this is the TCP port on which the OVSDB server is
+          listening.  (This is is particularly useful when <ref
+          column="target"/> specifies a port of 0, allowing the kernel to
+          choose any available port.)
+      </column>
     </group>
 
     <group title="Connection Parameters">