ofproto: Protect index by cookie with ofproto_mutex.
[sliver-openvswitch.git] / ofproto / ofproto-provider.h
index 571f881..bd40fbf 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "cfm.h"
 #include "classifier.h"
+#include "guarded-list.h"
 #include "heap.h"
 #include "hindex.h"
 #include "list.h"
@@ -39,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
@@ -74,13 +77,11 @@ struct ofproto {
     struct oftable *tables;
     int n_tables;
 
-    struct hindex cookies;      /* Rules indexed on their cookie values. */
+    /* Rules indexed on their cookie values, in all flow tables. */
+    struct hindex cookies OVS_GUARDED_BY(ofproto_mutex);
 
-    /* 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
@@ -98,6 +99,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. */
@@ -226,7 +235,7 @@ struct rule {
 
     ovs_be64 flow_cookie;        /* Controller-issued identifier. Guarded by
                                     rwlock. */
-    struct hindex_node cookie_node; /* In owning ofproto's 'cookies' index. */
+    struct hindex_node cookie_node OVS_GUARDED_BY(ofproto_mutex);
 
     long long int created;       /* Creation time. */
     long long int modified;      /* Time of last modification. */
@@ -265,9 +274,9 @@ 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 *);
@@ -333,7 +342,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);