/*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
* Copyright (c) 2010 Jean Tourrilhes - HP-Labs.
*
* Licensed under the Apache License, Version 2.0 (the "License");
struct oftable *table;
struct ofopgroup *group;
struct rule *victim;
- struct cls_rule cr;
struct rule *rule;
+ uint8_t table_id;
int error;
error = check_table_id(ofproto, fm->table_id);
/* Pick table. */
if (fm->table_id == 0xff) {
- uint8_t table_id;
if (ofproto->ofproto_class->rule_choose_table) {
error = ofproto->ofproto_class->rule_choose_table(ofproto,
&fm->match,
return error;
}
assert(table_id < ofproto->n_tables);
- table = &ofproto->tables[table_id];
} else {
- table = &ofproto->tables[0];
+ table_id = 0;
}
} else if (fm->table_id < ofproto->n_tables) {
- table = &ofproto->tables[fm->table_id];
+ table_id = fm->table_id;
} else {
return OFPERR_OFPBRC_BAD_TABLE_ID;
}
+ table = &ofproto->tables[table_id];
+
if (table->flags & OFTABLE_READONLY) {
return OFPERR_OFPBRC_EPERM;
}
cls_rule_init(&rule->cr, &fm->match, fm->priority);
/* Serialize against pending deletion. */
- if (is_flow_deletion_pending(ofproto, &cr, table - ofproto->tables)) {
+ if (is_flow_deletion_pending(ofproto, &rule->cr, table_id)) {
cls_rule_destroy(&rule->cr);
ofproto->ofproto_class->rule_dealloc(rule);
return OFPROTO_POSTPONE;
new_cookie = (fm->new_cookie != htonll(UINT64_MAX)
? fm->new_cookie
: rule->flow_cookie);
- if (!actions_changed && new_cookie == rule->flow_cookie) {
- /* No change at all. */
- continue;
- }
op = ofoperation_create(group, rule, OFOPERATION_MODIFY, 0);
rule->flow_cookie = new_cookie;
LIST_FOR_EACH_SAFE (op, next_op, group_node, &group->ops) {
struct rule *rule = op->rule;
- if (!op->error && !ofproto_rule_is_hidden(rule)) {
+ /* We generally want to report the change to active OpenFlow flow
+ monitors (e.g. NXST_FLOW_MONITOR). There are three exceptions:
+
+ - The operation failed.
+
+ - The affected rule is not visible to controllers.
+
+ - The operation's only effect was to update rule->modified. */
+ if (!(op->error
+ || ofproto_rule_is_hidden(rule)
+ || (op->type == OFOPERATION_MODIFY
+ && op->ofpacts
+ && rule->flow_cookie == op->flow_cookie))) {
/* Check that we can just cast from ofoperation_type to
* nx_flow_update_event. */
BUILD_ASSERT_DECL((enum nx_flow_update_event) OFOPERATION_ADD