goto exit;
}
}
+ if (insts[OVSINST_OFPIT11_CLEAR_ACTIONS]) {
+ instruction_get_OFPIT11_CLEAR_ACTIONS(
+ insts[OVSINST_OFPIT11_CLEAR_ACTIONS]);
+ ofpact_put_CLEAR_ACTIONS(ofpacts);
+ }
+ /* TODO:XXX Write-Actions */
+ /* TODO:XXX Write-Metadata */
+ if (insts[OVSINST_OFPIT11_GOTO_TABLE]) {
+ const struct ofp11_instruction_goto_table *oigt;
+ struct ofpact_goto_table *ogt;
+
+ oigt = instruction_get_OFPIT11_GOTO_TABLE(
+ insts[OVSINST_OFPIT11_GOTO_TABLE]);
+ ogt = ofpact_put_GOTO_TABLE(ofpacts);
+ ogt->table_id = oigt->table_id;
+ }
- if (insts[OVSINST_OFPIT11_GOTO_TABLE] ||
- insts[OVSINST_OFPIT11_WRITE_METADATA] ||
- insts[OVSINST_OFPIT11_WRITE_ACTIONS] ||
- insts[OVSINST_OFPIT11_CLEAR_ACTIONS]) {
+ if (insts[OVSINST_OFPIT11_WRITE_METADATA] ||
+ insts[OVSINST_OFPIT11_WRITE_ACTIONS]) {
error = OFPERR_OFPBIC_UNSUP_INST;
goto exit;
}
case OFPACT_EXIT:
return 0;
+ case OFPACT_CLEAR_ACTIONS:
+ case OFPACT_GOTO_TABLE:
+ return 0;
+
default:
NOT_REACHED();
}
case OFPACT_SET_IPV4_DSCP:
case OFPACT_SET_L4_SRC_PORT:
case OFPACT_SET_L4_DST_PORT:
+ case OFPACT_CLEAR_ACTIONS:
+ case OFPACT_GOTO_TABLE:
NOT_REACHED();
}
}
= htons(ofpact_get_SET_L4_DST_PORT(a)->port);
break;
+ case OFPACT_CLEAR_ACTIONS:
+ case OFPACT_GOTO_TABLE:
+ /* TODO:XXX */
+ break;
+
case OFPACT_CONTROLLER:
case OFPACT_OUTPUT_REG:
case OFPACT_BUNDLE:
= htons(ofpact_get_SET_L4_DST_PORT(a)->port);
break;
+ case OFPACT_CLEAR_ACTIONS:
+ case OFPACT_GOTO_TABLE:
+ NOT_REACHED();
+
case OFPACT_CONTROLLER:
case OFPACT_OUTPUT_REG:
case OFPACT_BUNDLE:
return openflow->size - start_size;
}
-void
-ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[],
- size_t ofpacts_len,
- struct ofpbuf *openflow)
+static void
+ofpacts_update_instruction_actions(struct ofpbuf *openflow, size_t ofs)
{
struct ofp11_instruction_actions *oia;
- size_t ofs;
-
- /* Put an OFPIT11_APPLY_ACTIONS instruction and fill it in. */
- ofs = openflow->size;
- instruction_put_OFPIT11_APPLY_ACTIONS(openflow);
- ofpacts_put_openflow11_actions(ofpacts, ofpacts_len, openflow);
/* Update the instruction's length (or, if it's empty, delete it). */
oia = ofpbuf_at_assert(openflow, ofs, sizeof *oia);
openflow->size = ofs;
}
}
+
+void
+ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[],
+ size_t ofpacts_len,
+ struct ofpbuf *openflow)
+{
+ const struct ofpact *a;
+
+ OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
+ /* TODO:XXX Write-Actions */
+ /* TODO:XXX Write-Metadata */
+ if (a->type == OFPACT_CLEAR_ACTIONS) {
+ struct ofp11_instruction *oi;
+ oi = instruction_put_OFPIT11_CLEAR_ACTIONS(openflow);
+ } else if (a->type == OFPACT_GOTO_TABLE) {
+ struct ofp11_instruction_goto_table *oigt;
+
+ oigt = instruction_put_OFPIT11_GOTO_TABLE(openflow);
+ oigt->table_id = ofpact_get_GOTO_TABLE(a)->table_id;
+ memset(oigt->pad, 0, sizeof oigt->pad);
+ } else if (!ofpact_is_instruction(a)) {
+ /* Apply-actions */
+ const size_t ofs = openflow->size;
+ const size_t ofpacts_len_left =
+ (uint8_t*)ofpact_end(ofpacts, ofpacts_len) - (uint8_t*)a;
+ const struct ofpact *action;
+ const struct ofpact *processed = a;
+
+ instruction_put_OFPIT11_APPLY_ACTIONS(openflow);
+ OFPACT_FOR_EACH(action, a, ofpacts_len_left) {
+ if (ofpact_is_instruction(action)) {
+ break;
+ }
+ ofpact_to_openflow11(action, openflow);
+ processed = action;
+ }
+ ofpacts_update_instruction_actions(openflow, ofs);
+ a = processed;
+ }
+ }
+}
\f
/* Returns true if 'action' outputs to 'port', false otherwise. */
static bool
case OFPACT_AUTOPATH:
case OFPACT_NOTE:
case OFPACT_EXIT:
+ case OFPACT_CLEAR_ACTIONS:
+ case OFPACT_GOTO_TABLE:
default:
return false;
}
case OFPACT_EXIT:
ds_put_cstr(s, "exit");
break;
+
+ case OFPACT_CLEAR_ACTIONS:
+ ds_put_format(s, "%s",
+ ofpact_instruction_name_from_type(
+ OVSINST_OFPIT11_CLEAR_ACTIONS));
+ break;
+
+ case OFPACT_GOTO_TABLE:
+ ds_put_format(s, "%s:%"PRIu8,
+ ofpact_instruction_name_from_type(
+ OVSINST_OFPIT11_GOTO_TABLE),
+ ofpact_get_GOTO_TABLE(a)->table_id);
+ break;
}
}
if (a != ofpacts) {
ds_put_cstr(string, ",");
}
+
+ /* TODO:XXX write-actions */
+ /* TODO:XXX write-metadata */
ofpact_format(a, string);
}
}