]> git.proxmox.com Git - ovs.git/blame - utilities/ovs-openflowd.c
Avoid shadowing local variable names.
[ovs.git] / utilities / ovs-openflowd.c
CommitLineData
064af421 1/*
67b732e8 2 * Copyright (c) 2008, 2009, 2010 Nicira Networks.
064af421 3 *
a14bc59f
BP
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:
064af421 7 *
a14bc59f
BP
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.
064af421
BP
15 */
16
17#include <config.h>
18#include <assert.h>
19#include <errno.h>
20#include <getopt.h>
21#include <inttypes.h>
22#include <netinet/in.h>
23#include <stdlib.h>
24#include <signal.h>
25#include <string.h>
26
27#include "command-line.h"
28#include "compiler.h"
29#include "daemon.h"
30#include "dirs.h"
064af421 31#include "dpif.h"
064af421
BP
32#include "leak-checker.h"
33#include "list.h"
34#include "netdev.h"
35#include "ofpbuf.h"
8cd4882f 36#include "ofproto/ofproto.h"
064af421
BP
37#include "openflow/openflow.h"
38#include "packets.h"
39#include "poll-loop.h"
40#include "rconn.h"
fe55ad15 41#include "stream-ssl.h"
064af421
BP
42#include "svec.h"
43#include "timeval.h"
44#include "unixctl.h"
45#include "util.h"
064af421 46#include "vconn.h"
064af421 47#include "vlog.h"
5136ce49
BP
48
49VLOG_DEFINE_THIS_MODULE(openflowd)
064af421 50
064af421
BP
51/* Settings that may be configured by the user. */
52struct ofsettings {
79c9f2ee 53 /* Controller configuration. */
76ce9432
BP
54 struct ofproto_controller *controllers;
55 size_t n_controllers;
31681a5d 56 enum ofproto_fail_mode fail_mode;
064af421
BP
57
58 /* Datapath. */
59 uint64_t datapath_id; /* Datapath ID. */
0e17074a
JG
60 char *dp_name; /* Name of local datapath. */
61 char *dp_type; /* Type of local datapath. */
e3e9370b 62 struct svec ports; /* Set of ports to add to datapath (if any). */
064af421
BP
63
64 /* Description strings. */
65 const char *mfr_desc; /* Manufacturer. */
66 const char *hw_desc; /* Hardware. */
67 const char *sw_desc; /* Software version. */
68 const char *serial_desc; /* Serial number. */
ce640333 69 const char *dp_desc; /* Datapath description. */
064af421
BP
70
71 /* Related vconns and network devices. */
064af421
BP
72 struct svec snoops; /* Listen for controller snooping conns. */
73
74 /* Failure behavior. */
064af421 75 int max_idle; /* Idle time for flows in fail-open mode. */
064af421 76
064af421
BP
77 /* NetFlow. */
78 struct svec netflow; /* NetFlow targets. */
79};
80
81static void parse_options(int argc, char *argv[], struct ofsettings *);
82static void usage(void) NO_RETURN;
83
84int
85main(int argc, char *argv[])
86{
87 struct unixctl_server *unixctl;
88 struct ofproto *ofproto;
89 struct ofsettings s;
90 int error;
0e17074a 91 struct dpif *dpif;
0193b2af 92 struct netflow_options nf_options;
064af421 93
40f0707c 94 proctitle_init(argc, argv);
064af421 95 set_program_name(argv[0]);
064af421
BP
96 parse_options(argc, argv, &s);
97 signal(SIGPIPE, SIG_IGN);
98
99 die_if_already_running();
95440284 100 daemonize_start();
064af421
BP
101
102 /* Start listening for ovs-appctl requests. */
103 error = unixctl_server_create(NULL, &unixctl);
104 if (error) {
4d12270a 105 exit(EXIT_FAILURE);
064af421
BP
106 }
107
108 VLOG_INFO("Open vSwitch version %s", VERSION BUILDNR);
109 VLOG_INFO("OpenFlow protocol version 0x%02x", OFP_VERSION);
110
0e17074a
JG
111 error = dpif_create_and_open(s.dp_name, s.dp_type, &dpif);
112 if (error) {
113 ovs_fatal(error, "could not create datapath");
114 }
115
116 /* Add ports to the datapath if requested by the user. */
e3e9370b 117 if (s.ports.n) {
e3e9370b
BP
118 const char *port;
119 size_t i;
e3e9370b
BP
120
121 SVEC_FOR_EACH (i, port, &s.ports) {
122 error = dpif_port_add(dpif, port, 0, NULL);
123 if (error) {
124 ovs_fatal(error, "failed to add %s as a port", port);
125 }
126 }
e3e9370b
BP
127 }
128
064af421 129 /* Start OpenFlow processing. */
0e17074a 130 error = ofproto_create(s.dp_name, s.dp_type, NULL, NULL, &ofproto);
064af421
BP
131 if (error) {
132 ovs_fatal(error, "could not initialize openflow switch");
133 }
064af421
BP
134 if (s.datapath_id) {
135 ofproto_set_datapath_id(ofproto, s.datapath_id);
136 }
8abc4ed7
JP
137 ofproto_set_desc(ofproto, s.mfr_desc, s.hw_desc, s.sw_desc,
138 s.serial_desc, s.dp_desc);
064af421
BP
139 error = ofproto_set_snoops(ofproto, &s.snoops);
140 if (error) {
141 ovs_fatal(error,
142 "failed to configure controller snooping connections");
143 }
0193b2af
JG
144 memset(&nf_options, 0, sizeof nf_options);
145 nf_options.collectors = s.netflow;
146 error = ofproto_set_netflow(ofproto, &nf_options);
064af421
BP
147 if (error) {
148 ovs_fatal(error, "failed to configure NetFlow collectors");
149 }
76ce9432 150 ofproto_set_controllers(ofproto, s.controllers, s.n_controllers);
31681a5d 151 ofproto_set_fail_mode(ofproto, s.fail_mode);
064af421 152
95440284
BP
153 daemonize_complete();
154
064af421
BP
155 while (ofproto_is_alive(ofproto)) {
156 error = ofproto_run(ofproto);
157 if (error) {
158 ovs_fatal(error, "unrecoverable datapath error");
159 }
160 unixctl_server_run(unixctl);
5792c5c6 161 dp_run();
8b61709d 162 netdev_run();
064af421
BP
163
164 ofproto_wait(ofproto);
165 unixctl_server_wait(unixctl);
5792c5c6 166 dp_wait();
8b61709d 167 netdev_wait();
064af421
BP
168 poll_block();
169 }
170
0e17074a
JG
171 dpif_close(dpif);
172
064af421
BP
173 return 0;
174}
175\f
176/* User interface. */
177
178static void
179parse_options(int argc, char *argv[], struct ofsettings *s)
180{
181 enum {
182 OPT_DATAPATH_ID = UCHAR_MAX + 1,
0c30c8f1
JP
183 OPT_MFR_DESC,
184 OPT_HW_DESC,
185 OPT_SW_DESC,
186 OPT_SERIAL_DESC,
8abc4ed7 187 OPT_DP_DESC,
064af421
BP
188 OPT_ACCEPT_VCONN,
189 OPT_NO_RESOLV_CONF,
190 OPT_BR_NAME,
191 OPT_FAIL_MODE,
192 OPT_INACTIVITY_PROBE,
193 OPT_MAX_IDLE,
194 OPT_MAX_BACKOFF,
195 OPT_SNOOP,
196 OPT_RATE_LIMIT,
197 OPT_BURST_LIMIT,
198 OPT_BOOTSTRAP_CA_CERT,
064af421
BP
199 OPT_OUT_OF_BAND,
200 OPT_IN_BAND,
064af421 201 OPT_NETFLOW,
e3e9370b 202 OPT_PORTS,
064af421
BP
203 VLOG_OPTION_ENUMS,
204 LEAK_CHECKER_OPTION_ENUMS
205 };
206 static struct option long_options[] = {
207 {"datapath-id", required_argument, 0, OPT_DATAPATH_ID},
0c30c8f1
JP
208 {"mfr-desc", required_argument, 0, OPT_MFR_DESC},
209 {"hw-desc", required_argument, 0, OPT_HW_DESC},
210 {"sw-desc", required_argument, 0, OPT_SW_DESC},
211 {"serial-desc", required_argument, 0, OPT_SERIAL_DESC},
212 {"dp-desc", required_argument, 0, OPT_DP_DESC},
064af421
BP
213 {"accept-vconn", required_argument, 0, OPT_ACCEPT_VCONN},
214 {"no-resolv-conf", no_argument, 0, OPT_NO_RESOLV_CONF},
215 {"config", required_argument, 0, 'F'},
216 {"br-name", required_argument, 0, OPT_BR_NAME},
217 {"fail", required_argument, 0, OPT_FAIL_MODE},
218 {"inactivity-probe", required_argument, 0, OPT_INACTIVITY_PROBE},
219 {"max-idle", required_argument, 0, OPT_MAX_IDLE},
220 {"max-backoff", required_argument, 0, OPT_MAX_BACKOFF},
221 {"listen", required_argument, 0, 'l'},
222 {"snoop", required_argument, 0, OPT_SNOOP},
223 {"rate-limit", optional_argument, 0, OPT_RATE_LIMIT},
224 {"burst-limit", required_argument, 0, OPT_BURST_LIMIT},
064af421
BP
225 {"out-of-band", no_argument, 0, OPT_OUT_OF_BAND},
226 {"in-band", no_argument, 0, OPT_IN_BAND},
064af421 227 {"netflow", required_argument, 0, OPT_NETFLOW},
e3e9370b 228 {"ports", required_argument, 0, OPT_PORTS},
064af421
BP
229 {"verbose", optional_argument, 0, 'v'},
230 {"help", no_argument, 0, 'h'},
231 {"version", no_argument, 0, 'V'},
232 DAEMON_LONG_OPTIONS,
233 VLOG_LONG_OPTIONS,
234 LEAK_CHECKER_LONG_OPTIONS,
235#ifdef HAVE_OPENSSL
fe55ad15 236 STREAM_SSL_LONG_OPTIONS
064af421
BP
237 {"bootstrap-ca-cert", required_argument, 0, OPT_BOOTSTRAP_CA_CERT},
238#endif
239 {0, 0, 0, 0},
240 };
241 char *short_options = long_options_to_short_options(long_options);
76ce9432 242 struct ofproto_controller controller_opts;
7d674866
BP
243 struct svec controllers;
244 int i;
064af421
BP
245
246 /* Set defaults that we can figure out before parsing options. */
76ce9432
BP
247 controller_opts.target = NULL;
248 controller_opts.max_backoff = 8;
249 controller_opts.probe_interval = 5;
76ce9432
BP
250 controller_opts.band = OFPROTO_IN_BAND;
251 controller_opts.accept_re = NULL;
252 controller_opts.update_resolv_conf = true;
253 controller_opts.rate_limit = 0;
254 controller_opts.burst_limit = 0;
31681a5d 255 s->fail_mode = OFPROTO_FAIL_STANDALONE;
064af421
BP
256 s->datapath_id = 0;
257 s->mfr_desc = NULL;
258 s->hw_desc = NULL;
259 s->sw_desc = NULL;
260 s->serial_desc = NULL;
8abc4ed7 261 s->dp_desc = NULL;
7d674866 262 svec_init(&controllers);
064af421 263 svec_init(&s->snoops);
064af421 264 s->max_idle = 0;
064af421 265 svec_init(&s->netflow);
e3e9370b 266 svec_init(&s->ports);
064af421
BP
267 for (;;) {
268 int c;
269
270 c = getopt_long(argc, argv, short_options, long_options, NULL);
271 if (c == -1) {
272 break;
273 }
274
275 switch (c) {
276 case OPT_DATAPATH_ID:
76343538 277 if (!dpid_from_string(optarg, &s->datapath_id)) {
064af421 278 ovs_fatal(0, "argument to --datapath-id must be "
b123cc3c 279 "exactly 16 hex digits and may not be all-zero");
064af421
BP
280 }
281 break;
282
0c30c8f1 283 case OPT_MFR_DESC:
064af421
BP
284 s->mfr_desc = optarg;
285 break;
286
0c30c8f1 287 case OPT_HW_DESC:
064af421
BP
288 s->hw_desc = optarg;
289 break;
290
0c30c8f1 291 case OPT_SW_DESC:
064af421
BP
292 s->sw_desc = optarg;
293 break;
294
0c30c8f1 295 case OPT_SERIAL_DESC:
064af421
BP
296 s->serial_desc = optarg;
297 break;
298
8abc4ed7
JP
299 case OPT_DP_DESC:
300 s->dp_desc = optarg;
301 break;
302
064af421 303 case OPT_ACCEPT_VCONN:
76ce9432 304 controller_opts.accept_re = optarg;
064af421
BP
305 break;
306
307 case OPT_NO_RESOLV_CONF:
76ce9432 308 controller_opts.update_resolv_conf = false;
064af421
BP
309 break;
310
311 case OPT_FAIL_MODE:
33e01d3a 312 if (!strcmp(optarg, "open") || !strcmp(optarg, "standalone")) {
31681a5d 313 s->fail_mode = OFPROTO_FAIL_STANDALONE;
33e01d3a
BP
314 } else if (!strcmp(optarg, "closed")
315 || !strcmp(optarg, "secure")) {
31681a5d 316 s->fail_mode = OFPROTO_FAIL_SECURE;
064af421 317 } else {
33e01d3a
BP
318 ovs_fatal(0, "--fail argument must be \"standalone\" "
319 "or \"secure\"");
064af421
BP
320 }
321 break;
322
323 case OPT_INACTIVITY_PROBE:
76ce9432
BP
324 controller_opts.probe_interval = atoi(optarg);
325 if (controller_opts.probe_interval < 5) {
064af421
BP
326 ovs_fatal(0, "--inactivity-probe argument must be at least 5");
327 }
328 break;
329
330 case OPT_MAX_IDLE:
331 if (!strcmp(optarg, "permanent")) {
332 s->max_idle = OFP_FLOW_PERMANENT;
333 } else {
334 s->max_idle = atoi(optarg);
335 if (s->max_idle < 1 || s->max_idle > 65535) {
336 ovs_fatal(0, "--max-idle argument must be between 1 and "
337 "65535 or the word 'permanent'");
338 }
339 }
340 break;
341
342 case OPT_MAX_BACKOFF:
76ce9432
BP
343 controller_opts.max_backoff = atoi(optarg);
344 if (controller_opts.max_backoff < 1) {
064af421 345 ovs_fatal(0, "--max-backoff argument must be at least 1");
76ce9432
BP
346 } else if (controller_opts.max_backoff > 3600) {
347 controller_opts.max_backoff = 3600;
064af421
BP
348 }
349 break;
350
351 case OPT_RATE_LIMIT:
352 if (optarg) {
76ce9432
BP
353 controller_opts.rate_limit = atoi(optarg);
354 if (controller_opts.rate_limit < 1) {
064af421
BP
355 ovs_fatal(0, "--rate-limit argument must be at least 1");
356 }
357 } else {
76ce9432 358 controller_opts.rate_limit = 1000;
064af421
BP
359 }
360 break;
361
362 case OPT_BURST_LIMIT:
76ce9432
BP
363 controller_opts.burst_limit = atoi(optarg);
364 if (controller_opts.burst_limit < 1) {
064af421
BP
365 ovs_fatal(0, "--burst-limit argument must be at least 1");
366 }
367 break;
368
064af421 369 case OPT_OUT_OF_BAND:
76ce9432 370 controller_opts.band = OFPROTO_OUT_OF_BAND;
064af421
BP
371 break;
372
373 case OPT_IN_BAND:
76ce9432 374 controller_opts.band = OFPROTO_IN_BAND;
064af421
BP
375 break;
376
064af421
BP
377 case OPT_NETFLOW:
378 svec_add(&s->netflow, optarg);
379 break;
380
064af421 381 case 'l':
7d674866 382 svec_add(&controllers, optarg);
064af421
BP
383 break;
384
385 case OPT_SNOOP:
386 svec_add(&s->snoops, optarg);
387 break;
388
e3e9370b
BP
389 case OPT_PORTS:
390 svec_split(&s->ports, optarg, ",");
391 break;
392
064af421
BP
393 case 'h':
394 usage();
395
396 case 'V':
397 OVS_PRINT_VERSION(OFP_VERSION, OFP_VERSION);
398 exit(EXIT_SUCCESS);
399
400 DAEMON_OPTION_HANDLERS
401
402 VLOG_OPTION_HANDLERS
403
404 LEAK_CHECKER_OPTION_HANDLERS
405
406#ifdef HAVE_OPENSSL
fe55ad15 407 STREAM_SSL_OPTION_HANDLERS
064af421
BP
408
409 case OPT_BOOTSTRAP_CA_CERT:
fe55ad15 410 stream_ssl_set_ca_cert_file(optarg, true);
064af421
BP
411 break;
412#endif
413
414 case '?':
415 exit(EXIT_FAILURE);
416
417 default:
418 abort();
419 }
420 }
421 free(short_options);
422
423 argc -= optind;
424 argv += optind;
67f6bdd7
BP
425 if (argc < 1) {
426 ovs_fatal(0, "need at least one non-option arguments; "
064af421
BP
427 "use --help for usage");
428 }
429
064af421 430 /* Set accept_controller_regex. */
76ce9432
BP
431 if (!controller_opts.accept_re) {
432 controller_opts.accept_re
fe55ad15 433 = stream_ssl_is_configured() ? "^ssl:.*" : "^tcp:.*";
064af421
BP
434 }
435
064af421 436 /* Rate limiting. */
76ce9432 437 if (controller_opts.rate_limit && controller_opts.rate_limit < 100) {
79c9f2ee 438 VLOG_WARN("Rate limit set to unusually low value %d",
76ce9432
BP
439 controller_opts.rate_limit);
440 }
441
442 /* Local vconns. */
443 dp_parse_name(argv[0], &s->dp_name, &s->dp_type);
444
7d674866
BP
445 /* Figure out controller names. */
446 if (!controllers.n) {
447 svec_add_nocopy(&controllers,
448 xasprintf("punix:%s/%s.mgmt", ovs_rundir, s->dp_name));
449 }
450 for (i = 1; i < argc; i++) {
451 svec_add(&controllers, argv[i]);
452 }
453 if (argc < 2) {
454 svec_add(&controllers, "discover");
455 }
456
457 /* Set up controllers. */
458 s->n_controllers = controllers.n;
76ce9432
BP
459 s->controllers = xmalloc(s->n_controllers * sizeof *s->controllers);
460 if (argc > 1) {
76ce9432
BP
461 for (i = 0; i < s->n_controllers; i++) {
462 s->controllers[i] = controller_opts;
7d674866 463 s->controllers[i].target = controllers.names[i];
76ce9432 464 }
76ce9432
BP
465 }
466
467 /* Sanity check. */
468 if (controller_opts.band == OFPROTO_OUT_OF_BAND) {
76ce9432
BP
469 for (i = 0; i < s->n_controllers; i++) {
470 if (!strcmp(s->controllers[i].target, "discover")) {
471 ovs_fatal(0, "Cannot perform discovery with out-of-band "
472 "control");
473 }
474 }
064af421
BP
475 }
476}
477
478static void
479usage(void)
480{
481 printf("%s: an OpenFlow switch implementation.\n"
76ce9432 482 "usage: %s [OPTIONS] DATAPATH [CONTROLLER...]\n"
064af421 483 "DATAPATH is a local datapath (e.g. \"dp0\").\n"
76ce9432
BP
484 "Each CONTROLLER is an active OpenFlow connection method. If\n"
485 "none is given, ovs-openflowd performs controller discovery.\n",
064af421
BP
486 program_name, program_name);
487 vconn_usage(true, true, true);
488 printf("\nOpenFlow options:\n"
489 " -d, --datapath-id=ID Use ID as the OpenFlow switch ID\n"
b123cc3c 490 " (ID must consist of 16 hex digits)\n"
0c30c8f1
JP
491 " --mfr-desc=MFR Identify manufacturer as MFR\n"
492 " --hw-desc=HW Identify hardware as HW\n"
493 " --sw-desc=SW Identify software as SW\n"
494 " --serial-desc=SERIAL Identify serial number as SERIAL\n"
495 " --dp-desc=DP_DESC Identify dp description as DP_DESC\n"
064af421
BP
496 "\nController discovery options:\n"
497 " --accept-vconn=REGEX accept matching discovered controllers\n"
498 " --no-resolv-conf do not update /etc/resolv.conf\n"
499 "\nNetworking options:\n"
500 " --fail=open|closed when controller connection fails:\n"
501 " closed: drop all packets\n"
502 " open (default): act as learning switch\n"
503 " --inactivity-probe=SECS time between inactivity probes\n"
8cd4882f 504 " --max-idle=SECS max idle for flows set up by switch\n"
064af421 505 " --max-backoff=SECS max time between controller connection\n"
c9aaa877 506 " attempts (default: 8 seconds)\n"
064af421
BP
507 " -l, --listen=METHOD allow management connections on METHOD\n"
508 " (a passive OpenFlow connection method)\n"
509 " --snoop=METHOD allow controller snooping on METHOD\n"
510 " (a passive OpenFlow connection method)\n"
511 " --out-of-band controller connection is out-of-band\n"
512 " --netflow=HOST:PORT configure NetFlow output target\n"
513 "\nRate-limiting of \"packet-in\" messages to the controller:\n"
514 " --rate-limit[=PACKETS] max rate, in packets/s (default: 1000)\n"
67b732e8 515 " --burst-limit=BURST limit on packet credit for idle time\n");
064af421
BP
516 daemon_usage();
517 vlog_usage();
518 printf("\nOther options:\n"
519 " -h, --help display this help message\n"
520 " -V, --version display version information\n");
521 leak_checker_usage();
522 exit(EXIT_SUCCESS);
523}