#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"
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
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
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. */
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. */
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".
*
*
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);