Esempio n. 1
0
bool
flow_entry_overlaps(struct flow_entry *entry, struct ofl_msg_flow_mod *mod) {
    return (entry->stats->priority == mod->priority &&
            (mod->out_port == OFPP_ANY || flow_entry_has_out_port(entry, mod->out_port)) &&
            (mod->out_group == OFPG_ANY || flow_entry_has_out_group(entry, mod->out_group)) &&
            flow_entry_matches(entry, mod, false));
}
Esempio n. 2
0
/* Handles flow mod messages with DELETE command. */
static ofl_err
flow_table_delete(struct flow_table *table, struct ofl_msg_flow_mod *mod, bool strict) {
    struct flow_entry *entry, *next;

    LIST_FOR_EACH_SAFE (entry, next, struct flow_entry, match_node, &table->match_entries) {
        if (flow_entry_matches(entry, mod, strict, true/*check_cookie*/)) {
             flow_entry_remove(entry, OFPRR_DELETE);
        }
    }

    return 0;
}
Esempio n. 3
0
/* Handles flow mod messages with MODIFY command. 
    If the flow doesn't exists don't do nothing*/
static ofl_err
flow_table_modify(struct flow_table *table, struct ofl_msg_flow_mod *mod, bool strict, bool *insts_kept) {
    struct flow_entry *entry;

    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;
        }
    }

    return 0;
}
Esempio n. 4
0
/* Handles flow mod messages with ADD command. */
static ofl_err
flow_table_add(struct flow_table *table, struct ofl_msg_flow_mod *mod, bool check_overlap, bool *match_kept, bool *insts_kept) {
    // Note: new entries will be placed behind those with equal priority
    struct flow_entry *entry, *new_entry;

    LIST_FOR_EACH (entry, struct flow_entry, match_node, &table->match_entries) {
        if (check_overlap && flow_entry_overlaps(entry, mod)) {
            return ofl_error(OFPET_FLOW_MOD_FAILED, OFPFMFC_OVERLAP);
        }

        /* if the entry equals, replace the old one */
        if (flow_entry_matches(entry, mod, true/*strict*/, false/*check_cookie*/)) {
            new_entry = flow_entry_create(table->dp, table, mod);
            *match_kept = true;
            *insts_kept = true;

            /* NOTE: no flow removed message should be generated according to spec. */
            list_replace(&new_entry->match_node, &entry->match_node);
            list_remove(&entry->hard_node);
            list_remove(&entry->idle_node);
            flow_entry_destroy(entry);
            add_to_timeout_lists(table, new_entry);
            return 0;
        }

        if (mod->priority > entry->stats->priority) {
            break;
        }
    }

    if (table->stats->active_count == FLOW_TABLE_MAX_ENTRIES) {
        return ofl_error(OFPET_FLOW_MOD_FAILED, OFPFMFC_TABLE_FULL);
    }
    table->stats->active_count++;

    new_entry = flow_entry_create(table->dp, table, mod);
    *match_kept = true;
    *insts_kept = true;

    list_insert(&entry->match_node, &new_entry->match_node);
    add_to_timeout_lists(table, new_entry);

    return 0;
}
/* 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;
}