#include "ofp-errors.h"
#include "ofp-util.h"
#include "ofproto/ofproto.h"
+#include "ovs-atomic.h"
#include "ovs-thread.h"
#include "shash.h"
#include "simap.h"
struct rule {
struct ofproto *ofproto; /* The ofproto that contains this rule. */
struct cls_rule cr; /* In owning ofproto's classifier. */
+ atomic_uint ref_count;
struct ofoperation *pending; /* Operation now in progress, if nonnull. */
struct eviction_group *eviction_group; /* NULL if not in any group. */
/* The rwlock is used to protect those elements in struct rule which are
- * accessed by multiple threads. While maintaining a pointer to struct
- * rule, threads are required to hold a readlock. The main ofproto code is
- * guaranteed not to evict the rule, or change any of the elements "Guarded
- * by rwlock" without holding the writelock.
- *
- * A rule will not be evicted unless both its own and its classifier's
- * write locks are held. Therefore, while holding a classifier readlock,
- * one can be assured that write locked rules are safe to reference. */
+ * accessed by multiple threads. The main ofproto code is guaranteed not
+ * to change any of the elements "Guarded by rwlock" without holding the
+ * writelock.
+ *
+ * While maintaining a pointer to struct rule, threads are required to hold
+ * a readlock on the classifier that holds the rule or increment the rule's
+ * ref_count.
+ *
+ * A rule will not be evicted unless its classifier's write lock is
+ * held. */
struct ovs_rwlock rwlock;
/* Guarded by rwlock. */
- struct ofpact *ofpacts; /* Sequence of "struct ofpacts". */
- unsigned int ofpacts_len; /* Size of 'ofpacts', in bytes. */
+ struct rule_actions *actions;
- uint32_t meter_id; /* Non-zero OF meter_id, or zero. */
struct list meter_list_node; /* In owning meter's 'rules' list. */
/* Flow monitors. */
* is expirable, otherwise empty. */
};
+void ofproto_rule_ref(struct rule *);
+void ofproto_rule_unref(struct rule *);
+
+/* A set of actions within a "struct rule".
+ *
+ *
+ * Thread-safety
+ * =============
+ *
+ * A struct rule_actions 'actions' may be accessed without a risk of being
+ * freed by code that holds a read-lock or write-lock on 'rule->rwlock' (where
+ * 'rule' is the rule for which 'rule->actions == actions') or that owns a
+ * reference to 'actions->ref_count' (or both). */
+struct rule_actions {
+ atomic_uint ref_count;
+
+ /* These members are immutable: they do not change during the struct's
+ * lifetime. */
+ struct ofpact *ofpacts; /* Sequence of "struct ofpacts". */
+ unsigned int ofpacts_len; /* Size of 'ofpacts', in bytes. */
+ uint32_t meter_id; /* Non-zero OF meter_id, or zero. */
+};
+
+struct rule_actions *rule_actions_create(const struct ofpact *, size_t);
+void rule_actions_ref(struct rule_actions *);
+void rule_actions_unref(struct rule_actions *);
+
/* A set of rules to which an OpenFlow operation applies. */
struct rule_collection {
struct rule **rules; /* The rules. */