meta-flow: Correctly set destination MAC in mf_set_flow_value().
[sliver-openvswitch.git] / utilities / ovs-appctl.c
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 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         fputs(reply, stderr);
69         ovs_error(0, "%s: server returned reply code %03d", target, code);
70         exit(2);
71     }
72     fputs(reply, stdout);
73
74     unixctl_client_destroy(client);
75     free(reply);
76     ds_destroy(&request);
77
78     return 0;
79 }
80
81 static void
82 usage(void)
83 {
84     printf("\
85 %s, for querying and controlling Open vSwitch daemon\n\
86 usage: %s [TARGET] COMMAND [ARG...]\n\
87 Targets:\n\
88   -t, --target=TARGET  pidfile or socket to contact\n\
89 Common commands:\n\
90   help               List commands supported by the target\n\
91   version            Print version of the target\n\
92   vlog/list          List current logging levels\n\
93   vlog/set MODULE[:FACILITY[:LEVEL]]\n\
94       Set MODULE and FACILITY log level to LEVEL\n\
95       MODULE may be any valid module name or 'ANY'\n\
96       FACILITY may be 'syslog', 'console', 'file', or 'ANY' (default)\n\
97       LEVEL may be 'off', 'emer', 'err', 'warn', 'info', or 'dbg' (default)\n\
98   vlog/reopen        Make the program reopen its log file\n\
99 Other options:\n\
100   -h, --help         Print this helpful information\n\
101   -V, --version      Display ovs-appctl version information\n",
102            program_name, program_name);
103     exit(EXIT_SUCCESS);
104 }
105
106 static const char *
107 parse_command_line(int argc, char *argv[])
108 {
109     static const struct option long_options[] = {
110         {"target", required_argument, NULL, 't'},
111         {"execute", no_argument, NULL, 'e'},
112         {"help", no_argument, NULL, 'h'},
113         {"version", no_argument, NULL, 'V'},
114         {NULL, 0, NULL, 0},
115     };
116     const char *target;
117     int e_options;
118
119     target = NULL;
120     e_options = 0;
121     for (;;) {
122         int option;
123
124         option = getopt_long(argc, argv, "+t:hVe", long_options, NULL);
125         if (option == -1) {
126             break;
127         }
128         switch (option) {
129         case 't':
130             if (target) {
131                 ovs_fatal(0, "-t or --target may be specified only once");
132             }
133             target = optarg;
134             break;
135
136         case 'e':
137             /* We ignore -e for compatibility.  Older versions specified the
138              * command as the argument to -e.  Since the current version takes
139              * the command as non-option arguments and we say that -e has no
140              * arguments, this just works in the common case. */
141             if (e_options++) {
142                 ovs_fatal(0, "-e or --execute may be speciifed only once");
143             }
144             break;
145
146         case 'h':
147             usage();
148             break;
149
150         case 'V':
151             ovs_print_version(0, 0);
152             exit(EXIT_SUCCESS);
153
154         case '?':
155             exit(EXIT_FAILURE);
156
157         default:
158             NOT_REACHED();
159         }
160     }
161
162     if (optind >= argc) {
163         ovs_fatal(0, "at least one non-option argument is required "
164                   "(use --help for help)");
165     }
166
167     return target ? target : "ovs-vswitchd";
168 }
169
170 static struct unixctl_client *
171 connect_to_target(const char *target)
172 {
173     struct unixctl_client *client;
174     char *socket_name;
175     int error;
176
177     if (target[0] != '/') {
178         char *pidfile_name;
179         pid_t pid;
180
181         pidfile_name = xasprintf("%s/%s.pid", ovs_rundir(), target);
182         pid = read_pidfile(pidfile_name);
183         if (pid < 0) {
184             ovs_fatal(-pid, "cannot read pidfile \"%s\"", pidfile_name);
185         }
186         free(pidfile_name);
187         socket_name = xasprintf("%s/%s.%ld.ctl",
188                                 ovs_rundir(), target, (long int) pid);
189     } else {
190         socket_name = xstrdup(target);
191     }
192
193     error = unixctl_client_create(socket_name, &client);
194     if (error) {
195         ovs_fatal(error, "cannot connect to \"%s\"", socket_name);
196     }
197     free(socket_name);
198
199     return client;
200 }
201