/* Handles flow mod messages with MODIFY command. */ static ofl_err flow_table_modify(struct flow_table *table, struct ofl_msg_flow_mod *mod, bool strict, bool *match_kept, bool *insts_kept) { struct flow_entry *entry; bool match_found; match_found = false; LIST_FOR_EACH (entry, struct flow_entry, match_node, &table->match_entries) { if (flow_entry_matches(entry, mod, strict, true/*check_cookie*/)) { flow_entry_replace_instructions(entry, mod->instructions_num, mod->instructions); *insts_kept = true; match_found = true; } } /* NOTE: if modify does not modify any entries, it acts like an add according to spec. */ if (!match_found) { return flow_table_add(table, mod, false, match_kept, insts_kept); } return 0; }
ofl_err flow_table_flow_mod(struct flow_table *table, struct ofl_msg_flow_mod *mod, bool *match_kept, bool *insts_kept) { switch (mod->command) { case (OFPFC_ADD): { bool overlap = ((mod->flags & OFPFF_CHECK_OVERLAP) != 0); return flow_table_add(table, mod, overlap, match_kept, insts_kept); } case (OFPFC_MODIFY): { return flow_table_modify(table, mod, false, insts_kept); } case (OFPFC_MODIFY_STRICT): { return flow_table_modify(table, mod, true, insts_kept); } case (OFPFC_DELETE): { return flow_table_delete(table, mod, false); } case (OFPFC_DELETE_STRICT): { return flow_table_delete(table, mod, true); } default: { return ofl_error(OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_COMMAND); } } }