2 * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <netinet/in.h>
27 #include "command-line.h"
33 #include "leak-checker.h"
37 #include "ofproto/ofproto.h"
38 #include "openflow/openflow.h"
40 #include "poll-loop.h"
42 #include "stream-ssl.h"
49 VLOG_DEFINE_THIS_MODULE(openflowd
);
51 /* Settings that may be configured by the user. */
53 const char *unixctl_path
; /* File name for unixctl socket. */
55 /* Controller configuration. */
56 struct ofproto_controller
*controllers
;
58 enum ofproto_fail_mode fail_mode
;
59 bool run_forever
; /* Continue running even with no controller? */
62 uint64_t datapath_id
; /* Datapath ID. */
63 char *dp_name
; /* Name of local datapath. */
64 char *dp_type
; /* Type of local datapath. */
65 struct sset ports
; /* Set of ports to add to datapath (if any). */
67 /* Description strings. */
68 const char *mfr_desc
; /* Manufacturer. */
69 const char *hw_desc
; /* Hardware. */
70 const char *sw_desc
; /* Software version. */
71 const char *serial_desc
; /* Serial number. */
72 const char *dp_desc
; /* Datapath description. */
74 /* Related vconns and network devices. */
75 struct sset snoops
; /* Listen for controller snooping conns. */
77 /* Failure behavior. */
78 int max_idle
; /* Idle time for flows in fail-open mode. */
81 struct sset netflow
; /* NetFlow targets. */
84 static unixctl_cb_func ovs_openflowd_exit
;
86 static void parse_options(int argc
, char *argv
[], struct ofsettings
*);
87 static void usage(void) NO_RETURN
;
90 main(int argc
, char *argv
[])
92 struct unixctl_server
*unixctl
;
93 struct ofproto
*ofproto
;
96 struct netflow_options nf_options
;
100 proctitle_init(argc
, argv
);
101 set_program_name(argv
[0]);
102 parse_options(argc
, argv
, &s
);
103 signal(SIGPIPE
, SIG_IGN
);
107 /* Start listening for ovs-appctl requests. */
108 error
= unixctl_server_create(s
.unixctl_path
, &unixctl
);
113 unixctl_command_register("exit", ovs_openflowd_exit
, &exiting
);
115 VLOG_INFO("Open vSwitch version %s", VERSION BUILDNR
);
116 VLOG_INFO("OpenFlow protocol version 0x%02x", OFP_VERSION
);
118 error
= ofproto_create(s
.dp_name
, s
.dp_type
, &ofproto
);
120 VLOG_FATAL("could not initialize OpenFlow switch (%s)",
124 /* Add ports to the datapath if requested by the user. */
125 SSET_FOR_EACH (port
, &s
.ports
) {
126 struct netdev
*netdev
;
128 error
= netdev_open_default(port
, &netdev
);
130 VLOG_FATAL("%s: failed to open network device (%s)",
131 port
, strerror(error
));
134 error
= ofproto_port_add(ofproto
, netdev
, NULL
);
136 VLOG_FATAL("failed to add %s as a port (%s)",
137 port
, strerror(error
));
140 netdev_close(netdev
);
143 /* Configure OpenFlow switch. */
145 ofproto_set_datapath_id(ofproto
, s
.datapath_id
);
147 ofproto_set_desc(ofproto
, s
.mfr_desc
, s
.hw_desc
, s
.sw_desc
,
148 s
.serial_desc
, s
.dp_desc
);
149 error
= ofproto_set_snoops(ofproto
, &s
.snoops
);
151 VLOG_FATAL("failed to configure controller snooping connections (%s)",
154 memset(&nf_options
, 0, sizeof nf_options
);
155 nf_options
.collectors
= s
.netflow
;
156 error
= ofproto_set_netflow(ofproto
, &nf_options
);
158 VLOG_FATAL("failed to configure NetFlow collectors (%s)",
161 ofproto_set_controllers(ofproto
, s
.controllers
, s
.n_controllers
);
162 ofproto_set_fail_mode(ofproto
, s
.fail_mode
);
164 daemonize_complete();
167 while (!exiting
&& (s
.run_forever
|| ofproto_is_alive(ofproto
))) {
168 error
= ofproto_run(ofproto
);
170 VLOG_FATAL("unrecoverable datapath error (%s)", strerror(error
));
172 unixctl_server_run(unixctl
);
175 ofproto_wait(ofproto
);
176 unixctl_server_wait(unixctl
);
179 poll_immediate_wake();
184 ofproto_destroy(ofproto
);
190 ovs_openflowd_exit(struct unixctl_conn
*conn
, const char *args OVS_UNUSED
,
193 bool *exiting
= exiting_
;
195 unixctl_command_reply(conn
, 200, NULL
);
198 /* User interface. */
200 /* Breaks 'ports' apart at commas and adds each resulting word to 'ports'. */
202 parse_ports(const char *s_
, struct sset
*ports
)
204 char *s
= xstrdup(s_
);
205 char *save_ptr
= NULL
;
208 for (token
= strtok_r(s
, ",", &save_ptr
); token
!= NULL
;
209 token
= strtok_r(NULL
, ",", &save_ptr
)) {
210 sset_add(ports
, token
);
216 parse_options(int argc
, char *argv
[], struct ofsettings
*s
)
219 OPT_DATAPATH_ID
= UCHAR_MAX
+ 1,
227 OPT_INACTIVITY_PROBE
,
233 OPT_BOOTSTRAP_CA_CERT
,
241 LEAK_CHECKER_OPTION_ENUMS
,
244 static struct option long_options
[] = {
245 {"datapath-id", required_argument
, 0, OPT_DATAPATH_ID
},
246 {"mfr-desc", required_argument
, 0, OPT_MFR_DESC
},
247 {"hw-desc", required_argument
, 0, OPT_HW_DESC
},
248 {"sw-desc", required_argument
, 0, OPT_SW_DESC
},
249 {"serial-desc", required_argument
, 0, OPT_SERIAL_DESC
},
250 {"dp-desc", required_argument
, 0, OPT_DP_DESC
},
251 {"config", required_argument
, 0, 'F'},
252 {"br-name", required_argument
, 0, OPT_BR_NAME
},
253 {"fail", required_argument
, 0, OPT_FAIL_MODE
},
254 {"inactivity-probe", required_argument
, 0, OPT_INACTIVITY_PROBE
},
255 {"max-idle", required_argument
, 0, OPT_MAX_IDLE
},
256 {"max-backoff", required_argument
, 0, OPT_MAX_BACKOFF
},
257 {"listen", required_argument
, 0, 'l'},
258 {"snoop", required_argument
, 0, OPT_SNOOP
},
259 {"rate-limit", optional_argument
, 0, OPT_RATE_LIMIT
},
260 {"burst-limit", required_argument
, 0, OPT_BURST_LIMIT
},
261 {"out-of-band", no_argument
, 0, OPT_OUT_OF_BAND
},
262 {"in-band", no_argument
, 0, OPT_IN_BAND
},
263 {"netflow", required_argument
, 0, OPT_NETFLOW
},
264 {"ports", required_argument
, 0, OPT_PORTS
},
265 {"unixctl", required_argument
, 0, OPT_UNIXCTL
},
266 {"enable-dummy", no_argument
, 0, OPT_ENABLE_DUMMY
},
267 {"verbose", optional_argument
, 0, 'v'},
268 {"help", no_argument
, 0, 'h'},
269 {"version", no_argument
, 0, 'V'},
272 LEAK_CHECKER_LONG_OPTIONS
,
274 STREAM_SSL_LONG_OPTIONS
275 {"bootstrap-ca-cert", required_argument
, 0, OPT_BOOTSTRAP_CA_CERT
},
279 char *short_options
= long_options_to_short_options(long_options
);
280 struct ofproto_controller controller_opts
;
281 struct sset controllers
;
285 /* Set defaults that we can figure out before parsing options. */
286 controller_opts
.target
= NULL
;
287 controller_opts
.max_backoff
= 8;
288 controller_opts
.probe_interval
= 5;
289 controller_opts
.band
= OFPROTO_IN_BAND
;
290 controller_opts
.rate_limit
= 0;
291 controller_opts
.burst_limit
= 0;
292 s
->unixctl_path
= NULL
;
293 s
->fail_mode
= OFPROTO_FAIL_STANDALONE
;
298 s
->serial_desc
= NULL
;
300 sset_init(&controllers
);
301 sset_init(&s
->snoops
);
303 sset_init(&s
->netflow
);
304 sset_init(&s
->ports
);
308 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
314 case OPT_DATAPATH_ID
:
315 if (!dpid_from_string(optarg
, &s
->datapath_id
)) {
316 VLOG_FATAL("argument to --datapath-id must be exactly 16 hex "
317 "digits and may not be all-zero");
322 s
->mfr_desc
= optarg
;
333 case OPT_SERIAL_DESC
:
334 s
->serial_desc
= optarg
;
342 if (!strcmp(optarg
, "open") || !strcmp(optarg
, "standalone")) {
343 s
->fail_mode
= OFPROTO_FAIL_STANDALONE
;
344 } else if (!strcmp(optarg
, "closed")
345 || !strcmp(optarg
, "secure")) {
346 s
->fail_mode
= OFPROTO_FAIL_SECURE
;
348 VLOG_FATAL("--fail argument must be \"standalone\" "
353 case OPT_INACTIVITY_PROBE
:
354 controller_opts
.probe_interval
= atoi(optarg
);
355 if (controller_opts
.probe_interval
< 5) {
356 VLOG_FATAL("--inactivity-probe argument must be at least 5");
361 if (!strcmp(optarg
, "permanent")) {
362 s
->max_idle
= OFP_FLOW_PERMANENT
;
364 s
->max_idle
= atoi(optarg
);
365 if (s
->max_idle
< 1 || s
->max_idle
> 65535) {
366 VLOG_FATAL("--max-idle argument must be between 1 and "
367 "65535 or the word 'permanent'");
372 case OPT_MAX_BACKOFF
:
373 controller_opts
.max_backoff
= atoi(optarg
);
374 if (controller_opts
.max_backoff
< 1) {
375 VLOG_FATAL("--max-backoff argument must be at least 1");
376 } else if (controller_opts
.max_backoff
> 3600) {
377 controller_opts
.max_backoff
= 3600;
383 controller_opts
.rate_limit
= atoi(optarg
);
384 if (controller_opts
.rate_limit
< 1) {
385 VLOG_FATAL("--rate-limit argument must be at least 1");
388 controller_opts
.rate_limit
= 1000;
392 case OPT_BURST_LIMIT
:
393 controller_opts
.burst_limit
= atoi(optarg
);
394 if (controller_opts
.burst_limit
< 1) {
395 VLOG_FATAL("--burst-limit argument must be at least 1");
399 case OPT_OUT_OF_BAND
:
400 controller_opts
.band
= OFPROTO_OUT_OF_BAND
;
404 controller_opts
.band
= OFPROTO_IN_BAND
;
408 sset_add(&s
->netflow
, optarg
);
412 sset_add(&controllers
, optarg
);
416 sset_add(&s
->snoops
, optarg
);
420 parse_ports(optarg
, &s
->ports
);
424 s
->unixctl_path
= optarg
;
427 case OPT_ENABLE_DUMMY
:
435 OVS_PRINT_VERSION(OFP_VERSION
, OFP_VERSION
);
438 DAEMON_OPTION_HANDLERS
442 LEAK_CHECKER_OPTION_HANDLERS
445 STREAM_SSL_OPTION_HANDLERS
447 case OPT_BOOTSTRAP_CA_CERT
:
448 stream_ssl_set_ca_cert_file(optarg
, true);
464 VLOG_FATAL("need at least two non-option arguments; "
465 "use --help for usage");
469 if (controller_opts
.rate_limit
&& controller_opts
.rate_limit
< 100) {
470 VLOG_WARN("Rate limit set to unusually low value %d",
471 controller_opts
.rate_limit
);
475 dp_parse_name(argv
[0], &s
->dp_name
, &s
->dp_type
);
477 /* Figure out controller names. */
478 s
->run_forever
= false;
479 if (sset_is_empty(&controllers
)) {
480 sset_add_and_free(&controllers
, xasprintf("punix:%s/%s.mgmt",
481 ovs_rundir(), s
->dp_name
));
483 for (i
= 1; i
< argc
; i
++) {
484 if (!strcmp(argv
[i
], "none")) {
485 s
->run_forever
= true;
487 sset_add(&controllers
, argv
[i
]);
491 /* Set up controllers. */
492 s
->n_controllers
= sset_count(&controllers
);
493 s
->controllers
= xmalloc(s
->n_controllers
* sizeof *s
->controllers
);
495 SSET_FOR_EACH (name
, &controllers
) {
496 s
->controllers
[i
] = controller_opts
;
497 s
->controllers
[i
].target
= xstrdup(name
);
500 sset_destroy(&controllers
);
506 printf("%s: an OpenFlow switch implementation.\n"
507 "usage: %s [OPTIONS] [TYPE@]DATAPATH CONTROLLER...\n"
508 "where DATAPATH is a local datapath (e.g. \"dp0\")\n"
509 "optionally with an explicit TYPE (default: \"system\").\n"
510 "Each CONTROLLER is an active OpenFlow connection method.\n",
511 program_name
, program_name
);
512 vconn_usage(true, true, true);
513 printf("\nOpenFlow options:\n"
514 " -d, --datapath-id=ID Use ID as the OpenFlow switch ID\n"
515 " (ID must consist of 16 hex digits)\n"
516 " --mfr-desc=MFR Identify manufacturer as MFR\n"
517 " --hw-desc=HW Identify hardware as HW\n"
518 " --sw-desc=SW Identify software as SW\n"
519 " --serial-desc=SERIAL Identify serial number as SERIAL\n"
520 " --dp-desc=DP_DESC Identify dp description as DP_DESC\n"
521 "\nNetworking options:\n"
522 " --fail=open|closed when controller connection fails:\n"
523 " closed: drop all packets\n"
524 " open (default): act as learning switch\n"
525 " --inactivity-probe=SECS time between inactivity probes\n"
526 " --max-idle=SECS max idle for flows set up by switch\n"
527 " --max-backoff=SECS max time between controller connection\n"
528 " attempts (default: 8 seconds)\n"
529 " -l, --listen=METHOD allow management connections on METHOD\n"
530 " (a passive OpenFlow connection method)\n"
531 " --snoop=METHOD allow controller snooping on METHOD\n"
532 " (a passive OpenFlow connection method)\n"
533 " --out-of-band controller connection is out-of-band\n"
534 " --netflow=HOST:PORT configure NetFlow output target\n"
535 "\nRate-limiting of \"packet-in\" messages to the controller:\n"
536 " --rate-limit[=PACKETS] max rate, in packets/s (default: 1000)\n"
537 " --burst-limit=BURST limit on packet credit for idle time\n");
540 printf("\nOther options:\n"
541 " --unixctl=SOCKET override default control socket name\n"
542 " -h, --help display this help message\n"
543 " -V, --version display version information\n");
544 leak_checker_usage();