Implement new OpenFlow "switch statistics" feature.
[sliver-openvswitch.git] / secchan / secchan.c
1 /* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
2  * Junior University
3  *
4  * We are making the OpenFlow specification and associated documentation
5  * (Software) available for public use and benefit with the expectation
6  * that others will use, modify and enhance the Software and contribute
7  * those enhancements back to the community. However, since we would
8  * like to make the Software available for broadest use, with as few
9  * restrictions as possible permission is hereby granted, free of
10  * charge, to any person obtaining a copy of this Software to deal in
11  * the Software under the copyrights without restriction, including
12  * without limitation the rights to use, copy, modify, merge, publish,
13  * distribute, sublicense, and/or sell copies of the Software, and to
14  * permit persons to whom the Software is furnished to do so, subject to
15  * the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be
18  * included in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27  * SOFTWARE.
28  *
29  * The name and trademarks of copyright holder(s) may NOT be used in
30  * advertising or publicity pertaining to the Software or any
31  * derivatives without specific, written prior permission.
32  */
33
34 #include <config.h>
35 #include <assert.h>
36 #include <errno.h>
37 #include <getopt.h>
38 #include <inttypes.h>
39 #include <netinet/in.h>
40 #include <poll.h>
41 #include <regex.h>
42 #include <stdlib.h>
43 #include <signal.h>
44 #include <string.h>
45 #include <time.h>
46 #include <unistd.h>
47
48 #include "buffer.h"
49 #include "command-line.h"
50 #include "compiler.h"
51 #include "daemon.h"
52 #include "dhcp.h"
53 #include "dhcp-client.h"
54 #include "dynamic-string.h"
55 #include "fault.h"
56 #include "flow.h"
57 #include "learning-switch.h"
58 #include "list.h"
59 #include "mac-learning.h"
60 #include "netdev.h"
61 #include "openflow.h"
62 #include "packets.h"
63 #include "poll-loop.h"
64 #include "rconn.h"
65 #include "timeval.h"
66 #include "util.h"
67 #include "vconn-ssl.h"
68 #include "vconn.h"
69 #include "vlog-socket.h"
70
71 #include "vlog.h"
72 #define THIS_MODULE VLM_secchan
73
74 /* Behavior when the connection to the controller fails. */
75 enum fail_mode {
76     FAIL_OPEN,                  /* Act as learning switch. */
77     FAIL_CLOSED                 /* Drop all packets. */
78 };
79
80 /* Settings that may be configured by the user. */
81 struct settings {
82     /* Overall mode of operation. */
83     bool discovery;           /* Discover the controller automatically? */
84     bool in_band;             /* Connect to controller in-band? */
85
86     /* Related vconns and network devices. */
87     const char *nl_name;        /* Local datapath (must be "nl:" vconn). */
88     char *of_name;              /* ofX network device name. */
89     const char *controller_name; /* Controller (if not discovery mode). */
90     const char *listen_vconn_name; /* Listens for mgmt connections. */
91
92     /* Failure behavior. */
93     enum fail_mode fail_mode; /* Act as learning switch if no controller? */
94     int max_idle;             /* Idle time for flows in fail-open mode. */
95     int probe_interval;       /* # seconds idle before sending echo request. */
96     int max_backoff;          /* Max # seconds between connection attempts. */
97
98     /* Packet-in rate-limiting. */
99     int rate_limit;           /* Tokens added to bucket per second. */
100     int burst_limit;          /* Maximum number token bucket size. */
101
102     /* Discovery behavior. */
103     regex_t accept_controller_regex;  /* Controller vconns to accept. */
104     const char *accept_controller_re; /* String version of regex. */
105     bool update_resolv_conf;          /* Update /etc/resolv.conf? */
106 };
107
108 struct half {
109     struct rconn *rconn;
110     struct buffer *rxbuf;
111     int n_txq;                  /* No. of packets queued for tx on 'rconn'. */
112 };
113
114 struct relay {
115     struct list node;
116
117 #define HALF_LOCAL 0
118 #define HALF_REMOTE 1
119     struct half halves[2];
120
121     bool is_mgmt_conn;
122 };
123
124 struct hook {
125     bool (*packet_cb)(struct relay *, int half, void *aux);
126     void (*periodic_cb)(void *aux);
127     void (*wait_cb)(void *aux);
128     void *aux;
129 };
130
131 static void parse_options(int argc, char *argv[], struct settings *);
132 static void usage(void) NO_RETURN;
133
134 static struct relay *relay_create(struct rconn *local, struct rconn *remote,
135                                   bool is_mgmt_conn);
136 static struct relay *relay_accept(const struct settings *, struct vconn *);
137 static void relay_run(struct relay *, const struct hook[], size_t n_hooks);
138 static void relay_wait(struct relay *);
139 static void relay_destroy(struct relay *);
140
141 static struct hook make_hook(bool (*packet_cb)(struct relay *, int, void *),
142                              void (*periodic_cb)(void *),
143                              void (*wait_cb)(void *),
144                              void *aux);
145
146 struct switch_status;
147 struct status_reply;
148 static struct hook switch_status_hook_create(const struct settings *,
149                                              struct switch_status **);
150 static void switch_status_register_category(struct switch_status *,
151                                             const char *category,
152                                             void (*cb)(struct status_reply *,
153                                                        void *aux),
154                                             void *aux);
155 static void status_reply_put(struct status_reply *, const char *, ...)
156     PRINTF_FORMAT(2, 3);
157
158 static void rconn_status_cb(struct status_reply *, void *rconn_);
159
160 static struct discovery *discovery_init(const struct settings *,
161                                         struct switch_status *);
162 static void discovery_question_connectivity(struct discovery *);
163 static bool discovery_run(struct discovery *, char **controller_name);
164 static void discovery_wait(struct discovery *);
165
166 static struct hook in_band_hook_create(const struct settings *,
167                                        struct switch_status *,
168                                        struct rconn *remote);
169 static struct hook fail_open_hook_create(const struct settings *,
170                                          struct switch_status *,
171                                          struct rconn *local,
172                                          struct rconn *remote);
173 static struct hook rate_limit_hook_create(const struct settings *,
174                                           struct switch_status *,
175                                           struct rconn *local,
176                                           struct rconn *remote);
177
178
179 static void modify_dhcp_request(struct dhcp_msg *, void *aux);
180 static bool validate_dhcp_offer(const struct dhcp_msg *, void *aux);
181
182 int
183 main(int argc, char *argv[])
184 {
185     struct settings s;
186
187     struct list relays = LIST_INITIALIZER(&relays);
188
189     struct hook hooks[8];
190     size_t n_hooks = 0;
191
192     struct rconn *local_rconn, *remote_rconn;
193     struct vconn *listen_vconn;
194     struct relay *controller_relay;
195     struct discovery *discovery;
196     struct switch_status *switch_status;
197     int retval;
198
199     set_program_name(argv[0]);
200     register_fault_handlers();
201     time_init();
202     vlog_init();
203     parse_options(argc, argv, &s);
204     signal(SIGPIPE, SIG_IGN);
205
206     /* Start listening for management connections. */
207     if (s.listen_vconn_name) {
208         retval = vconn_open(s.listen_vconn_name, &listen_vconn);
209         if (retval && retval != EAGAIN) {
210             fatal(retval, "opening %s", s.listen_vconn_name);
211         }
212         if (!vconn_is_passive(listen_vconn)) {
213             fatal(0, "%s is not a passive vconn", s.listen_vconn_name);
214         }
215     } else {
216         listen_vconn = NULL;
217     }
218
219     /* Initialize switch status hook. */
220     hooks[n_hooks++] = switch_status_hook_create(&s, &switch_status);
221
222     /* Start controller discovery. */
223     discovery = s.discovery ? discovery_init(&s, switch_status) : NULL;
224
225     /* Start listening for vlogconf requests. */
226     retval = vlog_server_listen(NULL, NULL);
227     if (retval) {
228         fatal(retval, "Could not listen for vlog connections");
229     }
230
231     daemonize();
232
233     VLOG_WARN("OpenFlow reference implementation version %s", VERSION);
234     VLOG_WARN("OpenFlow protocol version 0x%02x", OFP_VERSION);
235
236     /* Connect to datapath. */
237     local_rconn = rconn_create(0, s.max_backoff);
238     rconn_connect(local_rconn, s.nl_name);
239     switch_status_register_category(switch_status, "local",
240                                     rconn_status_cb, local_rconn);
241
242     /* Connect to controller. */
243     remote_rconn = rconn_create(s.probe_interval, s.max_backoff);
244     if (s.controller_name) {
245         retval = rconn_connect(remote_rconn, s.controller_name);
246         if (retval == EAFNOSUPPORT) {
247             fatal(0, "No support for %s vconn", s.controller_name);
248         }
249     }
250     switch_status_register_category(switch_status, "remote",
251                                     rconn_status_cb, remote_rconn);
252
253     /* Start relaying. */
254     controller_relay = relay_create(local_rconn, remote_rconn, false);
255     list_push_back(&relays, &controller_relay->node);
256
257     /* Set up hooks. */
258     if (s.in_band) {
259         hooks[n_hooks++] = in_band_hook_create(&s, switch_status,
260                                                remote_rconn);
261     }
262     if (s.fail_mode == FAIL_OPEN) {
263         hooks[n_hooks++] = fail_open_hook_create(&s, switch_status,
264                                                  local_rconn, remote_rconn);
265     }
266     if (s.rate_limit) {
267         hooks[n_hooks++] = rate_limit_hook_create(&s, switch_status,
268                                                   local_rconn, remote_rconn);
269     }
270     assert(n_hooks <= ARRAY_SIZE(hooks));
271
272     for (;;) {
273         struct relay *r, *n;
274         size_t i;
275
276         /* Do work. */
277         LIST_FOR_EACH_SAFE (r, n, struct relay, node, &relays) {
278             relay_run(r, hooks, n_hooks);
279         }
280         if (listen_vconn) {
281             for (;;) {
282                 struct relay *r = relay_accept(&s, listen_vconn);
283                 if (!r) {
284                     break;
285                 }
286                 list_push_back(&relays, &r->node);
287             }
288         }
289         for (i = 0; i < n_hooks; i++) {
290             if (hooks[i].periodic_cb) {
291                 hooks[i].periodic_cb(hooks[i].aux);
292             }
293         }
294         if (s.discovery) {
295             char *controller_name;
296             if (rconn_is_connectivity_questionable(remote_rconn)) {
297                 discovery_question_connectivity(discovery);
298             }
299             if (discovery_run(discovery, &controller_name)) {
300                 if (controller_name) {
301                     rconn_connect(remote_rconn, controller_name);
302                 } else {
303                     rconn_disconnect(remote_rconn);
304                 }
305             }
306         }
307
308         /* Wait for something to happen. */
309         LIST_FOR_EACH (r, struct relay, node, &relays) {
310             relay_wait(r);
311         }
312         if (listen_vconn) {
313             vconn_accept_wait(listen_vconn);
314         }
315         for (i = 0; i < n_hooks; i++) {
316             if (hooks[i].wait_cb) {
317                 hooks[i].wait_cb(hooks[i].aux);
318             }
319         }
320         if (discovery) {
321             discovery_wait(discovery);
322         }
323         poll_block();
324     }
325
326     return 0;
327 }
328
329 static struct hook
330 make_hook(bool (*packet_cb)(struct relay *, int half, void *aux),
331           void (*periodic_cb)(void *aux),
332           void (*wait_cb)(void *aux),
333           void *aux)
334 {
335     struct hook h;
336     h.packet_cb = packet_cb;
337     h.periodic_cb = periodic_cb;
338     h.wait_cb = wait_cb;
339     h.aux = aux;
340     return h;
341 }
342 \f
343 /* OpenFlow message relaying. */
344
345 static struct relay *
346 relay_accept(const struct settings *s, struct vconn *listen_vconn)
347 {
348     struct vconn *new_remote, *new_local;
349     char *nl_name_without_subscription;
350     struct rconn *r1, *r2;
351     int retval;
352
353     retval = vconn_accept(listen_vconn, &new_remote);
354     if (retval) {
355         if (retval != EAGAIN) {
356             VLOG_WARN("accept failed (%s)", strerror(retval));
357         }
358         return NULL;
359     }
360
361     /* nl:123 or nl:123:1 opens a netlink connection to local datapath 123.  We
362      * only accept the former syntax in main().
363      *
364      * nl:123:0 opens a netlink connection to local datapath 123 without
365      * obtaining a subscription for ofp_packet_in or ofp_flow_expired
366      * messages.*/
367     nl_name_without_subscription = xasprintf("%s:0", s->nl_name);
368     retval = vconn_open(nl_name_without_subscription, &new_local);
369     if (retval) {
370         VLOG_ERR("could not connect to %s (%s)",
371                  nl_name_without_subscription, strerror(retval));
372         vconn_close(new_remote);
373         free(nl_name_without_subscription);
374         return NULL;
375     }
376
377     /* Create and return relay. */
378     r1 = rconn_create(0, 0);
379     rconn_connect_unreliably(r1, nl_name_without_subscription, new_local);
380     free(nl_name_without_subscription);
381
382     r2 = rconn_create(0, 0);
383     rconn_connect_unreliably(r2, "passive", new_remote);
384
385     return relay_create(r1, r2, true);
386 }
387
388 static struct relay *
389 relay_create(struct rconn *local, struct rconn *remote, bool is_mgmt_conn)
390 {
391     struct relay *r = xcalloc(1, sizeof *r);
392     r->halves[HALF_LOCAL].rconn = local;
393     r->halves[HALF_REMOTE].rconn = remote;
394     r->is_mgmt_conn = is_mgmt_conn;
395     return r;
396 }
397
398 static void
399 relay_run(struct relay *r, const struct hook hooks[], size_t n_hooks)
400 {
401     int iteration;
402     int i;
403
404     for (i = 0; i < 2; i++) {
405         rconn_run(r->halves[i].rconn);
406     }
407
408     /* Limit the number of iterations to prevent other tasks from starving. */
409     for (iteration = 0; iteration < 50; iteration++) {
410         bool progress = false;
411         for (i = 0; i < 2; i++) {
412             struct half *this = &r->halves[i];
413             struct half *peer = &r->halves[!i];
414
415             if (!this->rxbuf) {
416                 this->rxbuf = rconn_recv(this->rconn);
417                 if (this->rxbuf) {
418                     const struct hook *h;
419                     for (h = hooks; h < &hooks[n_hooks]; h++) {
420                         if (h->packet_cb(r, i, h->aux)) {
421                             buffer_delete(this->rxbuf);
422                             this->rxbuf = NULL;
423                             progress = true;
424                             break;
425                         }
426                     }
427                 }
428             }
429
430             if (this->rxbuf && !this->n_txq) {
431                 int retval = rconn_send(peer->rconn, this->rxbuf,
432                                         &this->n_txq);
433                 if (retval != EAGAIN) {
434                     if (!retval) {
435                         progress = true;
436                     } else {
437                         buffer_delete(this->rxbuf);
438                     }
439                     this->rxbuf = NULL;
440                 }
441             }
442         }
443         if (!progress) {
444             break;
445         }
446     }
447
448     if (r->is_mgmt_conn) {
449         for (i = 0; i < 2; i++) {
450             struct half *this = &r->halves[i];
451             if (!rconn_is_alive(this->rconn)) {
452                 relay_destroy(r);
453                 return;
454             }
455         }
456     }
457 }
458
459 static void
460 relay_wait(struct relay *r)
461 {
462     int i;
463
464     for (i = 0; i < 2; i++) {
465         struct half *this = &r->halves[i];
466
467         rconn_run_wait(this->rconn);
468         if (!this->rxbuf) {
469             rconn_recv_wait(this->rconn);
470         }
471     }
472 }
473
474 static void
475 relay_destroy(struct relay *r)
476 {
477     int i;
478
479     list_remove(&r->node);
480     for (i = 0; i < 2; i++) {
481         struct half *this = &r->halves[i];
482         rconn_destroy(this->rconn);
483         buffer_delete(this->rxbuf);
484     }
485     free(r);
486 }
487 \f
488 /* In-band control. */
489
490 struct in_band_data {
491     const struct settings *s;
492     struct mac_learning *ml;
493     struct netdev *of_device;
494     struct rconn *controller;
495     uint8_t mac[ETH_ADDR_LEN];
496     int n_queued;
497 };
498
499 static void
500 queue_tx(struct rconn *rc, struct in_band_data *in_band, struct buffer *b)
501 {
502     rconn_send_with_limit(rc, b, &in_band->n_queued, 10);
503 }
504
505 static const uint8_t *
506 get_controller_mac(struct in_band_data *in_band)
507 {
508     static uint32_t ip, last_nonzero_ip;
509     static uint8_t mac[ETH_ADDR_LEN], last_nonzero_mac[ETH_ADDR_LEN];
510     static time_t next_refresh = 0;
511
512     uint32_t last_ip = ip;
513
514     time_t now = time_now();
515
516     ip = rconn_get_ip(in_band->controller);
517     if (last_ip != ip || !next_refresh || now >= next_refresh) {
518         bool have_mac;
519
520         /* Look up MAC address. */
521         memset(mac, 0, sizeof mac);
522         if (ip) {
523             int retval = netdev_arp_lookup(in_band->of_device, ip, mac);
524             if (retval) {
525                 VLOG_DBG("cannot look up controller hw address ("IP_FMT"): %s",
526                          IP_ARGS(&ip), strerror(retval));
527             }
528         }
529         have_mac = !eth_addr_is_zero(mac);
530
531         /* Log changes in IP, MAC addresses. */
532         if (ip && ip != last_nonzero_ip) {
533             VLOG_DBG("controller IP address changed from "IP_FMT
534                      " to "IP_FMT, IP_ARGS(&last_nonzero_ip), IP_ARGS(&ip));
535             last_nonzero_ip = ip;
536         }
537         if (have_mac && memcmp(last_nonzero_mac, mac, ETH_ADDR_LEN)) {
538             VLOG_DBG("controller MAC address changed from "ETH_ADDR_FMT" to "
539                      ETH_ADDR_FMT,
540                      ETH_ADDR_ARGS(last_nonzero_mac), ETH_ADDR_ARGS(mac));
541             memcpy(last_nonzero_mac, mac, ETH_ADDR_LEN);
542         }
543
544         /* Schedule next refresh.
545          *
546          * If we have an IP address but not a MAC address, then refresh
547          * quickly, since we probably will get a MAC address soon (via ARP).
548          * Otherwise, we can afford to wait a little while. */
549         next_refresh = now + (!ip || have_mac ? 10 : 1);
550     }
551     return !eth_addr_is_zero(mac) ? mac : NULL;
552 }
553
554 static bool
555 is_controller_mac(const uint8_t dl_addr[ETH_ADDR_LEN],
556                   struct in_band_data *in_band)
557 {
558     const uint8_t *mac = get_controller_mac(in_band);
559     return mac && eth_addr_equals(mac, dl_addr);
560 }
561
562 static bool
563 in_band_packet_cb(struct relay *r, int half, void *in_band_)
564 {
565     struct in_band_data *in_band = in_band_;
566     struct rconn *rc = r->halves[HALF_LOCAL].rconn;
567     struct buffer *msg = r->halves[HALF_LOCAL].rxbuf;
568     struct ofp_packet_in *opi;
569     struct ofp_header *oh;
570     size_t pkt_ofs, pkt_len;
571     struct buffer pkt;
572     struct flow flow;
573     uint16_t in_port, out_port;
574     const uint8_t *controller_mac;
575
576     if (half != HALF_LOCAL || r->is_mgmt_conn) {
577         return false;
578     }
579
580     oh = msg->data;
581     if (oh->type != OFPT_PACKET_IN) {
582         return false;
583     }
584     if (msg->size < offsetof(struct ofp_packet_in, data)) {
585         VLOG_WARN("packet too short (%zu bytes) for packet_in", msg->size);
586         return false;
587     }
588
589     /* Extract flow data from 'opi' into 'flow'. */
590     opi = msg->data;
591     in_port = ntohs(opi->in_port);
592     pkt_ofs = offsetof(struct ofp_packet_in, data);
593     pkt_len = ntohs(opi->header.length) - pkt_ofs;
594     pkt.data = opi->data;
595     pkt.size = pkt_len;
596     flow_extract(&pkt, in_port, &flow);
597
598     /* Deal with local stuff. */
599     controller_mac = get_controller_mac(in_band);
600     if (in_port == OFPP_LOCAL) {
601         /* Sent by secure channel. */
602         out_port = mac_learning_lookup(in_band->ml, flow.dl_dst);
603     } else if (eth_addr_equals(flow.dl_dst, in_band->mac)) {
604         /* Sent to secure channel. */
605         out_port = OFPP_LOCAL;
606         if (mac_learning_learn(in_band->ml, flow.dl_src, in_port)) {
607             VLOG_DBG("learned that "ETH_ADDR_FMT" is on port %"PRIu16,
608                      ETH_ADDR_ARGS(flow.dl_src), in_port);
609         }
610     } else if (flow.dl_type == htons(ETH_TYPE_ARP)
611                && eth_addr_is_broadcast(flow.dl_dst)
612                && is_controller_mac(flow.dl_src, in_band)) {
613         /* ARP sent by controller. */
614         out_port = OFPP_FLOOD;
615     } else if (is_controller_mac(flow.dl_dst, in_band)
616                && in_port == mac_learning_lookup(in_band->ml,
617                                                  controller_mac)) {
618         /* Drop controller traffic that arrives on the controller port. */
619         queue_tx(rc, in_band, make_add_flow(&flow, ntohl(opi->buffer_id),
620                                             in_band->s->max_idle, 0));
621         return true;
622     } else {
623         return false;
624     }
625
626     if (out_port != OFPP_FLOOD) {
627         /* The output port is known, so add a new flow. */
628         queue_tx(rc, in_band,
629                  make_add_simple_flow(&flow, ntohl(opi->buffer_id),
630                                       out_port, in_band->s->max_idle));
631
632         /* If the switch didn't buffer the packet, we need to send a copy. */
633         if (ntohl(opi->buffer_id) == UINT32_MAX) {
634             queue_tx(rc, in_band,
635                      make_unbuffered_packet_out(&pkt, in_port, out_port));
636         }
637     } else {
638         /* We don't know that MAC.  Send along the packet without setting up a
639          * flow. */
640         struct buffer *b;
641         if (ntohl(opi->buffer_id) == UINT32_MAX) {
642             b = make_unbuffered_packet_out(&pkt, in_port, out_port);
643         } else {
644             b = make_buffered_packet_out(ntohl(opi->buffer_id),
645                                          in_port, out_port);
646         }
647         queue_tx(rc, in_band, b);
648     }
649     return true;
650 }
651
652 static void
653 in_band_status_cb(struct status_reply *sr, void *in_band_)
654 {
655     struct in_band_data *in_band = in_band_;
656     struct in_addr local_ip;
657     uint32_t controller_ip;
658     const uint8_t *controller_mac;
659
660     if (netdev_get_in4(in_band->of_device, &local_ip)) {
661         status_reply_put(sr, "local-ip="IP_FMT, IP_ARGS(&local_ip.s_addr));
662     }
663     status_reply_put(sr, "local-mac="ETH_ADDR_FMT,
664                      ETH_ADDR_ARGS(in_band->mac));
665
666     controller_ip = rconn_get_ip(in_band->controller);
667     if (controller_ip) {
668         status_reply_put(sr, "controller-ip="IP_FMT,
669                       IP_ARGS(&controller_ip));
670     }
671     controller_mac = get_controller_mac(in_band);
672     if (controller_mac) {
673         status_reply_put(sr, "controller-mac="ETH_ADDR_FMT,
674                       ETH_ADDR_ARGS(controller_mac));
675     }
676 }
677
678 static struct hook
679 in_band_hook_create(const struct settings *s, struct switch_status *ss,
680                     struct rconn *remote)
681 {
682     struct in_band_data *in_band;
683     int retval;
684
685     in_band = xcalloc(1, sizeof *in_band);
686     in_band->s = s;
687     in_band->ml = mac_learning_create();
688     retval = netdev_open(s->of_name, NETDEV_ETH_TYPE_NONE,
689                          &in_band->of_device);
690     if (retval) {
691         fatal(retval, "Could not open %s device", s->of_name);
692     }
693     memcpy(in_band->mac, netdev_get_etheraddr(in_band->of_device),
694            ETH_ADDR_LEN);
695     in_band->controller = remote;
696     switch_status_register_category(ss, "in-band", in_band_status_cb, in_band);
697     return make_hook(in_band_packet_cb, NULL, NULL, in_band);
698 }
699 \f
700 /* Fail open support. */
701
702 struct fail_open_data {
703     const struct settings *s;
704     struct rconn *local_rconn;
705     struct rconn *remote_rconn;
706     struct lswitch *lswitch;
707     int last_disconn_secs;
708 };
709
710 /* Causes 'r' to enter or leave fail-open mode, if appropriate. */
711 static void
712 fail_open_periodic_cb(void *fail_open_)
713 {
714     struct fail_open_data *fail_open = fail_open_;
715     int disconn_secs;
716     bool open;
717
718     disconn_secs = rconn_disconnected_duration(fail_open->remote_rconn);
719     open = disconn_secs >= fail_open->s->probe_interval * 3;
720     if (open != (fail_open->lswitch != NULL)) {
721         if (!open) {
722             VLOG_WARN("No longer in fail-open mode");
723             lswitch_destroy(fail_open->lswitch);
724             fail_open->lswitch = NULL;
725         } else {
726             VLOG_WARN("Could not connect to controller for %d seconds, "
727                       "failing open", disconn_secs);
728             fail_open->lswitch = lswitch_create(fail_open->local_rconn, true,
729                                                 fail_open->s->max_idle);
730             fail_open->last_disconn_secs = disconn_secs;
731         }
732     } else if (open && disconn_secs > fail_open->last_disconn_secs + 60) {
733         VLOG_WARN("Still in fail-open mode after %d seconds disconnected "
734                   "from controller", disconn_secs);
735         fail_open->last_disconn_secs = disconn_secs;
736     }
737 }
738
739 static bool
740 fail_open_packet_cb(struct relay *r, int half, void *fail_open_)
741 {
742     struct fail_open_data *fail_open = fail_open_;
743     if (half != HALF_LOCAL || r->is_mgmt_conn || !fail_open->lswitch) {
744         return false;
745     } else {
746         lswitch_process_packet(fail_open->lswitch, fail_open->local_rconn,
747                                r->halves[HALF_LOCAL].rxbuf);
748         rconn_run(fail_open->local_rconn);
749         return true;
750     }
751 }
752
753 static void
754 fail_open_status_cb(struct status_reply *sr, void *fail_open_)
755 {
756     struct fail_open_data *fail_open = fail_open_;
757     const struct settings *s = fail_open->s;
758     int trigger_duration = s->probe_interval * 3;
759     int cur_duration = rconn_disconnected_duration(fail_open->remote_rconn);
760
761     status_reply_put(sr, "trigger-duration=%d", trigger_duration);
762     status_reply_put(sr, "current-duration=%d", cur_duration);
763     status_reply_put(sr, "triggered=%s",
764                      cur_duration >= trigger_duration ? "true" : "false");
765     status_reply_put(sr, "max-idle=%d", s->max_idle);
766 }
767
768 static struct hook
769 fail_open_hook_create(const struct settings *s, struct switch_status *ss,
770                       struct rconn *local_rconn, struct rconn *remote_rconn)
771 {
772     struct fail_open_data *fail_open = xmalloc(sizeof *fail_open);
773     fail_open->s = s;
774     fail_open->local_rconn = local_rconn;
775     fail_open->remote_rconn = remote_rconn;
776     fail_open->lswitch = NULL;
777     switch_status_register_category(ss, "fail-open",
778                                     fail_open_status_cb, fail_open);
779     return make_hook(fail_open_packet_cb, fail_open_periodic_cb, NULL,
780                      fail_open);
781 }
782 \f
783 struct rate_limiter {
784     const struct settings *s;
785     struct rconn *remote_rconn;
786
787     /* One queue per physical port. */
788     struct queue queues[OFPP_MAX];
789     int n_queued;               /* Sum over queues[*].n. */
790     int next_tx_port;           /* Next port to check in round-robin. */
791
792     /* Token bucket.
793      *
794      * It costs 1000 tokens to send a single packet_in message.  A single token
795      * per message would be more straightforward, but this choice lets us avoid
796      * round-off error in refill_bucket()'s calculation of how many tokens to
797      * add to the bucket, since no division step is needed. */
798     long long int last_fill;    /* Time at which we last added tokens. */
799     int tokens;                 /* Current number of tokens. */
800
801     /* Transmission queue. */
802     int n_txq;                  /* No. of packets waiting in rconn for tx. */
803
804     /* Statistics reporting. */
805     unsigned long long n_normal;        /* # txed w/o rate limit queuing. */
806     unsigned long long n_limited;       /* # queued for rate limiting. */
807     unsigned long long n_queue_dropped; /* # dropped due to queue overflow. */
808     unsigned long long n_tx_dropped;    /* # dropped due to tx overflow. */
809 };
810
811 /* Drop a packet from the longest queue in 'rl'. */
812 static void
813 drop_packet(struct rate_limiter *rl)
814 {
815     struct queue *longest;      /* Queue currently selected as longest. */
816     int n_longest;              /* # of queues of same length as 'longest'. */
817     struct queue *q;
818
819     longest = &rl->queues[0];
820     n_longest = 1;
821     for (q = &rl->queues[0]; q < &rl->queues[OFPP_MAX]; q++) {
822         if (longest->n < q->n) {
823             longest = q;
824             n_longest = 1;
825         } else if (longest->n == q->n) {
826             n_longest++;
827
828             /* Randomly select one of the longest queues, with a uniform
829              * distribution (Knuth algorithm 3.4.2R). */
830             if (!random_range(n_longest)) {
831                 longest = q;
832             }
833         }
834     }
835
836     /* FIXME: do we want to pop the tail instead? */
837     buffer_delete(queue_pop_head(longest));
838     rl->n_queued--;
839 }
840
841 /* Remove and return the next packet to transmit (in round-robin order). */
842 static struct buffer *
843 dequeue_packet(struct rate_limiter *rl)
844 {
845     unsigned int i;
846
847     for (i = 0; i < OFPP_MAX; i++) {
848         unsigned int port = (rl->next_tx_port + i) % OFPP_MAX;
849         struct queue *q = &rl->queues[port];
850         if (q->n) {
851             rl->next_tx_port = (port + 1) % OFPP_MAX;
852             rl->n_queued--;
853             return queue_pop_head(q);
854         }
855     }
856     NOT_REACHED();
857 }
858
859 /* Add tokens to the bucket based on elapsed time. */
860 static void
861 refill_bucket(struct rate_limiter *rl)
862 {
863     const struct settings *s = rl->s;
864     long long int now = time_msec();
865     long long int tokens = (now - rl->last_fill) * s->rate_limit + rl->tokens;
866     if (tokens >= 1000) {
867         rl->last_fill = now;
868         rl->tokens = MIN(tokens, s->burst_limit * 1000);
869     }
870 }
871
872 /* Attempts to remove enough tokens from 'rl' to transmit a packet.  Returns
873  * true if successful, false otherwise.  (In the latter case no tokens are
874  * removed.) */
875 static bool
876 get_token(struct rate_limiter *rl)
877 {
878     if (rl->tokens >= 1000) {
879         rl->tokens -= 1000;
880         return true;
881     } else {
882         return false;
883     }
884 }
885
886 static bool
887 rate_limit_packet_cb(struct relay *r, int half, void *rl_)
888 {
889     struct rate_limiter *rl = rl_;
890     const struct settings *s = rl->s;
891     struct buffer *msg = r->halves[HALF_LOCAL].rxbuf;
892     struct ofp_header *oh;
893
894     if (half == HALF_REMOTE) {
895         return false;
896     }
897
898     oh = msg->data;
899     if (oh->type != OFPT_PACKET_IN) {
900         return false;
901     }
902     if (msg->size < offsetof(struct ofp_packet_in, data)) {
903         VLOG_WARN("packet too short (%zu bytes) for packet_in", msg->size);
904         return false;
905     }
906
907     if (!rl->n_queued && get_token(rl)) {
908         /* In the common case where we are not constrained by the rate limit,
909          * let the packet take the normal path. */
910         rl->n_normal++;
911         return false;
912     } else {
913         /* Otherwise queue it up for the periodic callback to drain out. */
914         struct ofp_packet_in *opi = msg->data;
915         int port = ntohs(opi->in_port) % OFPP_MAX;
916         if (rl->n_queued >= s->burst_limit) {
917             drop_packet(rl);
918         }
919         queue_push_tail(&rl->queues[port], buffer_clone(msg));
920         rl->n_queued++;
921         rl->n_limited++;
922         return true;
923     }
924 }
925
926 static void
927 rate_limit_status_cb(struct status_reply *sr, void *rl_)
928 {
929     struct rate_limiter *rl = rl_;
930
931     status_reply_put(sr, "normal=%llu", rl->n_normal);
932     status_reply_put(sr, "limited=%llu", rl->n_limited);
933     status_reply_put(sr, "queue-dropped=%llu", rl->n_queue_dropped);
934     status_reply_put(sr, "tx-dropped=%llu", rl->n_tx_dropped);
935 }
936
937 static void
938 rate_limit_periodic_cb(void *rl_)
939 {
940     struct rate_limiter *rl = rl_;
941     int i;
942
943     /* Drain some packets out of the bucket if possible, but limit the number
944      * of iterations to allow other code to get work done too. */
945     refill_bucket(rl);
946     for (i = 0; rl->n_queued && get_token(rl) && i < 50; i++) {
947         /* Use a small, arbitrary limit for the amount of queuing to do here,
948          * because the TCP connection is responsible for buffering and there is
949          * no point in trying to transmit faster than the TCP connection can
950          * handle. */
951         struct buffer *b = dequeue_packet(rl);
952         if (rconn_send_with_limit(rl->remote_rconn, b, &rl->n_txq, 10)) {
953             rl->n_tx_dropped++;
954         }
955     }
956 }
957
958 static void
959 rate_limit_wait_cb(void *rl_)
960 {
961     struct rate_limiter *rl = rl_;
962     if (rl->n_queued) {
963         if (rl->tokens >= 1000) {
964             /* We can transmit more packets as soon as we're called again. */
965             poll_immediate_wake();
966         } else {
967             /* We have to wait for the bucket to re-fill.  We could calculate
968              * the exact amount of time here for increased smoothness. */
969             poll_timer_wait(TIME_UPDATE_INTERVAL / 2);
970         }
971     }
972 }
973
974 static struct hook
975 rate_limit_hook_create(const struct settings *s, struct switch_status *ss,
976                        struct rconn *local, struct rconn *remote)
977 {
978     struct rate_limiter *rl;
979     size_t i;
980
981     rl = xcalloc(1, sizeof *rl);
982     rl->s = s;
983     rl->remote_rconn = remote;
984     for (i = 0; i < ARRAY_SIZE(rl->queues); i++) {
985         queue_init(&rl->queues[i]);
986     }
987     rl->last_fill = time_msec();
988     rl->tokens = s->rate_limit * 100;
989     switch_status_register_category(ss, "rate-limit",
990                                     rate_limit_status_cb, rl);
991     return make_hook(rate_limit_packet_cb, rate_limit_periodic_cb,
992                      rate_limit_wait_cb, rl);
993 }
994 \f
995 /* OFPST_SWITCH statistics. */
996
997 struct switch_status_category {
998     char *name;
999     void (*cb)(struct status_reply *, void *aux);
1000     void *aux;
1001 };
1002
1003 struct switch_status {
1004     const struct settings *s;
1005     time_t booted;
1006     struct switch_status_category categories[8];
1007     int n_categories;
1008 };
1009
1010 struct status_reply {
1011     struct switch_status_category *category;
1012     struct ds request;
1013     struct ds output;
1014 };
1015
1016 static bool
1017 switch_status_packet_cb(struct relay *r, int half, void *ss_)
1018 {
1019     struct switch_status *ss = ss_;
1020     struct rconn *rc = r->halves[HALF_REMOTE].rconn;
1021     struct buffer *msg = r->halves[HALF_REMOTE].rxbuf;
1022     struct switch_status_category *c;
1023     struct ofp_stats_request *osr;
1024     struct ofp_stats_reply *reply;
1025     struct status_reply sr;
1026     struct ofp_header *oh;
1027     struct buffer *b;
1028     int retval;
1029
1030     if (half == HALF_LOCAL) {
1031         return false;
1032     }
1033
1034     oh = msg->data;
1035     if (oh->type != OFPT_STATS_REQUEST) {
1036         return false;
1037     }
1038     if (msg->size < sizeof(struct ofp_stats_request)) {
1039         VLOG_WARN("packet too short (%zu bytes) for stats_request", msg->size);
1040         return false;
1041     }
1042
1043     osr = msg->data;
1044     if (osr->type != htons(OFPST_SWITCH)) {
1045         return false;
1046     }
1047
1048     sr.request.string = (void *) (osr + 1);
1049     sr.request.length = msg->size - sizeof *osr;
1050     ds_init(&sr.output);
1051     for (c = ss->categories; c < &ss->categories[ss->n_categories]; c++) {
1052         if (!memcmp(c->name, sr.request.string,
1053                     MIN(strlen(c->name), sr.request.length))) {
1054             sr.category = c;
1055             c->cb(&sr, c->aux);
1056         }
1057     }
1058     reply = make_openflow_xid((offsetof(struct ofp_stats_reply, body)
1059                                + sr.output.length),
1060                               OFPT_STATS_REPLY, osr->header.xid, &b);
1061     reply->type = htons(OFPST_SWITCH);
1062     reply->flags = 0;
1063     memcpy(reply->body, sr.output.string, sr.output.length);
1064     retval = rconn_send(rc, b, NULL);
1065     if (retval && retval != EAGAIN) {
1066         VLOG_WARN("send failed (%s)", strerror(retval));
1067     }
1068     ds_destroy(&sr.output);
1069     return true;
1070 }
1071
1072 static void
1073 rconn_status_cb(struct status_reply *sr, void *rconn_)
1074 {
1075     struct rconn *rconn = rconn_;
1076     time_t now = time_now();
1077
1078     status_reply_put(sr, "name=%s", rconn_get_name(rconn));
1079     status_reply_put(sr, "state=%s", rconn_get_state(rconn));
1080     status_reply_put(sr, "is-connected=%s",
1081                      rconn_is_connected(rconn) ? "true" : "false");
1082     status_reply_put(sr, "sent-msgs=%u", rconn_packets_sent(rconn));
1083     status_reply_put(sr, "received-msgs=%u", rconn_packets_received(rconn));
1084     status_reply_put(sr, "attempted-connections=%u",
1085                      rconn_get_attempted_connections(rconn));
1086     status_reply_put(sr, "successful-connections=%u",
1087                      rconn_get_successful_connections(rconn));
1088     status_reply_put(sr, "last-connection=%ld",
1089                      (long int) (now - rconn_get_last_connection(rconn)));
1090     status_reply_put(sr, "time-connected=%lu",
1091                      rconn_get_total_time_connected(rconn));
1092 }
1093
1094 static void
1095 config_status_cb(struct status_reply *sr, void *s_)
1096 {
1097      const struct settings *s = s_;
1098
1099     if (s->listen_vconn_name) {
1100         status_reply_put(sr, "management=%s", s->listen_vconn_name);
1101     }
1102     if (s->probe_interval) {
1103         status_reply_put(sr, "probe-interval=%d", s->probe_interval);
1104     }
1105     if (s->max_backoff) {
1106         status_reply_put(sr, "max-backoff=%d", s->max_backoff);
1107     }
1108 }
1109
1110 static void
1111 switch_status_cb(struct status_reply *sr, void *ss_)
1112 {
1113     struct switch_status *ss = ss_;
1114     time_t now = time_now();
1115
1116     status_reply_put(sr, "now=%ld", (long int) now);
1117     status_reply_put(sr, "uptime=%ld", (long int) (now - ss->booted));
1118     status_reply_put(sr, "pid=%ld", (long int) getpid());
1119 }
1120
1121 static struct hook
1122 switch_status_hook_create(const struct settings *s, struct switch_status **ssp)
1123 {
1124     struct switch_status *ss = xcalloc(1, sizeof *ss);
1125     ss->s = s;
1126     ss->booted = time_now();
1127     switch_status_register_category(ss, "config",
1128                                     config_status_cb, (void *) s);
1129     switch_status_register_category(ss, "switch", switch_status_cb, ss);
1130     *ssp = ss;
1131     return make_hook(switch_status_packet_cb, NULL, NULL, ss);
1132 }
1133
1134 static void
1135 switch_status_register_category(struct switch_status *ss,
1136                                 const char *category,
1137                                 void (*cb)(struct status_reply *,
1138                                            void *aux),
1139                                 void *aux)
1140 {
1141     struct switch_status_category *c;
1142     assert(ss->n_categories < ARRAY_SIZE(ss->categories));
1143     c = &ss->categories[ss->n_categories++];
1144     c->cb = cb;
1145     c->aux = aux;
1146     c->name = xstrdup(category);
1147 }
1148
1149 static void
1150 status_reply_put(struct status_reply *sr, const char *content, ...)
1151 {
1152     size_t old_length = sr->output.length;
1153     size_t added;
1154     va_list args;
1155
1156     /* Append the status reply to the output. */
1157     ds_put_format(&sr->output, "%s.", sr->category->name);
1158     va_start(args, content);
1159     ds_put_format_valist(&sr->output, content, args);
1160     va_end(args);
1161     if (ds_last(&sr->output) != '\n') {
1162         ds_put_char(&sr->output, '\n');
1163     }
1164
1165     /* Drop what we just added if it doesn't match the request. */
1166     added = sr->output.length - old_length;
1167     if (added < sr->request.length
1168         || memcmp(&sr->output.string[old_length],
1169                   sr->request.string, sr->request.length)) {
1170         ds_truncate(&sr->output, old_length);
1171     }
1172 }
1173
1174 \f
1175 /* Controller discovery. */
1176
1177 struct discovery
1178 {
1179     const struct settings *s;
1180     struct dhclient *dhcp;
1181     int n_changes;
1182 };
1183
1184 static void
1185 discovery_status_cb(struct status_reply *sr, void *d_)
1186 {
1187     struct discovery *d = d_;
1188
1189     status_reply_put(sr, "discovery.accept-remote=%s",
1190                      d->s->accept_controller_re);
1191     status_reply_put(sr, "discovery.n-changes=%d", d->n_changes);
1192     status_reply_put(sr, "discovery.state=%s", dhclient_get_state(d->dhcp));
1193     status_reply_put(sr, "discovery.state-elapsed=%u",
1194                      dhclient_get_state_elapsed(d->dhcp));
1195     if (dhclient_is_bound(d->dhcp)) {
1196         uint32_t ip = dhclient_get_ip(d->dhcp);
1197         uint32_t netmask = dhclient_get_netmask(d->dhcp);
1198         uint32_t router = dhclient_get_router(d->dhcp);
1199
1200         const struct dhcp_msg *cfg = dhclient_get_config(d->dhcp);
1201         uint32_t dns_server;
1202         char *domain_name;
1203         int i;
1204
1205         status_reply_put(sr, "discovery.ip="IP_FMT, IP_ARGS(&ip));
1206         status_reply_put(sr, "discovery.netmask="IP_FMT, IP_ARGS(&netmask));
1207         if (router) {
1208             status_reply_put(sr, "discovery.router="IP_FMT, IP_ARGS(&router));
1209         }
1210
1211         for (i = 0; dhcp_msg_get_ip(cfg, DHCP_CODE_DNS_SERVER, i, &dns_server);
1212              i++) {
1213             status_reply_put(sr, "discovery.dns%d="IP_FMT,
1214                              i, IP_ARGS(&dns_server));
1215         }
1216
1217         domain_name = dhcp_msg_get_string(cfg, DHCP_CODE_DOMAIN_NAME);
1218         if (domain_name) {
1219             status_reply_put(sr, "discovery.domain=%s", domain_name);
1220             free(domain_name);
1221         }
1222
1223         status_reply_put(sr, "discovery.lease-remaining=%u",
1224                          dhclient_get_lease_remaining(d->dhcp));
1225     }
1226 }
1227
1228 static struct discovery *
1229 discovery_init(const struct settings *s, struct switch_status *ss)
1230 {
1231     struct netdev *netdev;
1232     struct discovery *d;
1233     struct dhclient *dhcp;
1234     int retval;
1235
1236     /* Bring ofX network device up. */
1237     retval = netdev_open(s->of_name, NETDEV_ETH_TYPE_NONE, &netdev);
1238     if (retval) {
1239         fatal(retval, "Could not open %s device", s->of_name);
1240     }
1241     retval = netdev_turn_flags_on(netdev, NETDEV_UP, true);
1242     if (retval) {
1243         fatal(retval, "Could not bring %s device up", s->of_name);
1244     }
1245     netdev_close(netdev);
1246
1247     /* Initialize DHCP client. */
1248     retval = dhclient_create(s->of_name, modify_dhcp_request,
1249                              validate_dhcp_offer, (void *) s, &dhcp);
1250     if (retval) {
1251         fatal(retval, "Failed to initialize DHCP client");
1252     }
1253     dhclient_init(dhcp, 0);
1254
1255     d = xmalloc(sizeof *d);
1256     d->s = s;
1257     d->dhcp = dhcp;
1258     d->n_changes = 0;
1259
1260     switch_status_register_category(ss, "discovery", discovery_status_cb, d);
1261
1262     return d;
1263 }
1264
1265 static void
1266 discovery_question_connectivity(struct discovery *d)
1267 {
1268     dhclient_force_renew(d->dhcp, 15);
1269 }
1270
1271 static bool
1272 discovery_run(struct discovery *d, char **controller_name)
1273 {
1274     dhclient_run(d->dhcp);
1275     if (!dhclient_changed(d->dhcp)) {
1276         return false;
1277     }
1278
1279     dhclient_configure_netdev(d->dhcp);
1280     if (d->s->update_resolv_conf) {
1281         dhclient_update_resolv_conf(d->dhcp);
1282     }
1283
1284     if (dhclient_is_bound(d->dhcp)) {
1285         *controller_name = dhcp_msg_get_string(dhclient_get_config(d->dhcp),
1286                                                DHCP_CODE_OFP_CONTROLLER_VCONN);
1287         VLOG_WARN("%s: discovered controller", *controller_name);
1288         d->n_changes++;
1289     } else {
1290         *controller_name = NULL;
1291         if (d->n_changes) {
1292             VLOG_WARN("discovered controller no longer available");
1293             d->n_changes++;
1294         }
1295     }
1296     return true;
1297 }
1298
1299 static void
1300 discovery_wait(struct discovery *d)
1301 {
1302     dhclient_wait(d->dhcp);
1303 }
1304
1305 static void
1306 modify_dhcp_request(struct dhcp_msg *msg, void *aux)
1307 {
1308     dhcp_msg_put_string(msg, DHCP_CODE_VENDOR_CLASS, "OpenFlow");
1309 }
1310
1311 static bool
1312 validate_dhcp_offer(const struct dhcp_msg *msg, void *s_)
1313 {
1314     const struct settings *s = s_;
1315     char *vconn_name;
1316     bool accept;
1317
1318     vconn_name = dhcp_msg_get_string(msg, DHCP_CODE_OFP_CONTROLLER_VCONN);
1319     if (!vconn_name) {
1320         VLOG_WARN("rejecting DHCP offer missing controller vconn");
1321         return false;
1322     }
1323     accept = !regexec(&s->accept_controller_regex, vconn_name, 0, NULL, 0);
1324     if (!accept) {
1325         VLOG_WARN("rejecting controller vconn that fails to match %s",
1326                   s->accept_controller_re);
1327     }
1328     free(vconn_name);
1329     return accept;
1330 }
1331 \f
1332 /* User interface. */
1333
1334 static void
1335 parse_options(int argc, char *argv[], struct settings *s)
1336 {
1337     enum {
1338         OPT_ACCEPT_VCONN = UCHAR_MAX + 1,
1339         OPT_NO_RESOLV_CONF,
1340         OPT_INACTIVITY_PROBE,
1341         OPT_MAX_IDLE,
1342         OPT_MAX_BACKOFF,
1343         OPT_RATE_LIMIT,
1344         OPT_BURST_LIMIT
1345     };
1346     static struct option long_options[] = {
1347         {"accept-vconn", required_argument, 0, OPT_ACCEPT_VCONN},
1348         {"no-resolv-conf", no_argument, 0, OPT_NO_RESOLV_CONF},
1349         {"fail",        required_argument, 0, 'f'},
1350         {"inactivity-probe", required_argument, 0, OPT_INACTIVITY_PROBE},
1351         {"max-idle",    required_argument, 0, OPT_MAX_IDLE},
1352         {"max-backoff", required_argument, 0, OPT_MAX_BACKOFF},
1353         {"listen",      required_argument, 0, 'l'},
1354         {"rate-limit",  optional_argument, 0, OPT_RATE_LIMIT},
1355         {"burst-limit", required_argument, 0, OPT_BURST_LIMIT},
1356         {"detach",      no_argument, 0, 'D'},
1357         {"pidfile",     optional_argument, 0, 'P'},
1358         {"verbose",     optional_argument, 0, 'v'},
1359         {"help",        no_argument, 0, 'h'},
1360         {"version",     no_argument, 0, 'V'},
1361         VCONN_SSL_LONG_OPTIONS
1362         {0, 0, 0, 0},
1363     };
1364     char *short_options = long_options_to_short_options(long_options);
1365     char *accept_re = NULL;
1366     int retval;
1367
1368     /* Set defaults that we can figure out before parsing options. */
1369     s->listen_vconn_name = NULL;
1370     s->fail_mode = FAIL_OPEN;
1371     s->max_idle = 15;
1372     s->probe_interval = 15;
1373     s->max_backoff = 15;
1374     s->update_resolv_conf = true;
1375     s->rate_limit = 0;
1376     s->burst_limit = 0;
1377     for (;;) {
1378         int c;
1379
1380         c = getopt_long(argc, argv, short_options, long_options, NULL);
1381         if (c == -1) {
1382             break;
1383         }
1384
1385         switch (c) {
1386         case OPT_ACCEPT_VCONN:
1387             accept_re = optarg[0] == '^' ? optarg : xasprintf("^%s", optarg);
1388             break;
1389
1390         case OPT_NO_RESOLV_CONF:
1391             s->update_resolv_conf = false;
1392             break;
1393
1394         case 'f':
1395             if (!strcmp(optarg, "open")) {
1396                 s->fail_mode = FAIL_OPEN;
1397             } else if (!strcmp(optarg, "closed")) {
1398                 s->fail_mode = FAIL_CLOSED;
1399             } else {
1400                 fatal(0,
1401                       "-f or --fail argument must be \"open\" or \"closed\"");
1402             }
1403             break;
1404
1405         case OPT_INACTIVITY_PROBE:
1406             s->probe_interval = atoi(optarg);
1407             if (s->probe_interval < 5) {
1408                 fatal(0, "--inactivity-probe argument must be at least 5");
1409             }
1410             break;
1411
1412         case OPT_MAX_IDLE:
1413             if (!strcmp(optarg, "permanent")) {
1414                 s->max_idle = OFP_FLOW_PERMANENT;
1415             } else {
1416                 s->max_idle = atoi(optarg);
1417                 if (s->max_idle < 1 || s->max_idle > 65535) {
1418                     fatal(0, "--max-idle argument must be between 1 and "
1419                           "65535 or the word 'permanent'");
1420                 }
1421             }
1422             break;
1423
1424         case OPT_MAX_BACKOFF:
1425             s->max_backoff = atoi(optarg);
1426             if (s->max_backoff < 1) {
1427                 fatal(0, "--max-backoff argument must be at least 1");
1428             } else if (s->max_backoff > 3600) {
1429                 s->max_backoff = 3600;
1430             }
1431             break;
1432
1433         case OPT_RATE_LIMIT:
1434             if (optarg) {
1435                 s->rate_limit = atoi(optarg);
1436                 if (s->rate_limit < 1) {
1437                     fatal(0, "--rate-limit argument must be at least 1");
1438                 }
1439             } else {
1440                 s->rate_limit = 1000;
1441             }
1442             break;
1443
1444         case OPT_BURST_LIMIT:
1445             s->burst_limit = atoi(optarg);
1446             if (s->burst_limit < 1) {
1447                 fatal(0, "--burst-limit argument must be at least 1");
1448             }
1449             break;
1450
1451         case 'D':
1452             set_detach();
1453             break;
1454
1455         case 'P':
1456             set_pidfile(optarg);
1457             break;
1458
1459         case 'l':
1460             if (s->listen_vconn_name) {
1461                 fatal(0, "-l or --listen may be only specified once");
1462             }
1463             s->listen_vconn_name = optarg;
1464             break;
1465
1466         case 'h':
1467             usage();
1468
1469         case 'V':
1470             printf("%s "VERSION" compiled "__DATE__" "__TIME__"\n", argv[0]);
1471             exit(EXIT_SUCCESS);
1472
1473         case 'v':
1474             vlog_set_verbosity(optarg);
1475             break;
1476
1477         VCONN_SSL_OPTION_HANDLERS
1478
1479         case '?':
1480             exit(EXIT_FAILURE);
1481
1482         default:
1483             abort();
1484         }
1485     }
1486     free(short_options);
1487
1488     argc -= optind;
1489     argv += optind;
1490     if (argc < 1 || argc > 2) {
1491         fatal(0, "need one or two non-option arguments; use --help for usage");
1492     }
1493
1494     /* Local and remote vconns. */
1495     s->nl_name = argv[0];
1496     if (strncmp(s->nl_name, "nl:", 3)
1497         || strlen(s->nl_name) < 4
1498         || s->nl_name[strspn(s->nl_name + 3, "0123456789") + 3]) {
1499         fatal(0, "%s: argument is not of the form \"nl:DP_IDX\"", s->nl_name);
1500     }
1501     s->of_name = xasprintf("of%s", s->nl_name + 3);
1502     s->controller_name = argc > 1 ? xstrdup(argv[1]) : NULL;
1503
1504     /* Set accept_controller_regex. */
1505     if (!accept_re) {
1506         accept_re = vconn_ssl_is_configured() ? "^ssl:.*" : ".*";
1507     }
1508     retval = regcomp(&s->accept_controller_regex, accept_re,
1509                      REG_NOSUB | REG_EXTENDED);
1510     if (retval) {
1511         size_t length = regerror(retval, &s->accept_controller_regex, NULL, 0);
1512         char *buffer = xmalloc(length);
1513         regerror(retval, &s->accept_controller_regex, buffer, length);
1514         fatal(0, "%s: %s", accept_re, buffer);
1515     }
1516     s->accept_controller_re = accept_re;
1517
1518     /* Mode of operation. */
1519     s->discovery = s->controller_name == NULL;
1520     if (s->discovery) {
1521         s->in_band = true;
1522     } else {
1523         enum netdev_flags flags;
1524         struct netdev *netdev;
1525
1526         retval = netdev_open(s->of_name, NETDEV_ETH_TYPE_NONE, &netdev);
1527         if (retval) {
1528             fatal(retval, "Could not open %s device", s->of_name);
1529         }
1530
1531         retval = netdev_get_flags(netdev, &flags);
1532         if (retval) {
1533             fatal(retval, "Could not get flags for %s device", s->of_name);
1534         }
1535
1536         s->in_band = (flags & NETDEV_UP) != 0;
1537         if (s->in_band && netdev_get_in6(netdev, NULL)) {
1538             VLOG_WARN("Ignoring IPv6 address on %s device: IPv6 not supported",
1539                       s->of_name);
1540         }
1541
1542         netdev_close(netdev);
1543     }
1544
1545     /* Rate limiting. */
1546     if (s->rate_limit) {
1547         if (s->rate_limit < 100) {
1548             VLOG_WARN("Rate limit set to unusually low value %d",
1549                       s->rate_limit);
1550         }
1551         if (!s->burst_limit) {
1552             s->burst_limit = s->rate_limit / 4;
1553         }
1554         s->burst_limit = MAX(s->burst_limit, 1);
1555         s->burst_limit = MIN(s->burst_limit, INT_MAX / 1000);
1556     }
1557 }
1558
1559 static void
1560 usage(void)
1561 {
1562     printf("%s: secure channel, a relay for OpenFlow messages.\n"
1563            "usage: %s [OPTIONS] nl:DP_IDX [CONTROLLER]\n"
1564            "where nl:DP_IDX is a datapath that has been added with dpctl.\n"
1565            "CONTROLLER is an active OpenFlow connection method; if it is\n"
1566            "omitted, then secchan performs controller discovery.\n",
1567            program_name, program_name);
1568     vconn_usage(true, true);
1569     printf("\nController discovery options:\n"
1570            "  --accept-vconn=REGEX    accept matching discovered controllers\n"
1571            "  --no-resolv-conf        do not update /etc/resolv.conf\n"
1572            "\nNetworking options:\n"
1573            "  -f, --fail=open|closed  when controller connection fails:\n"
1574            "                            closed: drop all packets\n"
1575            "                            open (default): act as learning switch\n"
1576            "  --inactivity-probe=SECS time between inactivity probes\n"
1577            "  --max-idle=SECS         max idle for flows set up by secchan\n"
1578            "  --max-backoff=SECS      max time between controller connection\n"
1579            "                          attempts (default: 15 seconds)\n"
1580            "  -l, --listen=METHOD     allow management connections on METHOD\n"
1581            "                          (a passive OpenFlow connection method)\n"
1582            "\nRate-limiting of \"packet-in\" messages to the controller:\n"
1583            "  --rate-limit[=PACKETS]  max rate, in packets/s (default: 1000)\n"
1584            "  --burst-limit=BURST     limit on packet credit for idle time\n"
1585            "\nOther options:\n"
1586            "  -D, --detach            run in background as daemon\n"
1587            "  -P, --pidfile[=FILE]    create pidfile (default: %s/secchan.pid)\n"
1588            "  -v, --verbose=MODULE[:FACILITY[:LEVEL]]  set logging levels\n"
1589            "  -v, --verbose           set maximum verbosity level\n"
1590            "  -h, --help              display this help message\n"
1591            "  -V, --version           display version information\n",
1592            RUNDIR);
1593     exit(EXIT_SUCCESS);
1594 }