static void reinit_ports(struct ofproto *);
/* rule. */
-static void ofproto_rule_destroy(struct rule *);
static void ofproto_rule_destroy__(struct rule *);
static void ofproto_rule_send_removed(struct rule *, uint8_t reason);
static bool rule_is_modifiable(const struct rule *);
}
}
\f
-static void
-ofproto_rule_destroy(struct rule *rule)
+void
+ofproto_rule_ref(struct rule *rule)
{
if (rule) {
- rule->ofproto->ofproto_class->rule_destruct(rule);
- ofproto_rule_destroy__(rule);
+ unsigned int orig;
+
+ atomic_add(&rule->ref_count, 1, &orig);
+ ovs_assert(orig != 0);
+ }
+}
+
+void
+ofproto_rule_unref(struct rule *rule)
+{
+ if (rule) {
+ unsigned int orig;
+
+ atomic_sub(&rule->ref_count, 1, &orig);
+ if (orig == 1) {
+ rule->ofproto->ofproto_class->rule_destruct(rule);
+ ofproto_rule_destroy__(rule);
+ } else {
+ ovs_assert(orig != 0);
+ }
}
}
/* Initialize base state. */
rule->ofproto = ofproto;
cls_rule_move(&rule->cr, &cr);
+ atomic_init(&rule->ref_count, 1);
rule->pending = NULL;
rule->flow_cookie = fm->new_cookie;
rule->created = rule->modified = rule->used = time_msec();
} else {
ovs_rwlock_wrlock(&rule->rwlock);
oftable_remove_rule(rule);
- ofproto_rule_destroy(rule);
+ ofproto_rule_unref(rule);
}
break;
case OFOPERATION_DELETE:
ovs_assert(!op->error);
- ofproto_rule_destroy(rule);
+ ofproto_rule_unref(rule);
op->rule = NULL;
break;