#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"
};
struct datapath {
- struct controller_connection *cc;
+ struct rconn *rconn;
time_t last_timeout;
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 *,
}
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;
}
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) {
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);
}
}
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
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. */
}
}
-/* 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)
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;
}
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,
}
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
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;
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