From bce273b4c0c4ab92bdc0386b4da41a4f91e746db Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 27 Mar 2008 15:16:57 -0700 Subject: [PATCH] Add abstraction of packet queue, and use it in the controller. The packet queue abstraction will also be used in the userspace switch. --- controller/controller.c | 66 +++++---------------------- include/Makefile.am | 1 + include/queue.h | 38 ++++++++++++++++ lib/Makefile.am | 1 + lib/queue.c | 99 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 151 insertions(+), 54 deletions(-) create mode 100644 include/queue.h create mode 100644 lib/queue.c diff --git a/controller/controller.c b/controller/controller.c index f4a53f5d..458f621f 100644 --- a/controller/controller.c +++ b/controller/controller.c @@ -40,6 +40,7 @@ #include "ofp-print.h" #include "openflow.h" #include "poll-loop.h" +#include "queue.h" #include "time.h" #include "util.h" #include "vconn-ssl.h" @@ -60,8 +61,7 @@ struct switch_ { uint64_t datapath_id; time_t last_control_hello; - int n_txq; - struct buffer *txq, *tx_tail; + struct queue txq; }; /* -H, --hub: Use dumb hub instead of learning switch? */ @@ -185,7 +185,7 @@ main(int argc, char *argv[]) } } else { vconn_recv_wait(this->vconn); - if (this->n_txq) { + if (this->txq.n) { vconn_send_wait(this->vconn); } } @@ -214,19 +214,13 @@ static int do_switch_send(struct switch_ *this) { int retval = 0; - if (this->n_txq) { - struct buffer *next = this->txq->next; - - retval = vconn_send(this->vconn, this->txq); + if (this->txq.n) { + struct buffer *next = this->txq.head->next; + retval = vconn_send(this->vconn, this->txq.head); if (retval) { return retval; } - - this->txq = next; - if (this->txq == NULL) { - this->tx_tail = NULL; - } - this->n_txq--; + queue_advance_head(&this->txq, next); return 0; } return EAGAIN; @@ -254,9 +248,7 @@ new_switch(const char *name, struct vconn *vconn) memset(this, 0, sizeof *this); this->name = xstrdup(name); this->vconn = vconn; - this->n_txq = 0; - this->txq = NULL; - this->tx_tail = NULL; + queue_init(&this->txq); this->last_control_hello = 0; if (!vconn_is_passive(vconn)) { send_control_hello(this); @@ -268,14 +260,9 @@ static void close_switch(struct switch_ *this) { if (this) { - struct buffer *cur, *next; - free(this->name); vconn_close(this->vconn); - for (cur = this->txq; cur != NULL; cur = next) { - next = cur->next; - buffer_delete(cur); - } + queue_destroy(&this->txq); free(this); } } @@ -303,40 +290,10 @@ send_control_hello(struct switch_ *this) } } -static void -check_txq(struct switch_ *this UNUSED) -{ -#if 0 - struct buffer *iter; - size_t n; - - assert(this->n_txq == 0 - ? this->txq == NULL && this->tx_tail == NULL - : this->txq != NULL && this->tx_tail != NULL); - - n = 0; - for (iter = this->txq; iter != NULL; iter = iter->next) { - n++; - assert((iter->next != NULL) == (iter != this->tx_tail)); - } - assert(n == this->n_txq); -#endif -} - static void queue_tx(struct switch_ *this, struct buffer *b) { - check_txq(this); - - b->next = NULL; - if (this->n_txq++) { - this->tx_tail->next = b; - } else { - this->txq = b; - } - this->tx_tail = b; - - check_txq(this); + queue_push_tail(&this->txq, b); } static void @@ -374,7 +331,8 @@ process_packet(struct switch_ *sw, struct buffer *msg) } if (oh->type == OFPT_PACKET_IN) { - if (sw->n_txq >= MAX_TXQ) { + if (sw->txq.n >= MAX_TXQ) { + /* FIXME: ratelimit. */ VLOG_WARN("%s: tx queue overflow", sw->name); } else if (noflow) { process_noflow(sw, msg->data); diff --git a/include/Makefile.am b/include/Makefile.am index c1651e13..60999183 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -17,6 +17,7 @@ noinst_HEADERS = \ openflow-netlink.h \ packets.h \ poll-loop.h \ + queue.h \ socket-util.h \ util.h \ vconn.h \ diff --git a/include/queue.h b/include/queue.h new file mode 100644 index 00000000..6a1027a4 --- /dev/null +++ b/include/queue.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2008 Board of Trustees, Leland Stanford Jr. University. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef QUEUE_H +#define QUEUE_H 1 + +/* Packet queue. */ +struct queue { + int n; + struct buffer *head; + struct buffer *tail; +}; + +void queue_init(struct queue *); +void queue_destroy(struct queue *); +void queue_clear(struct queue *); +void queue_advance_head(struct queue *, struct buffer *next); +void queue_push_tail(struct queue *, struct buffer *); + +#endif /* queue.h */ diff --git a/lib/Makefile.am b/lib/Makefile.am index 906b5d89..a91631bc 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -13,6 +13,7 @@ libopenflow_la_SOURCES = \ list.c \ ofp-print.c \ poll-loop.c \ + queue.c \ socket-util.c \ util.c \ vconn-tcp.c \ diff --git a/lib/queue.c b/lib/queue.c new file mode 100644 index 00000000..7f3f8178 --- /dev/null +++ b/lib/queue.c @@ -0,0 +1,99 @@ +/* Copyright (C) 2008 Board of Trustees, Leland Stanford Jr. University. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "queue.h" +#include +#include "buffer.h" + +static void check_queue(struct queue *q); + +void +queue_init(struct queue *q) +{ + q->n = 0; + q->head = NULL; + q->tail = NULL; +} + +void +queue_destroy(struct queue *q) +{ + struct buffer *cur, *next; + for (cur = q->head; cur != NULL; cur = next) { + next = cur->next; + buffer_delete(cur); + } +} + +void +queue_clear(struct queue *q) +{ + queue_destroy(q); + queue_init(q); +} + +void +queue_advance_head(struct queue *q, struct buffer *next) +{ + assert(q->n); + assert(q->head); + q->head = next; + if (q->head == NULL) { + q->tail = NULL; + } + q->n--; +} + +void +queue_push_tail(struct queue *q, struct buffer *b) +{ + check_queue(q); + + b->next = NULL; + if (q->n++) { + q->tail->next = b; + } else { + q->head = b; + } + q->tail = b; + + check_queue(q); +} + +static void +check_queue(struct queue *q) +{ +#if 0 + struct buffer *iter; + size_t n; + + assert(q->n == 0 + ? q->head == NULL && q->tail == NULL + : q->head != NULL && q->tail != NULL); + + n = 0; + for (iter = q->head; iter != NULL; iter = iter->next) { + n++; + assert((iter->next != NULL) == (iter != q->tail)); + } + assert(n == q->n); +#endif +} -- 2.30.2