* recently been processed by a revalidator. */
struct ovs_mutex stats_mutex;
struct dpif_flow_stats stats OVS_GUARDED;
+
+ /* If non-zero then the recirculation id that has
+ * been allocated for use with this rule.
+ * The recirculation id and associated internal flow should
+ * be freed when the rule is freed */
+ uint32_t recirc_id;
};
/* RULE_CAST() depends on this. */
return rule_get_actions(&rule->up);
}
+/* Sets 'rule''s recirculation id. */
+static void
+rule_dpif_set_recirc_id(struct rule_dpif *rule, uint32_t id)
+ OVS_REQUIRES(rule->up.mutex)
+{
+ ovs_assert(!rule->recirc_id);
+ rule->recirc_id = id;
+}
+
+/* Returns 'rule''s recirculation id. */
+uint32_t
+rule_dpif_get_recirc_id(struct rule_dpif *rule)
+ OVS_REQUIRES(rule->up.mutex)
+{
+ if (!rule->recirc_id) {
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
+
+ rule_dpif_set_recirc_id(rule, ofproto_dpif_alloc_recirc_id(ofproto));
+ }
+ return rule->recirc_id;
+}
+
+/* Sets 'rule''s recirculation id. */
+void
+rule_set_recirc_id(struct rule *rule_, uint32_t id)
+{
+ struct rule_dpif *rule = rule_dpif_cast(rule_);
+
+ ovs_mutex_lock(&rule->up.mutex);
+ rule_dpif_set_recirc_id(rule, id);
+ ovs_mutex_unlock(&rule->up.mutex);
+}
+
/* Lookup 'flow' in table 0 of 'ofproto''s classifier.
* If 'wc' is non-null, sets the fields that were relevant as part of
* the lookup. Returns the table_id where a match or miss occurred.
rule->stats.n_packets = 0;
rule->stats.n_bytes = 0;
rule->stats.used = rule->up.modified;
+ rule->recirc_id = 0;
+
return 0;
}
rule_destruct(struct rule *rule_)
{
struct rule_dpif *rule = rule_dpif_cast(rule_);
+
ovs_mutex_destroy(&rule->stats_mutex);
+ if (rule->recirc_id) {
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
+
+ ofproto_dpif_free_recirc_id(ofproto, rule->recirc_id);
+ }
}
static void