ofproto: Add a ref_count to "struct rule" to protect it from being freed.
[sliver-openvswitch.git] / ofproto / ofproto-provider.h
index d5fec1b..571f881 100644 (file)
@@ -27,6 +27,7 @@
 #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"
@@ -219,6 +220,7 @@ struct oftable {
 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. */
 
@@ -241,21 +243,21 @@ struct rule {
     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. */
@@ -268,6 +270,33 @@ struct rule {
                                  * 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. */