Support SSL in secchan and controller.
[sliver-openvswitch.git] / controller / controller.c
1 /* Copyright (C) 2007 Board of Trustees, Leland Stanford Jr. University.
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to
5  * deal in the Software without restriction, including without limitation the
6  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7  * sell copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19  * IN THE SOFTWARE.
20  */
21
22 #include <assert.h>
23 #include <errno.h>
24 #include <getopt.h>
25 #include <inttypes.h>
26 #include <netinet/in.h>
27 #include <poll.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31
32 #include "buffer.h"
33 #include "command-line.h"
34 #include "compiler.h"
35 #include "fault.h"
36 #include "flow.h"
37 #include "hash.h"
38 #include "list.h"
39 #include "mac.h"
40 #include "ofp-print.h"
41 #include "openflow.h"
42 #include "time.h"
43 #include "util.h"
44 #include "vconn.h"
45 #include "vlog-socket.h"
46 #include "xtoxll.h"
47
48 #include "vlog.h"
49 #define THIS_MODULE VLM_controller
50
51 #define MAX_SWITCHES 16
52 #define MAX_TXQ 128
53
54 struct switch_ {
55     char *name;
56     struct vconn *vconn;
57     struct pollfd *pollfd;
58
59     uint64_t datapath_id;
60     time_t last_control_hello;
61
62     int n_txq;
63     struct buffer *txq, *tx_tail;
64 };
65
66 /* -H, --hub: Use dumb hub instead of learning switch? */
67 static bool hub = false;
68
69 /* -n, --noflow: Pass traffic, but don't setup flows in switch */
70 static bool noflow = false;
71
72 static void parse_options(int argc, char *argv[]);
73 static void usage(void) NO_RETURN;
74
75 static struct switch_ *connect_switch(const char *name);
76 static struct switch_ *new_switch(const char *name, struct vconn *);
77 static void close_switch(struct switch_ *);
78
79 static void queue_tx(struct switch_ *, struct buffer *);
80
81 static void send_control_hello(struct switch_ *);
82
83 static int do_switch_recv(struct switch_ *this);
84 static int do_switch_send(struct switch_ *this);
85
86 static void process_packet(struct switch_ *, struct buffer *);
87 static void process_hub(struct switch_ *, struct ofp_packet_in *);
88 static void process_noflow(struct switch_ *, struct ofp_packet_in *);
89
90 static void switch_init(void);
91 static void process_switch(struct switch_ *, struct ofp_packet_in *);
92
93 int
94 main(int argc, char *argv[])
95 {
96     struct switch_ *switches[MAX_SWITCHES];
97     struct pollfd pollfds[MAX_SWITCHES + 1];
98     struct vlog_server *vlog_server;
99     int n_switches;
100     int retval;
101     int i;
102
103     set_program_name(argv[0]);
104     register_fault_handlers();
105     vlog_init();
106     parse_options(argc, argv);
107
108     if (!hub && !noflow) {
109         switch_init();
110     }
111
112     if (argc - optind < 1) {
113         fatal(0, "at least one vconn argument required; use --help for usage");
114     }
115
116     retval = vlog_server_listen(NULL, &vlog_server);
117     if (retval) {
118         fatal(retval, "Could not listen for vlog connections");
119     }
120
121     n_switches = 0;
122     for (i = 0; i < argc - optind; i++) {
123         struct switch_ *this = connect_switch(argv[optind + i]);
124         if (this) {
125             if (n_switches >= MAX_SWITCHES) {
126                 fatal(0, "max %d switch connections", n_switches);
127             }
128             switches[n_switches++] = this;
129         }
130     }
131     if (n_switches == 0) {
132         fatal(0, "could not connect to any switches");
133     }
134     
135     while (n_switches > 0) {
136         size_t n_ready;
137         int retval;
138
139         /* Wait until there's something to do. */
140         n_ready = 0;
141         for (i = 0; i < n_switches; i++) {
142             struct switch_ *this = switches[i];
143             int want;
144
145             if (vconn_is_passive(this->vconn)) {
146                 want = n_switches < MAX_SWITCHES ? WANT_ACCEPT : 0;
147             } else {
148                 want = WANT_RECV;
149                 if (this->n_txq) {
150                     want |= WANT_SEND;
151                 }
152             }
153
154             this->pollfd = &pollfds[i];
155             this->pollfd->fd = -1;
156             this->pollfd->events = 0;
157             n_ready += vconn_prepoll(this->vconn, want, this->pollfd);
158         }
159         if (vlog_server) {
160             pollfds[n_switches].fd = vlog_server_get_fd(vlog_server);
161             pollfds[n_switches].events = POLLIN;
162         }
163         do {
164             retval = poll(pollfds, n_switches + (vlog_server != NULL),
165                           n_ready ? 0 : -1);
166         } while (retval < 0 && errno == EINTR);
167         if (retval < 0 || (retval == 0 && !n_ready)) {
168             fatal(retval < 0 ? errno : 0, "poll");
169         }
170
171         /* Let each connection deal with any pending operations. */
172         for (i = 0; i < n_switches; i++) {
173             struct switch_ *this = switches[i];
174             vconn_postpoll(this->vconn, &this->pollfd->revents);
175             if (this->pollfd->revents & POLLERR) {
176                 this->pollfd->revents |= POLLIN | POLLOUT;
177             }
178         }
179         if (vlog_server && pollfds[n_switches].revents) {
180             vlog_server_poll(vlog_server);
181         }
182
183         for (i = 0; i < n_switches; ) {
184             struct switch_ *this = switches[i];
185
186             if (this->pollfd) {
187                 retval = 0;
188                 if (vconn_is_passive(this->vconn)) {
189                     if (this->pollfd->revents & POLLIN) {
190                         struct vconn *new_vconn;
191                         while (n_switches < MAX_SWITCHES 
192                                && (retval = vconn_accept(this->vconn,
193                                                          &new_vconn)) == 0) {
194                             switches[n_switches++] = new_switch("tcp",
195                                                                 new_vconn);
196                         }
197                     }
198                 } else {
199                     bool may_read = this->pollfd->revents & POLLIN;
200                     bool may_write = this->pollfd->revents & POLLOUT;
201                     if (may_read) {
202                         retval = do_switch_recv(this);
203                         if (!retval || retval == EAGAIN) {
204                             retval = 0;
205
206                             /* Enable writing to avoid round trip through poll
207                              * in common case. */
208                             may_write = true;
209                         }
210                     }
211                     while ((!retval || retval == EAGAIN) && may_write) {
212                         retval = do_switch_send(this);
213                         may_write = !retval;
214                     }
215                 }
216
217                 if (retval && retval != EAGAIN) {
218                     close_switch(this);
219                     switches[i] = switches[--n_switches];
220                     continue;
221                 }
222             } else {
223                 /* New switch that hasn't been polled yet. */
224             }
225             i++;
226         }
227     }
228
229     return 0;
230 }
231
232 static int
233 do_switch_recv(struct switch_ *this) 
234 {
235     struct buffer *msg;
236     int retval;
237
238     retval = vconn_recv(this->vconn, &msg);
239     if (!retval) {
240         process_packet(this, msg);
241         buffer_delete(msg);
242     }
243     return retval;
244 }
245
246 static int
247 do_switch_send(struct switch_ *this) 
248 {
249     int retval = 0;
250     if (this->n_txq) {
251         struct buffer *next = this->txq->next;
252
253         retval = vconn_send(this->vconn, this->txq);
254         if (retval) {
255             return retval;
256         }
257
258         this->txq = next;
259         if (this->txq == NULL) {
260             this->tx_tail = NULL;
261         }
262         this->n_txq--;
263         return 0;
264     }
265     return EAGAIN;
266 }
267
268 struct switch_ *
269 connect_switch(const char *name) 
270 {
271     struct vconn *vconn;
272     int retval;
273
274     retval = vconn_open(name, &vconn);
275     if (retval) {
276         VLOG_ERR("%s: connect: %s", name, strerror(retval));
277         return NULL;
278     }
279
280     return new_switch(name, vconn);
281 }
282
283 static struct switch_ *
284 new_switch(const char *name, struct vconn *vconn) 
285 {
286     struct switch_ *this = xmalloc(sizeof *this);
287     memset(this, 0, sizeof *this);
288     this->name = xstrdup(name);
289     this->vconn = vconn;
290     this->pollfd = NULL;
291     this->n_txq = 0;
292     this->txq = NULL;
293     this->tx_tail = NULL;
294     this->last_control_hello = 0;
295     if (!vconn_is_passive(vconn)) {
296         send_control_hello(this);
297     }
298     return this;
299 }
300
301 static void
302 close_switch(struct switch_ *this) 
303 {
304     if (this) {
305         struct buffer *cur, *next;
306
307         free(this->name);
308         vconn_close(this->vconn);
309         for (cur = this->txq; cur != NULL; cur = next) {
310             next = cur->next;
311             buffer_delete(cur);
312         }
313         free(this);
314     }
315 }
316
317 static void
318 send_control_hello(struct switch_ *this)
319 {
320     time_t now = time(0);
321     if (now >= this->last_control_hello + 1) {
322         struct buffer *b;
323         struct ofp_control_hello *och;
324
325         b = buffer_new(0);
326         och = buffer_put_uninit(b, sizeof *och);
327         memset(och, 0, sizeof *och);
328         och->header.version = OFP_VERSION;
329         och->header.length = htons(sizeof *och);
330
331         och->version = htonl(OFP_VERSION);
332         och->flags = htons(OFP_CHELLO_SEND_FLOW_EXP);
333         och->miss_send_len = htons(OFP_DEFAULT_MISS_SEND_LEN);
334         queue_tx(this, b);
335
336         this->last_control_hello = now;
337     }
338 }
339
340 static void
341 check_txq(struct switch_ *this UNUSED)
342 {
343 #if 0
344     struct buffer *iter;
345     size_t n;
346
347     assert(this->n_txq == 0
348            ? this->txq == NULL && this->tx_tail == NULL
349            : this->txq != NULL && this->tx_tail != NULL);
350
351     n = 0;
352     for (iter = this->txq; iter != NULL; iter = iter->next) {
353         n++;
354         assert((iter->next != NULL) == (iter != this->tx_tail));
355     }
356     assert(n == this->n_txq);
357 #endif
358 }
359
360 static void
361 queue_tx(struct switch_ *this, struct buffer *b) 
362 {
363     check_txq(this);
364
365     b->next = NULL;
366     if (this->n_txq++) {
367         this->tx_tail->next = b;
368     } else {
369         this->txq = b;
370     }
371     this->tx_tail = b;
372
373     check_txq(this);
374 }
375
376 static void
377 process_packet(struct switch_ *sw, struct buffer *msg) 
378 {
379     static const size_t min_size[UINT8_MAX + 1] = {
380         [0 ... UINT8_MAX] = SIZE_MAX,
381         [OFPT_CONTROL_HELLO] = sizeof (struct ofp_control_hello),
382         [OFPT_DATA_HELLO] = sizeof (struct ofp_data_hello),
383         [OFPT_PACKET_IN] = offsetof (struct ofp_packet_in, data),
384         [OFPT_PACKET_OUT] = sizeof (struct ofp_packet_out),
385         [OFPT_FLOW_MOD] = sizeof (struct ofp_flow_mod),
386         [OFPT_FLOW_EXPIRED] = sizeof (struct ofp_flow_expired),
387         [OFPT_TABLE] = sizeof (struct ofp_table),
388         [OFPT_PORT_MOD] = sizeof (struct ofp_port_mod),
389         [OFPT_PORT_STATUS] = sizeof (struct ofp_port_status),
390         [OFPT_FLOW_STAT_REQUEST] = sizeof (struct ofp_flow_stat_request),
391         [OFPT_FLOW_STAT_REPLY] = sizeof (struct ofp_flow_stat_reply),
392     };
393     struct ofp_header *oh;
394
395     oh = msg->data;
396     if (msg->size < min_size[oh->type]) {
397         VLOG_WARN("%s: too short (%zu bytes) for type %"PRIu8" (min %zu)",
398                   sw->name, msg->size, oh->type, min_size[oh->type]);
399         return;
400     }
401
402     if (oh->type == OFPT_DATA_HELLO) {
403         struct ofp_data_hello *odh = msg->data;
404         sw->datapath_id = odh->datapath_id;
405     } else if (sw->datapath_id == 0) {
406         send_control_hello(sw);
407         return;
408     }
409
410     if (oh->type == OFPT_PACKET_IN) {
411         if (sw->n_txq >= MAX_TXQ) {
412             VLOG_WARN("%s: tx queue overflow", sw->name);
413         } else if (noflow) {
414             process_noflow(sw, msg->data);
415         } else if (hub) {
416             process_hub(sw, msg->data);
417         } else {
418             process_switch(sw, msg->data);
419         }
420         return;
421     }
422
423     ofp_print(stdout, msg->data, msg->size, 2);
424 }
425
426 static void
427 process_hub(struct switch_ *sw, struct ofp_packet_in *opi)
428 {
429     size_t pkt_ofs, pkt_len;
430     struct buffer pkt;
431     struct flow flow;
432
433     /* Extract flow data from 'opi' into 'flow'. */
434     pkt_ofs = offsetof(struct ofp_packet_in, data);
435     pkt_len = ntohs(opi->header.length) - pkt_ofs;
436     pkt.data = opi->data;
437     pkt.size = pkt_len;
438     flow_extract(&pkt, ntohs(opi->in_port), &flow);
439
440     /* Add new flow. */
441     queue_tx(sw, make_add_simple_flow(&flow, ntohl(opi->buffer_id),
442                                       OFPP_FLOOD));
443
444     /* If the switch didn't buffer the packet, we need to send a copy. */
445     if (ntohl(opi->buffer_id) == UINT32_MAX) {
446         queue_tx(sw, make_unbuffered_packet_out(&pkt, ntohs(flow.in_port),
447                                                 OFPP_FLOOD));
448     }
449 }
450
451 static void
452 process_noflow(struct switch_ *sw, struct ofp_packet_in *opi)
453 {
454     /* If the switch didn't buffer the packet, we need to send a copy. */
455     if (ntohl(opi->buffer_id) == UINT32_MAX) {
456         size_t pkt_ofs, pkt_len;
457         struct buffer pkt;
458
459         /* Extract flow data from 'opi' into 'flow'. */
460         pkt_ofs = offsetof(struct ofp_packet_in, data);
461         pkt_len = ntohs(opi->header.length) - pkt_ofs;
462         pkt.data = opi->data;
463         pkt.size = pkt_len;
464
465         queue_tx(sw, make_unbuffered_packet_out(&pkt, ntohs(opi->in_port),
466                     OFPP_FLOOD));
467     } else {
468         queue_tx(sw, make_buffered_packet_out(ntohl(opi->buffer_id), 
469                     ntohs(opi->in_port), OFPP_FLOOD));
470     }
471 }
472
473
474 #define MAC_HASH_BITS 10
475 #define MAC_HASH_MASK (MAC_HASH_SIZE - 1)
476 #define MAC_HASH_SIZE (1u << MAC_HASH_BITS)
477
478 #define MAC_MAX 1024
479
480 struct mac_source {
481     struct list hash_list;
482     struct list lru_list;
483     uint64_t datapath_id;
484     uint8_t mac[ETH_ADDR_LEN];
485     uint16_t port;
486 };
487
488 static struct list mac_table[MAC_HASH_SIZE];
489 static struct list lrus;
490 static size_t mac_count;
491
492 static void
493 switch_init(void)
494 {
495     int i;
496
497     list_init(&lrus);
498     for (i = 0; i < MAC_HASH_SIZE; i++) {
499         list_init(&mac_table[i]);
500     }
501 }
502
503 static struct list *
504 mac_table_bucket(uint64_t datapath_id, const uint8_t mac[ETH_ADDR_LEN]) 
505 {
506     uint32_t hash;
507     hash = hash_fnv(&datapath_id, sizeof datapath_id, HASH_FNV_BASIS);
508     hash = hash_fnv(mac, ETH_ADDR_LEN, hash);
509     return &mac_table[hash & MAC_HASH_BITS];
510 }
511
512 static void
513 process_switch(struct switch_ *sw, struct ofp_packet_in *opi)
514 {
515     size_t pkt_ofs, pkt_len;
516     struct buffer pkt;
517     struct flow flow;
518
519     uint16_t out_port;
520
521     /* Extract flow data from 'opi' into 'flow'. */
522     pkt_ofs = offsetof(struct ofp_packet_in, data);
523     pkt_len = ntohs(opi->header.length) - pkt_ofs;
524     pkt.data = opi->data;
525     pkt.size = pkt_len;
526     flow_extract(&pkt, ntohs(opi->in_port), &flow);
527
528     /* Learn the source. */
529     if (!mac_is_multicast(flow.dl_src)) {
530         struct mac_source *src;
531         struct list *bucket;
532         bool found;
533
534         bucket = mac_table_bucket(sw->datapath_id, flow.dl_src);
535         found = false;
536         LIST_FOR_EACH (src, struct mac_source, hash_list, bucket) {
537             if (src->datapath_id == sw->datapath_id
538                 && mac_equals(src->mac, flow.dl_src)) {
539                 found = true;
540                 break;
541             }
542         }
543
544         if (!found) {
545             /* Learn a new address. */
546
547             if (mac_count >= MAC_MAX) {
548                 /* Drop the least recently used mac source. */
549                 struct mac_source *lru;
550                 lru = CONTAINER_OF(lrus.next, struct mac_source, lru_list);
551                 list_remove(&lru->hash_list);
552                 list_remove(&lru->lru_list);
553                 free(lru);
554             } else {
555                 mac_count++;
556             }
557
558             /* Create new mac source */
559             src = xmalloc(sizeof *src);
560             src->datapath_id = sw->datapath_id;
561             memcpy(src->mac, flow.dl_src, ETH_ADDR_LEN);
562             src->port = -1;
563             list_push_front(bucket, &src->hash_list);
564             list_push_back(&lrus, &src->lru_list);
565         } else {
566             /* Make 'src' most-recently-used.  */
567             list_remove(&src->lru_list);
568             list_push_back(&lrus, &src->lru_list);
569         }
570
571         if (ntohs(flow.in_port) != src->port) {
572             src->port = ntohs(flow.in_port);
573             VLOG_DBG("learned that "MAC_FMT" is on datapath %"PRIx64" port %d",
574                      MAC_ARGS(src->mac), ntohll(src->datapath_id),
575                      src->port);
576         }
577     } else {
578         VLOG_DBG("multicast packet source "MAC_FMT, MAC_ARGS(flow.dl_src));
579     }
580
581     /* Figure out the destination. */
582     out_port = OFPP_FLOOD;
583     if (!mac_is_multicast(flow.dl_dst)) {
584         struct mac_source *dst;
585         struct list *bucket;
586
587         bucket = mac_table_bucket(sw->datapath_id, flow.dl_dst);
588         LIST_FOR_EACH (dst, struct mac_source, hash_list, bucket) {
589             if (dst->datapath_id == sw->datapath_id
590                 && mac_equals(dst->mac, flow.dl_dst)) {
591                 out_port = dst->port;
592                 break;
593             }
594         }
595     }
596
597     if (out_port != OFPP_FLOOD) {
598         /* The output port is known, so add a new flow. */
599         queue_tx(sw, make_add_simple_flow(&flow, ntohl(opi->buffer_id), 
600                     out_port));
601
602         /* If the switch didn't buffer the packet, we need to send a copy. */
603         if (ntohl(opi->buffer_id) == UINT32_MAX) {
604             queue_tx(sw, make_unbuffered_packet_out(&pkt, ntohs(flow.in_port),
605                                                     out_port));
606         }
607     } else {
608         /* We don't know that MAC.  Flood the packet. */
609         struct buffer *b;
610         if (ntohl(opi->buffer_id) == UINT32_MAX) {
611             b = make_unbuffered_packet_out(&pkt, ntohs(flow.in_port), out_port);
612         } else {
613             b = make_buffered_packet_out(ntohl(opi->buffer_id), 
614                         ntohs(flow.in_port), out_port);
615         }
616         queue_tx(sw, b);
617     }
618 }
619
620 static void
621 parse_options(int argc, char *argv[])
622 {
623     static struct option long_options[] = {
624         {"hub",         no_argument, 0, 'H'},
625         {"noflow",      no_argument, 0, 'n'},
626         {"verbose",     optional_argument, 0, 'v'},
627         {"help",        no_argument, 0, 'h'},
628         {"version",     no_argument, 0, 'V'},
629 #ifdef HAVE_OPENSSL
630         {"private-key", required_argument, 0, 'p'},
631         {"certificate", required_argument, 0, 'c'},
632         {"ca-cert",     required_argument, 0, 'C'},
633 #endif
634         {0, 0, 0, 0},
635     };
636     char *short_options = long_options_to_short_options(long_options);
637
638     for (;;) {
639         int indexptr;
640         int c;
641
642         c = getopt_long(argc, argv, short_options, long_options, &indexptr);
643         if (c == -1) {
644             break;
645         }
646
647         switch (c) {
648         case 'H':
649             hub = true;
650             break;
651
652         case 'n':
653             noflow = true;
654             break;
655
656         case 'h':
657             usage();
658
659         case 'V':
660             printf("%s "VERSION" compiled "__DATE__" "__TIME__"\n", argv[0]);
661             exit(EXIT_SUCCESS);
662
663         case 'v':
664             vlog_set_verbosity(optarg);
665             break;
666
667 #ifdef HAVE_OPENSSL
668         case 'p':
669             vconn_ssl_set_private_key_file(optarg);
670             break;
671
672         case 'c':
673             vconn_ssl_set_certificate_file(optarg);
674             break;
675
676         case 'C':
677             vconn_ssl_set_ca_cert_file(optarg);
678             break;
679 #endif
680
681         case '?':
682             exit(EXIT_FAILURE);
683
684         default:
685             abort();
686         }
687     }
688     free(short_options);
689 }
690
691 static void
692 usage(void)
693 {
694     printf("%s: OpenFlow controller\n"
695            "usage: %s [OPTIONS] VCONN\n"
696            "where VCONN is one of the following:\n"
697            "  ptcp:[PORT]             listen to TCP PORT (default: %d)\n",
698            program_name, program_name);
699 #ifdef HAVE_NETLINK
700     printf("  nl:DP_IDX               via netlink to local datapath DP_IDX\n");
701 #endif
702 #ifdef HAVE_OPENSSL
703     printf("  pssl:[PORT]             listen for SSL on PORT (default: %d)\n"
704            "\nPKI configuration (required to use SSL):\n"
705            "  -p, --private-key=FILE  file with private key\n"
706            "  -c, --certificate=FILE  file with certificate for private key\n"
707            "  -C, --ca-cert=FILE      file with peer CA certificate\n",
708            OFP_SSL_PORT);
709 #endif
710     printf("\nOther options:\n"
711            "  -H, --hub               act as hub instead of learning switch\n"
712            "  -n, --noflow            pass traffic, but don't add flows\n"
713            "  -v, --verbose           set maximum verbosity level\n"
714            "  -h, --help              display this help message\n"
715            "  -V, --version           display version information\n",
716            OFP_TCP_PORT);
717     exit(EXIT_SUCCESS);
718 }