static void ofport_free(struct ofport *);
static void hton_ofp_phy_port(struct ofp_phy_port *);
-static void xlate_actions(const union ofp_action *in, size_t n_in,
- const flow_t *flow, struct ofproto *ofproto,
- bool revalidating,
- struct odp_actions *out, tag_type *tags);
+static int xlate_actions(const union ofp_action *in, size_t n_in,
+ const flow_t *flow, struct ofproto *ofproto,
+ bool revalidating,
+ struct odp_actions *out, tag_type *tags);
#define UNKNOWN_SUPER ((struct rule *)-1)
struct rule {
struct odp_actions odp_actions;
int error;
- xlate_actions(actions, n_actions, flow, p, false, &odp_actions, NULL);
- error = dpif_execute(&p->dpif, flow->in_port, odp_actions.actions,
- odp_actions.n_actions, packet);
- odp_actions_free(&odp_actions);
- return error;
+ error = xlate_actions(actions, n_actions, flow, p, false, &odp_actions,
+ NULL);
+ if (error) {
+ return error;
+ }
+
+ /* XXX Should we translate the dpif_execute() errno value into an OpenFlow
+ * error code? */
+ dpif_execute(&p->dpif, flow->in_port, odp_actions.actions,
+ odp_actions.n_actions, packet);
+ return 0;
}
void
odp_flow.actions = odp_actions.actions;
odp_flow.n_actions = odp_actions.n_actions;
dpif_flow_add(&p->dpif, &odp_flow);
- odp_actions_free(&odp_actions);
} else {
assert(!packet);
}
}
}
-static void
+static int
xlate_actions(const union ofp_action *in, size_t n_in,
const flow_t *flow, struct ofproto *ofproto, bool revalidating,
struct odp_actions *out, tag_type *tags)
ctx.out = out;
ctx.tags = tags ? tags : &no_tags;
do_xlate_actions(in, n_in, &ctx);
+ if (odp_actions_overflow(out)) {
+ odp_actions_init(out);
+ return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_TOO_MANY);
+ }
+ return 0;
}
static int
}
flow_extract(&payload, ofp_port_to_odp_port(ntohs(opo->in_port)), &flow);
- xlate_actions((const union ofp_action *) opo->actions, n_actions, &flow,
- p, false, &actions, NULL);
+ error = xlate_actions((const union ofp_action *) opo->actions, n_actions,
+ &flow, p, false, &actions, NULL);
+ if (error) {
+ return error;
+ }
+
dpif_execute(&p->dpif, flow.in_port, actions.actions, actions.n_actions,
&payload);
- odp_actions_free(&actions);
ofpbuf_delete(buffer);
return 0;
}
flow_extract(packet, in_port, &flow);
- xlate_actions(rule->actions, rule->n_actions, &flow, p, false,
- &actions, NULL);
+ error = xlate_actions(rule->actions, rule->n_actions, &flow, p, false,
+ &actions, NULL);
+ if (error) {
+ return error;
+ }
+
error = dpif_execute(&p->dpif, in_port,
actions.actions, actions.n_actions, packet);
if (!error) {
*byte_count = packet->size;
}
- odp_actions_free(&actions);
ofpbuf_delete(packet);
return 0;
struct ofp_flow_mod *ofm, size_t n_actions)
{
struct rule *rule, *displaced_rule;
- int buffer_error = 0;
+ int error = 0;
rule = xmalloc(sizeof *rule);
cls_rule_from_match(&rule->cr, &ofm->match, ntohs(ofm->priority));
if (ofm->buffer_id != htonl(UINT32_MAX)) {
int byte_count = 0;
- buffer_error = send_buffered(p, ofconn, ntohl(ofm->buffer_id),
- rule, &byte_count);
+ error = send_buffered(p, ofconn, ntohl(ofm->buffer_id),
+ rule, &byte_count);
rule->byte_count += byte_count;
rule->packet_count += byte_count > 0;
}
} else {
struct odp_flow odp_flow;
struct odp_actions actions;
+ int retval;
- xlate_actions((const union ofp_action *) ofm->actions, n_actions,
- &rule->cr.flow, p, false, &actions, NULL);
+ retval = xlate_actions((const union ofp_action *) ofm->actions,
+ n_actions, &rule->cr.flow, p, false, &actions,
+ NULL);
+ if (retval) {
+ error = retval;
+ }
odp_flow.key = rule->cr.flow;
odp_flow.actions = actions.actions;
}
rule_destroy(displaced_rule);
}
- odp_actions_free(&actions);
}
- return buffer_error;
+ return error;
}
static int
struct odp_flow odp_flow;
struct odp_actions actions;
+ /* XXX We should check the return value here. */
xlate_actions((const union ofp_action *) ofm->actions, n_actions,
&rule->cr.flow, p, false, &actions, NULL);
odp_flow.key = rule->cr.flow;
odp_flow.actions = actions.actions;
odp_flow.n_actions = actions.n_actions;
dpif_flow_add(&p->dpif, &odp_flow);
- odp_actions_free(&actions);
update_stats(rule, &odp_flow.stats);
}
rule_make_actions(p, old_sr, false, &actions);
dpif_execute(&p->dpif, msg->port,
actions.actions, actions.n_actions, &payload);
- odp_actions_free(&actions);
ofpbuf_delete(packet);
return;
} else {
/* Execute subrule on packet. */
dpif_execute(&p->dpif, msg->port, actions.actions, actions.n_actions,
&payload);
- odp_actions_free(&actions);
ofpbuf_delete(packet);
}
\f
rule_make_actions(p, rule, true, &actions);
dpif_flow_set_actions(&p->dpif, flow, actions.actions,
actions.n_actions);
- odp_actions_free(&actions);
return true;
}