Rename controller_connection to rconn and use it in secchan also.
[openvswitch] / switch / datapath.c
index 34914dfd04c3b40b643c157436a48531f76c7b92..b59e789b3493a4a8d393f30833529ee1645eaa8f 100644 (file)
 #include <string.h>
 #include "buffer.h"
 #include "chain.h"
-#include "controller.h"
 #include "flow.h"
 #include "netdev.h"
 #include "packets.h"
 #include "poll-loop.h"
+#include "rconn.h"
 #include "table.h"
 #include "xtoxll.h"
 
@@ -73,7 +73,7 @@ struct sw_port {
 };
 
 struct datapath {
-    struct controller_connection *cc;
+    struct rconn *rconn;
 
     time_t last_timeout;
 
@@ -99,6 +99,7 @@ void dp_send_hello(struct datapath *);
 void dp_update_port_flags(struct datapath *dp, const struct ofp_phy_port *opp);
 void dp_output_control(struct datapath *, struct buffer *, int in_port,
                        size_t max_len, int reason);
+static void send_flow_expired(struct datapath *, struct sw_flow *);
 static void send_port_status(struct sw_port *p, uint8_t status);
 static void del_switch_port(struct sw_port *p);
 static void execute_actions(struct datapath *, struct buffer *,
@@ -156,7 +157,7 @@ gen_datapath_id(void)
 }
 
 int
-dp_new(struct datapath **dp_, uint64_t dpid, struct controller_connection *cc)
+dp_new(struct datapath **dp_, uint64_t dpid, struct rconn *rconn)
 {
     struct datapath *dp;
 
@@ -166,7 +167,7 @@ dp_new(struct datapath **dp_, uint64_t dpid, struct controller_connection *cc)
     }
 
     dp->last_timeout = time(0);
-    dp->cc = cc;
+    dp->rconn = rconn;
     dp->id = dpid <= UINT64_C(0xffffffffffff) ? dpid : gen_datapath_id();
     dp->chain = chain_create();
     if (!dp->chain) {
@@ -220,7 +221,15 @@ dp_run(struct datapath *dp)
     int i;
 
     if (now != dp->last_timeout) {
-        chain_timeout(dp->chain, dp);
+        struct list deleted = LIST_INITIALIZER(&deleted);
+        struct sw_flow *f, *n;
+
+        chain_timeout(dp->chain, &deleted);
+        LIST_FOR_EACH_SAFE (f, n, struct sw_flow, node, &deleted) {
+            send_flow_expired(dp, f);
+            list_remove(&f->node);
+            flow_free(f);
+        }
         dp->last_timeout = now;
     }
     poll_timer_wait(1000);
@@ -249,6 +258,19 @@ dp_run(struct datapath *dp)
         }
     }
     buffer_delete(buffer);
+
+    /* Process a number of commands from the controller, but cap it at a
+     * reasonable number so that other processing doesn't starve. */
+    for (i = 0; i < 50; i++) {
+        struct buffer *buffer = rconn_recv(dp->rconn);
+        if (!buffer) {
+            break;
+        }
+        fwd_control_input(dp, buffer->data, buffer->size);
+        buffer_delete(buffer);
+    }
+
+    rconn_run(dp->rconn);
 }
 
 void
@@ -259,6 +281,7 @@ dp_wait(struct datapath *dp)
     LIST_FOR_EACH (p, struct sw_port, node, &dp->port_list) {
         netdev_recv_wait(p->netdev);
     }
+    rconn_recv_wait(dp->rconn);
 }
 
 /* Delete 'p' from switch. */
@@ -344,11 +367,12 @@ dp_output_port(struct datapath *dp, struct buffer *buffer,
     }
 }
 
-/* Takes ownership of 'buffer' and transmits it to 'dp''s controller.  If
- * 'buffer_id' != -1, then only the first 64 bytes of 'buffer' are sent;
- * otherwise, all of 'buffer' is sent.  'reason' indicates why 'buffer' is
- * being sent. 'max_len' sets the maximum number of bytes that the caller wants
- * to be sent; a value of 0 indicates the entire packet should be sent. */
+/* Takes ownership of 'buffer' and transmits it to 'dp''s controller.  If the
+ * packet can be saved in a buffer, then only the first max_len bytes of
+ * 'buffer' are sent; otherwise, all of 'buffer' is sent.  'reason' indicates
+ * why 'buffer' is being sent. 'max_len' sets the maximum number of bytes that
+ * the caller wants to be sent; a value of 0 indicates the entire packet should
+ * be sent. */
 void
 dp_output_control(struct datapath *dp, struct buffer *buffer, int in_port,
                   size_t max_len, int reason)
@@ -359,7 +383,7 @@ dp_output_control(struct datapath *dp, struct buffer *buffer, int in_port,
 
     buffer_id = save_buffer(buffer);
     total_len = buffer->size;
-    if (buffer_id != UINT32_MAX && max_len > buffer->size) {
+    if (buffer_id != UINT32_MAX && buffer->size > max_len) {
         buffer->size = max_len;
     }
 
@@ -373,7 +397,7 @@ dp_output_control(struct datapath *dp, struct buffer *buffer, int in_port,
     opi->in_port        = htons(in_port);
     opi->reason         = reason;
     opi->pad            = 0;
-    controller_send(dp->cc, buffer);
+    rconn_send(dp->rconn, buffer);
 }
 
 static void fill_port_desc(struct datapath *dp, struct sw_port *p,
@@ -419,7 +443,7 @@ dp_send_hello(struct datapath *dp)
     }
     odh = buffer_at_assert(buffer, 0, sizeof *odh);
     odh->header.length = htons(buffer->size);
-    controller_send(dp->cc, buffer);
+    rconn_send(dp->rconn, buffer);
 }
 
 void
@@ -450,11 +474,11 @@ send_port_status(struct sw_port *p, uint8_t status)
     ops->header.xid     = htonl(0);
     ops->reason         = status;
     fill_port_desc(p->dp, p, &ops->desc);
-    controller_send(p->dp->cc, buffer);
+    rconn_send(p->dp->rconn, buffer);
 }
 
 void
-dp_send_flow_expired(struct datapath *dp, struct sw_flow *flow)
+send_flow_expired(struct datapath *dp, struct sw_flow *flow)
 {
     struct buffer *buffer;
     struct ofp_flow_expired *ofe;
@@ -468,7 +492,7 @@ dp_send_flow_expired(struct datapath *dp, struct sw_flow *flow)
     ofe->duration   = htonl(flow->timeout - flow->max_idle - flow->created);
     ofe->packet_count   = htonll(flow->packet_count);
     ofe->byte_count     = htonll(flow->byte_count);
-    controller_send(dp->cc, buffer);
+    rconn_send(dp->rconn, buffer);
 }
 \f
 /* 'buffer' was received on 'in_port', a physical switch port between 0 and