static struct rule *rule_from_cls_rule(const struct cls_rule *);
static void rule_insert(struct ofproto *, struct rule *,
struct ofpbuf *packet);
+static void rule_remove(struct ofproto *, struct rule *);
static bool rule_make_actions(struct ofproto *, struct rule *,
const struct ofpbuf *packet);
static void rule_install(struct ofproto *, struct rule *,
flow, wildcards,
priority));
if (rule) {
- if (rule->cr.wc.wildcards) {
- ofproto->need_revalidate = true;
- }
- classifier_remove(&ofproto->cls, &rule->cr);
- rule_destroy(ofproto, rule);
+ rule_remove(ofproto, rule);
}
}
struct rule *rule = rule_from_cls_rule(rule_);
struct ofproto *ofproto = ofproto_;
- classifier_remove(&ofproto->cls, &rule->cr);
- rule_free(rule);
+ /* Mark the flow as not installed, even though it might really be
+ * installed, so that rule_remove() doesn't bother trying to uninstall it.
+ * There is no point in uninstalling it individually since we are about to
+ * blow away all the flows with dpif_flow_flush(). */
+ rule->installed = false;
+
+ rule_remove(ofproto, rule);
}
void
}
}
+static void
+rule_remove(struct ofproto *ofproto, struct rule *rule)
+{
+ if (rule->cr.wc.wildcards) {
+ ofproto->need_revalidate = true;
+ } else {
+ rule_uninstall(ofproto, rule);
+ }
+ classifier_remove(&ofproto->cls, &rule->cr);
+ rule_destroy(ofproto, rule);
+}
+
/* Returns true if the actions changed, false otherwise. */
static bool
rule_make_actions(struct ofproto *p, struct rule *rule,
return 0;
}
- if (rule->cr.wc.wildcards) {
- p->need_revalidate = true;
- }
if (command == OFPFC_DELETE) {
- if (!rule->cr.wc.wildcards) {
- rule_uninstall(p, rule);
- }
- classifier_remove(&p->cls, &rule->cr);
- rule_destroy(p, rule);
+ rule_remove(p, rule);
} else {
free(rule->actions);
rule->actions = xmemdup(ofm->actions,
n_actions * sizeof *rule->actions);
rule->n_actions = n_actions;
- if (!rule->cr.wc.wildcards) {
+
+ if (rule->cr.wc.wildcards) {
+ p->need_revalidate = true;
+ } else {
if (rule_make_actions(p, rule, NULL)) {
rule_update(p, rule);
} else if (rule->installed && !rule->may_install) {
struct rule *super;
super = rule_from_cls_rule(classifier_lookup_wild(&p->cls, flow));
if (!super) {
- rule_uninstall(p, rule);
- classifier_remove(&p->cls, &rule->cr);
- rule_destroy(p, rule);
+ rule_remove(p, rule);
return false;
} else if (super != rule->super) {
list_remove(&rule->list);
assert(rule->installed);
assert(!rule->cr.wc.wildcards);
- rule_uninstall(ofproto, rule);
if (rule->super) {
- classifier_remove(&ofproto->cls, &rule->cr);
- rule_destroy(ofproto, rule);
+ rule_remove(ofproto, rule);
+ } else {
+ rule_uninstall(ofproto, rule);
}
}
return;
}
- if (!rule->super) {
- if (rule->cr.wc.wildcards) {
- /* Update stats. (This code will be a no-op if the rule expired
- * due to an idle timeout, because in that case the rule has no
- * subrules left.) */
- struct rule *subrule, *next_subrule;
- LIST_FOR_EACH_SAFE (subrule, next_subrule,
- struct rule, list, &rule->list) {
- rule_uninstall(p, subrule);
- classifier_remove(&p->cls, &subrule->cr);
- rule_destroy(p, subrule);
- }
- } else {
- rule_uninstall(p, rule);
+ if (rule->cr.wc.wildcards) {
+ /* Update stats. (This code will be a no-op if the rule expired
+ * due to an idle timeout, because in that case the rule has no
+ * subrules left.) */
+ struct rule *subrule, *next;
+ LIST_FOR_EACH_SAFE (subrule, next, struct rule, list, &rule->list) {
+ rule_remove(p, subrule);
}
}
send_flow_exp(p, rule, now,
(now >= hard_expire
? OFPER_HARD_TIMEOUT : OFPER_IDLE_TIMEOUT));
- classifier_remove(&p->cls, &rule->cr);
- rule_destroy(p, rule);
+ rule_remove(p, rule);
}
static void