ofproto: Drop 'expirable_mutex' in favor of new global 'ofproto_mutex'.
[sliver-openvswitch.git] / ofproto / ofproto-provider.h
index 52a7014..c9fd71e 100644 (file)
 
 #include "cfm.h"
 #include "classifier.h"
+#include "guarded-list.h"
 #include "heap.h"
 #include "hindex.h"
 #include "list.h"
 #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"
@@ -38,6 +40,8 @@ struct ofputil_flow_mod;
 struct bfd_cfg;
 struct meter;
 
+extern struct ovs_mutex ofproto_mutex;
+
 /* An OpenFlow switch.
  *
  * With few exceptions, ofproto implementations may look at these fields but
@@ -75,11 +79,8 @@ struct ofproto {
 
     struct hindex cookies;      /* Rules indexed on their cookie values. */
 
-    /* Optimisation for flow expiry.
-     * These flows should all be present in tables. */
-    struct ovs_mutex expirable_mutex;
-    struct list expirable OVS_GUARDED; /* Expirable 'struct rule"s in all
-                                          tables. */
+    /* List of expirable flows, in all flow tables. */
+    struct list expirable OVS_GUARDED_BY(ofproto_mutex);
 
     /* Meter table.
      * OpenFlow meters start at 1.  To avoid confusion we leave the first
@@ -97,6 +98,14 @@ struct ofproto {
     unsigned int n_pending;     /* list_size(&pending). */
     struct hmap deletions;      /* All OFOPERATION_DELETE "ofoperation"s. */
 
+    /* Delayed rule executions.
+     *
+     * We delay calls to ->ofproto_class->rule_execute() past releasing
+     * ofproto_mutex during a flow_mod, because otherwise a "learn" action
+     * triggered by the executing the packet would try to recursively modify
+     * the flow table and reacquire the global lock. */
+    struct guarded_list rule_executes;
+
     /* Flow table operation logging. */
     int n_add, n_delete, n_modify; /* Number of unreported ops of each kind. */
     long long int first_op, last_op; /* Range of times for unreported ops. */
@@ -217,20 +226,21 @@ struct oftable {
  * With few exceptions, ofproto implementations may look at these fields but
  * should not modify them. */
 struct rule {
-    struct list ofproto_node;    /* Owned by ofproto base code. */
     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. */
 
-    ovs_be64 flow_cookie;        /* Controller-issued identifier. */
+    ovs_be64 flow_cookie;        /* Controller-issued identifier. Guarded by
+                                    rwlock. */
     struct hindex_node cookie_node; /* In owning ofproto's 'cookies' index. */
 
     long long int created;       /* Creation time. */
     long long int modified;      /* Time of last modification. */
     long long int used;          /* Last use; time created if never used. */
     uint8_t table_id;            /* Index in ofproto's 'tables' array. */
-    bool send_flow_removed;      /* Send a flow removed message? */
+    enum ofputil_flow_mod_flags flags;
 
     struct ovs_mutex timeout_mutex;
     uint16_t hard_timeout OVS_GUARDED; /* In seconds from ->modified. */
@@ -240,19 +250,22 @@ struct rule {
     struct heap_node evg_node;   /* In eviction_group's "rules" heap. */
     struct eviction_group *eviction_group; /* NULL if not in any group. */
 
-    /* The evict lock is used to prevent rules from being evicted while child
-     * threads are using them to xlate flows.  A read lock means the rule is
-     * currently being used.  A write lock means the rule is in the process of
-     * being evicted and should be considered gone.  A rule will not be evicted
-     * unless both its own and its classifiers write locks are held.
-     * Therefore, while holding a classifier readlock, one can be assured that
-     * even write locked rules are safe. */
-    struct ovs_rwlock evict;
+    /* The rwlock is used to protect those elements in struct rule which are
+     * 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;
 
-    struct ofpact *ofpacts;      /* Sequence of "struct ofpacts". */
-    unsigned int ofpacts_len;    /* Size of 'ofpacts', in bytes. */
+    /* Guarded by rwlock. */
+    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. */
@@ -260,11 +273,51 @@ struct rule {
     uint64_t add_seqno;         /* Sequence number when added. */
     uint64_t modify_seqno;      /* Sequence number when changed. */
 
-    /* Optimisation for flow expiry. */
-    struct list expirable;      /* In ofproto's 'expirable' list if this rule
-                                 * is expirable, otherwise empty. */
+    /* Optimisation for flow expiry.  In ofproto's 'expirable' list if this
+     * rule is expirable, otherwise empty. */
+    struct list expirable OVS_GUARDED_BY(ofproto_mutex);
 };
 
+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. */
+    size_t n;                   /* Number of rules collected. */
+
+    size_t capacity;            /* Number of rules that will fit in 'rules'. */
+    struct rule *stub[64];      /* Preallocated rules to avoid malloc(). */
+};
+
+void rule_collection_init(struct rule_collection *);
+void rule_collection_add(struct rule_collection *, struct rule *);
+void rule_collection_destroy(struct rule_collection *);
+
 /* Threshold at which to begin flow table eviction. Only affects the
  * ofproto-dpif implementation */
 extern unsigned flow_eviction_threshold;
@@ -288,7 +341,7 @@ void ofproto_rule_delete(struct ofproto *, struct classifier *cls,
                          struct rule *) OVS_REQ_WRLOCK(cls->rwlock);
 void ofproto_rule_reduce_timeouts(struct rule *rule, uint16_t idle_timeout,
                                   uint16_t hard_timeout)
-    OVS_EXCLUDED(rule->ofproto->expirable_mutex, rule->timeout_mutex);
+    OVS_EXCLUDED(ofproto_mutex, rule->timeout_mutex);
 
 bool ofproto_rule_has_out_port(const struct rule *, ofp_port_t out_port);
 
@@ -316,7 +369,7 @@ struct ofgroup {
     struct hmap_node hmap_node; /* In struct ofproto's "groups" hmap. */
     struct ofproto *ofproto;    /* The ofproto that contains this group. */
     uint32_t group_id;
-    uint8_t type;               /* One of OFPGT_*. */
+    enum ofp11_group_type type; /* One of OFPGT_*. */
 
     long long int created;      /* Creation time. */
     long long int modified;     /* Time of last modification. */