Catalli's threaded switch
[sliver-openvswitch.git] / utilities / ovs-appctl.c
1 /*
2  * Copyright (c) 2008, 2009, 2010 Nicira Networks.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18
19 #include <errno.h>
20 #include <getopt.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include "command-line.h"
26 #include "daemon.h"
27 #include "dirs.h"
28 #include "dynamic-string.h"
29 #include "timeval.h"
30 #include "unixctl.h"
31 #include "util.h"
32
33 static void usage(void);
34 static const char *parse_command_line(int argc, char *argv[]);
35 static struct unixctl_client *connect_to_target(const char *target);
36
37 int
38 main(int argc, char *argv[])
39 {
40     struct unixctl_client *client;
41     const char *target;
42     struct ds request;
43     int code, error;
44     char *reply;
45     int i;
46
47     set_program_name(argv[0]);
48
49     /* Parse command line and connect to target. */
50     target = parse_command_line(argc, argv);
51     client = connect_to_target(target);
52
53     /* Compose request. */
54     ds_init(&request);
55     for (i = optind; i < argc; i++) {
56         if (i != optind) {
57             ds_put_char(&request, ' ');
58         }
59         ds_put_cstr(&request, argv[i]);
60     }
61
62     /* Transact request and process reply. */
63     error = unixctl_client_transact(client, ds_cstr(&request), &code, &reply);
64     if (error) {
65         ovs_fatal(error, "%s: transaction error", target);
66     }
67     if (code / 100 != 2) {
68         ovs_error(0, "%s: server returned reply code %03d", target, code);
69         exit(2);
70     }
71     fputs(reply, stdout);
72
73     unixctl_client_destroy(client);
74     free(reply);
75     ds_destroy(&request);
76
77     return 0;
78 }
79
80 static void
81 usage(void)
82 {
83     printf("%s, for querying and controlling Open vSwitch daemon\n"
84            "usage: %s [TARGET] COMMAND [ARG...]\n"
85            "Targets:\n"
86            "  -t, --target=TARGET  pidfile or socket to contact\n"
87            "Common commands:"
88            "  help               List commands supported by the target\n"
89            "  vlog/list          List current logging levels\n"
90            "  vlog/set MODULE[:FACILITY[:LEVEL]]\n"
91            "        Set MODULE and FACILITY log level to LEVEL\n"
92            "        MODULE may be any valid module name or 'ANY'\n"
93            "        FACILITY may be 'syslog', 'console', 'file', or 'ANY' (default)\n"
94            "        LEVEL may be 'emer', 'err', 'warn', 'info', or 'dbg' (default)\n"
95            "  vlog/reopen        Make the program reopen its log file\n"
96            "Other options:\n"
97            "  -h, --help         Print this helpful information\n"
98            "  -V, --version      Display version information\n",
99            program_name, program_name);
100     exit(EXIT_SUCCESS);
101 }
102
103 static const char *
104 parse_command_line(int argc, char *argv[])
105 {
106     static const struct option long_options[] = {
107         {"target", required_argument, NULL, 't'},
108         {"execute", no_argument, NULL, 'e'},
109         {"help", no_argument, NULL, 'h'},
110         {"version", no_argument, NULL, 'V'},
111         {0, 0, 0, 0},
112     };
113     const char *target;
114     int e_options;
115
116     target = NULL;
117     e_options = 0;
118     for (;;) {
119         int option;
120
121         option = getopt_long(argc, argv, "+t:hVe", long_options, NULL);
122         if (option == -1) {
123             break;
124         }
125         switch (option) {
126         case 't':
127             if (target) {
128                 ovs_fatal(0, "-t or --target may be specified only once");
129             }
130             target = optarg;
131             break;
132
133         case 'e':
134             /* We ignore -e for compatibility.  Older versions specified the
135              * command as the argument to -e.  Since the current version takes
136              * the command as non-option arguments and we say that -e has no
137              * arguments, this just works in the common case. */
138             if (e_options++) {
139                 ovs_fatal(0, "-e or --execute may be speciifed only once");
140             }
141             break;
142
143         case 'h':
144             usage();
145             break;
146
147         case 'V':
148             OVS_PRINT_VERSION(0, 0);
149             exit(EXIT_SUCCESS);
150
151         case '?':
152             exit(EXIT_FAILURE);
153
154         default:
155             NOT_REACHED();
156         }
157     }
158
159     if (optind >= argc) {
160         ovs_fatal(0, "at least one non-option argument is required "
161                   "(use --help for help)");
162     }
163
164     return target ? target : "ovs-vswitchd";
165 }
166
167 static struct unixctl_client *
168 connect_to_target(const char *target)
169 {
170     struct unixctl_client *client;
171     char *socket_name;
172     int error;
173
174     if (target[0] != '/') {
175         char *pidfile_name;
176         pid_t pid;
177
178         pidfile_name = xasprintf("%s/%s.pid", ovs_rundir, target);
179         pid = read_pidfile(pidfile_name);
180         if (pid < 0) {
181             ovs_fatal(-pid, "cannot read pidfile \"%s\"", pidfile_name);
182         }
183         free(pidfile_name);
184         socket_name = xasprintf("%s/%s.%ld.ctl",
185                                 ovs_rundir, target, (long int) pid);
186     } else {
187         socket_name = xstrdup(target);
188     }
189
190     error = unixctl_client_create(socket_name, &client);
191     if (error) {
192         ovs_fatal(error, "cannot connect to \"%s\"", socket_name);
193     }
194     free(socket_name);
195
196     return client;
197 }
198