ofproto_check_ofpacts(struct ofproto *ofproto,
const struct ofpact ofpacts[], size_t ofpacts_len,
struct flow *flow, uint8_t table_id,
- bool enforce_consistency)
+ const struct ofp_header *oh)
{
enum ofperr error;
uint32_t mid;
error = ofpacts_check(ofpacts, ofpacts_len, flow,
u16_to_ofp(ofproto->max_ports), table_id,
- enforce_consistency);
+ oh && oh->version > OFP10_VERSION);
if (error) {
return error;
}
/* Verify actions against packet, then send packet if successful. */
in_port_.ofp_port = po.in_port;
flow_extract(payload, 0, 0, NULL, &in_port_, &flow);
- error = ofproto_check_ofpacts(p, po.ofpacts, po.ofpacts_len, &flow, 0,
- oh->version > OFP10_VERSION);
+ error = ofproto_check_ofpacts(p, po.ofpacts, po.ofpacts_len, &flow, 0, oh);
if (!error) {
error = p->ofproto_class->packet_out(p, payload, &flow,
po.ofpacts, po.ofpacts_len);
/* Verify actions. */
error = ofproto_check_ofpacts(ofproto, fm->ofpacts, fm->ofpacts_len,
- &fm->match.flow, table_id,
- request && request->version > OFP10_VERSION);
+ &fm->match.flow, table_id, request);
if (error) {
cls_rule_destroy(&cr);
return error;
enum ofperr error;
size_t i;
+ /* Verify actions before we start to modify any rules, to avoid partial
+ * flow table modifications. */
+ for (i = 0; i < rules->n; i++) {
+ struct rule *rule = rules->rules[i];
+
+ error = ofproto_check_ofpacts(ofproto, fm->ofpacts, fm->ofpacts_len,
+ &fm->match.flow, rule->table_id,
+ request);
+ if (error) {
+ return error;
+ }
+ }
+
type = fm->command == OFPFC_ADD ? OFOPERATION_REPLACE : OFOPERATION_MODIFY;
group = ofopgroup_create(ofproto, ofconn, request, fm->buffer_id);
error = OFPERR_OFPBRC_EPERM;
continue;
}
- /* Verify actions, enforce consistency check on OF1.1+. */
- error = ofpacts_check(fm->ofpacts, fm->ofpacts_len, &fm->match.flow,
- u16_to_ofp(ofproto->max_ports), rule->table_id,
- request && request->version > OFP10_VERSION);
- if (error) {
- return error;
- }
-
actions_changed = !ofpacts_equal(fm->ofpacts, fm->ofpacts_len,
rule->actions->ofpacts,
rule->actions->ofpacts_len);