lib/netdev-dpdk: increase ring name length for dpdkr ports
[cascardo/ovs.git] / lib / unixctl.c
index 054ce49..b47f35a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks.
+ * 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.
@@ -16,7 +16,6 @@
 
 #include <config.h>
 #include "unixctl.h"
-#include <assert.h>
 #include <errno.h>
 #include <unistd.h>
 #include "coverage.h"
@@ -28,8 +27,9 @@
 #include "poll-loop.h"
 #include "shash.h"
 #include "stream.h"
+#include "stream-provider.h"
 #include "svec.h"
-#include "vlog.h"
+#include "openvswitch/vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(unixctl);
 
@@ -44,7 +44,7 @@ struct unixctl_command {
 };
 
 struct unixctl_conn {
-    struct list node;
+    struct ovs_list node;
     struct jsonrpc *rpc;
 
     /* Only one request can be in progress at a time.  While the request is
@@ -55,7 +55,7 @@ struct unixctl_conn {
 /* Server for control connection. */
 struct unixctl_server {
     struct pstream *listener;
-    struct list conns;
+    struct ovs_list conns;
 };
 
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
@@ -63,8 +63,8 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
 static struct shash commands = SHASH_INITIALIZER(&commands);
 
 static void
-unixctl_help(struct unixctl_conn *conn, int argc OVS_UNUSED,
-             const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
+unixctl_list_commands(struct unixctl_conn *conn, int argc OVS_UNUSED,
+                      const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
 {
     struct ds ds = DS_EMPTY_INITIALIZER;
     const struct shash_node **nodes = shash_sort(&commands);
@@ -88,20 +88,20 @@ static void
 unixctl_version(struct unixctl_conn *conn, int argc OVS_UNUSED,
                 const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
 {
-    unixctl_command_reply(conn, get_program_version());
+    unixctl_command_reply(conn, ovs_get_program_version());
 }
 
 /* Registers a unixctl command with the given 'name'.  'usage' describes the
  * arguments to the command; it is used only for presentation to the user in
- * "help" output.
+ * "list-commands" output.
  *
- * 'cb' is called when the command is received.  It is passed the actual set of
- * arguments, as a text string, plus a copy of 'aux'.  Normally 'cb' should
- * reply by calling unixctl_command_reply() or unixctl_command_reply_error()
- * before it returns, but if the command cannot be handled immediately then it
- * can defer the reply until later.  A given connection can only process a
- * single request at a time, so a reply must be made eventually to avoid
- * blocking that connection. */
+ * 'cb' is called when the command is received.  It is passed an array
+ * containing the command name and arguments, plus a copy of 'aux'.  Normally
+ * 'cb' should reply by calling unixctl_command_reply() or
+ * unixctl_command_reply_error() before it returns, but if the command cannot
+ * be handled immediately then it can defer the reply until later.  A given
+ * connection can only process a single request at a time, so a reply must be
+ * made eventually to avoid blocking that connection. */
 void
 unixctl_command_register(const char *name, const char *usage,
                          int min_args, int max_args,
@@ -110,7 +110,7 @@ unixctl_command_register(const char *name, const char *usage,
     struct unixctl_command *command;
     struct unixctl_command *lookup = shash_find_data(&commands, name);
 
-    assert(!lookup || lookup->cb == cb);
+    ovs_assert(!lookup || lookup->cb == cb);
 
     if (lookup) {
         return;
@@ -133,7 +133,7 @@ unixctl_command_reply__(struct unixctl_conn *conn,
     struct jsonrpc_msg *reply;
 
     COVERAGE_INC(unixctl_replied);
-    assert(conn->request_id);
+    ovs_assert(conn->request_id);
 
     if (!body) {
         body = "";
@@ -169,7 +169,7 @@ unixctl_command_reply(struct unixctl_conn *conn, const char *result)
 }
 
 /* Replies to the active unixctl connection 'conn'. 'error' is sent to the
- * client indicating an error occured processing the command.  Only one call to
+ * client indicating an error occurred processing the command.  Only one call to
  * unixctl_command_reply() or unixctl_command_reply_error() may be made per
  * request. */
 void
@@ -178,19 +178,26 @@ unixctl_command_reply_error(struct unixctl_conn *conn, const char *error)
     unixctl_command_reply__(conn, false, error);
 }
 
-/* Creates a unixctl server listening on 'path', which may be:
+/* Creates a unixctl server listening on 'path', which for POSIX may be:
  *
  *      - NULL, in which case <rundir>/<program>.<pid>.ctl is used.
  *
- *      - "none", in which case the function will return successfully but
- *        no socket will actually be created.
- *
  *      - A name that does not start with '/', in which case it is put in
  *        <rundir>.
  *
  *      - An absolute path (starting with '/') that gives the exact name of
  *        the Unix domain socket to listen on.
  *
+ * For Windows, a kernel assigned TCP port is used and written in 'path'
+ * which may be:
+ *
+ *      - NULL, in which case <rundir>/<program>.ctl is used.
+ *
+ *      - An absolute path that gives the name of the file.
+ *
+ * For both POSIX and Windows, if the path is "none", the function will
+ * return successfully but no socket will actually be created.
+ *
  * A program that (optionally) daemonizes itself should call this function
  * *after* daemonization, so that the socket name contains the pid of the
  * daemon instead of the pid of the program that exited.  (Otherwise,
@@ -213,31 +220,41 @@ unixctl_server_create(const char *path, struct unixctl_server **serverp)
     }
 
     if (path) {
-        char *abs_path = abs_file_name(ovs_rundir(), path);
+        char *abs_path;
+#ifndef _WIN32
+        abs_path = abs_file_name(ovs_rundir(), path);
+#else
+        abs_path = xstrdup(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 = xasprintf("punix:%s/%s.ctl", ovs_rundir(), program_name);
+#endif
     }
 
-    error = pstream_open(punix_path, &listener);
-    free(punix_path);
-    punix_path = NULL;
-
+    error = pstream_open(punix_path, &listener, 0);
     if (error) {
-        ovs_error(error, "could not initialize control socket %s", path);
-        return error;
+        ovs_error(error, "could not initialize control socket %s", punix_path);
+        goto exit;
     }
 
-    unixctl_command_register("help", "", 0, 0, unixctl_help, NULL);
+    unixctl_command_register("list-commands", "", 0, 0, unixctl_list_commands,
+                             NULL);
     unixctl_command_register("version", "", 0, 0, unixctl_version, NULL);
 
     server = xmalloc(sizeof *server);
     server->listener = listener;
     list_init(&server->conns);
     *serverp = server;
-    return 0;
+
+exit:
+    free(punix_path);
+    return error;
 }
 
 static void
@@ -359,7 +376,7 @@ unixctl_server_run(struct unixctl_server *server)
         } else {
             VLOG_WARN_RL(&rl, "%s: accept failed: %s",
                          pstream_get_name(server->listener),
-                         strerror(error));
+                         ovs_strerror(error));
         }
     }
 
@@ -405,9 +422,12 @@ unixctl_server_destroy(struct unixctl_server *server)
     }
 }
 \f
-/* Connects to a unixctl server socket.  'path' should be the name of a unixctl
- * server socket.  If it does not start with '/', it will be prefixed with the
- * rundir (e.g. /usr/local/var/run/openvswitch).
+/* On POSIX based systems, connects to a unixctl server socket.  'path' should
+ * be the name of a unixctl server socket.  If it does not start with '/', it
+ * will be prefixed with the rundir (e.g. /usr/local/var/run/openvswitch).
+ *
+ * On Windows, connects to a localhost TCP port as written inside 'path'.
+ * 'path' should be an absolute path of the file.
  *
  * Returns 0 if successful, otherwise a positive errno value.  If successful,
  * sets '*client' to the new jsonrpc, otherwise to NULL. */
@@ -418,11 +438,17 @@ unixctl_client_create(const char *path, struct jsonrpc **client)
     struct stream *stream;
     int error;
 
-    *client = NULL;
-
+#ifdef _WIN32
+    abs_path = xstrdup(path);
+#else
     abs_path = abs_file_name(ovs_rundir(), path);
+#endif
     unix_path = xasprintf("unix:%s", abs_path);
-    error = stream_open_block(stream_open(unix_path, &stream), &stream);
+
+    *client = NULL;
+
+    error = stream_open_block(stream_open(unix_path, &stream, DSCP_DEFAULT),
+                              &stream);
     free(unix_path);
     free(abs_path);
 
@@ -462,7 +488,7 @@ unixctl_client_transact(struct jsonrpc *client, const char *command, int argc,
     error = jsonrpc_transact_block(client, request, &reply);
     if (error) {
         VLOG_WARN("error communicating with %s: %s", jsonrpc_get_name(client),
-                  strerror(error));
+                  ovs_retval_to_string(error));
         return error;
     }