/* Remote connections. */
struct remote *controller; /* Connection to controller. */
struct list remotes; /* All connections (including controller). */
- struct vconn *listen_vconn;
+ struct pvconn *listen_pvconn;
time_t last_timeout;
dp->last_timeout = time_now();
list_init(&dp->remotes);
dp->controller = remote_create(dp, rconn);
- dp->listen_vconn = NULL;
+ dp->listen_pvconn = NULL;
dp->id = dpid <= UINT64_C(0xffffffffffff) ? dpid : gen_datapath_id();
dp->chain = chain_create();
if (!dp->chain) {
}
void
-dp_add_listen_vconn(struct datapath *dp, struct vconn *listen_vconn)
+dp_add_listen_pvconn(struct datapath *dp, struct pvconn *listen_pvconn)
{
- assert(!dp->listen_vconn);
- dp->listen_vconn = listen_vconn;
+ assert(!dp->listen_pvconn);
+ dp->listen_pvconn = listen_pvconn;
}
void
LIST_FOR_EACH_SAFE (r, rn, struct remote, node, &dp->remotes) {
remote_run(dp, r);
}
- if (dp->listen_vconn) {
+ if (dp->listen_pvconn) {
for (;;) {
struct vconn *new_vconn;
int retval;
- retval = vconn_accept(dp->listen_vconn, &new_vconn);
+ retval = pvconn_accept(dp->listen_pvconn, OFP_VERSION, &new_vconn);
if (retval) {
if (retval != EAGAIN) {
VLOG_WARN_RL(&rl, "accept failed (%s)", strerror(retval));
LIST_FOR_EACH (r, struct remote, node, &dp->remotes) {
remote_wait(r);
}
- if (dp->listen_vconn) {
- vconn_accept_wait(dp->listen_vconn);
+ if (dp->listen_pvconn) {
+ pvconn_wait(dp->listen_pvconn);
}
}
{
struct buffer *buffer;
struct ofp_error_msg *oem;
- oem = make_openflow_reply(sizeof(*oem)+len, OFPT_ERROR_MSG,
- sender, &buffer);
+ oem = make_openflow_reply(sizeof(*oem)+len, OFPT_ERROR, sender, &buffer);
oem->type = htons(type);
oem->code = htons(code);
memcpy(oem->data, data, len);
int table_idx, time_t now)
{
struct ofp_flow_stats *ofs;
- int length = sizeof *ofs + sizeof *ofs->actions * flow->n_actions;
+ int length = sizeof *ofs + sizeof *ofs->actions * flow->sf_acts->n_actions;
ofs = buffer_put_uninit(buffer, length);
ofs->length = htons(length);
ofs->table_id = table_idx;
memset(ofs->pad2, 0, sizeof ofs->pad2);
ofs->packet_count = htonll(flow->packet_count);
ofs->byte_count = htonll(flow->byte_count);
- memcpy(ofs->actions, flow->actions,
- sizeof *ofs->actions * flow->n_actions);
+ memcpy(ofs->actions, flow->sf_acts->actions,
+ sizeof *ofs->actions * flow->sf_acts->n_actions);
}
\f
if (flow != NULL) {
flow_used(flow, buffer);
execute_actions(dp, buffer, port_no(dp, p),
- &key, flow->actions, flow->n_actions, false);
+ &key, flow->sf_acts->actions,
+ flow->sf_acts->n_actions, false);
return 0;
} else {
return -ESRCH;
flow->idle_timeout = ntohs(ofm->idle_timeout);
flow->hard_timeout = ntohs(ofm->hard_timeout);
flow->used = flow->created = time_now();
- flow->n_actions = n_actions;
+ flow->sf_acts->n_actions = n_actions;
flow->byte_count = 0;
flow->packet_count = 0;
- memcpy(flow->actions, ofm->actions, n_actions * sizeof *flow->actions);
+ memcpy(flow->sf_acts->actions, ofm->actions,
+ n_actions * sizeof *flow->sf_acts->actions);
/* Act. */
error = chain_insert(dp->chain, flow);
return error;
}
+static int
+mod_flow(struct datapath *dp, const struct ofp_flow_mod *ofm)
+{
+ int error = -ENOMEM;
+ int n_actions;
+ int i;
+ struct sw_flow_key key;
+
+
+ /* To prevent loops, make sure there's no action to send to the
+ * OFP_TABLE virtual port.
+ */
+ n_actions = (ntohs(ofm->header.length) - sizeof *ofm)
+ / sizeof *ofm->actions;
+ for (i=0; i<n_actions; i++) {
+ const struct ofp_action *a = &ofm->actions[i];
+
+ if (a->type == htons(OFPAT_OUTPUT)
+ && (a->arg.output.port == htons(OFPP_TABLE)
+ || a->arg.output.port == htons(OFPP_NONE)
+ || a->arg.output.port == ofm->match.in_port)) {
+ /* xxx Send fancy new error message? */
+ goto error;
+ }
+ }
+
+ flow_extract_match(&key, &ofm->match);
+ chain_modify(dp->chain, &key, ofm->actions, n_actions);
+
+ if (ntohl(ofm->buffer_id) != UINT32_MAX) {
+ struct buffer *buffer = retrieve_buffer(ntohl(ofm->buffer_id));
+ if (buffer) {
+ struct sw_flow_key skb_key;
+ uint16_t in_port = ntohs(ofm->match.in_port);
+ flow_extract(buffer, in_port, &skb_key.flow);
+ execute_actions(dp, buffer, in_port, &skb_key,
+ ofm->actions, n_actions, false);
+ } else {
+ error = -ESRCH;
+ }
+ }
+ return error;
+
+error:
+ if (ntohl(ofm->buffer_id) != (uint32_t) -1)
+ discard_buffer(ntohl(ofm->buffer_id));
+ return error;
+}
+
static int
recv_flow(struct datapath *dp, const struct sender *sender UNUSED,
const void *msg)
if (command == OFPFC_ADD) {
return add_flow(dp, ofm);
+ } else if (command == OFPFC_MODIFY) {
+ return mod_flow(dp, ofm);
} else if (command == OFPFC_DELETE) {
struct sw_flow_key key;
flow_extract_match(&key, &ofm->match);
struct ofp_header *oh;
oh = (struct ofp_header *) msg;
- assert(oh->version == OFP_VERSION);
if (ntohs(oh->length) > length)
return -EINVAL;