#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
uint16_t max_ports; /* Max possible OpenFlow port num, plus one. */
/* Flow tables. */
+ long long int eviction_group_timer; /* For rate limited reheapification. */
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
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. */
unsigned long int *vlan_bitmap; /* 4096-bit bitmap of in-use VLANs. */
bool vlans_changed; /* True if new VLANs are in use. */
int min_mtu; /* Current MTU of non-internal ports. */
+
+ /* Groups. */
+ struct ovs_rwlock groups_rwlock;
+ struct hmap groups OVS_GUARDED; /* Contains "struct ofgroup"s. */
+ uint32_t n_groups[4] OVS_GUARDED; /* # of existing groups of each type. */
+ struct ofputil_group_features ogf;
};
void ofproto_init_tables(struct ofproto *, int n_tables);
* 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. */
- struct hindex_node cookie_node; /* In owning ofproto's 'cookies' index. */
+ ovs_be64 flow_cookie; /* Controller-issued identifier. Guarded by
+ mutex. */
+ struct hindex_node cookie_node OVS_GUARDED_BY(ofproto_mutex);
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. */
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 mutex 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 mutex" without holding the
+ * lock.
+ *
+ * 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_mutex mutex;
- struct ofpact *ofpacts; /* Sequence of "struct ofpacts". */
- unsigned int ofpacts_len; /* Size of 'ofpacts', in bytes. */
+ /* Guarded by mutex. */
+ 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. */
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->mutex' (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;
return cls_rule ? CONTAINER_OF(cls_rule, struct rule, cr) : NULL;
}
-void ofproto_rule_update_used(struct rule *, long long int used);
void ofproto_rule_expire(struct rule *rule, uint8_t reason);
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);
void ofoperation_complete(struct ofoperation *, enum ofperr);
bool ofoperation_has_out_port(const struct ofoperation *, ofp_port_t out_port);
+bool ofproto_rule_has_out_group(const struct rule *, uint32_t group_id);
bool ofproto_rule_is_hidden(const struct rule *);
+/* A group within a "struct ofproto".
+ *
+ * With few exceptions, ofproto implementations may look at these fields but
+ * should not modify them. */
+struct ofgroup {
+ /* The rwlock is used to prevent groups from being deleted while child
+ * threads are using them to xlate flows. A read lock means the
+ * group is currently being used. A write lock means the group is
+ * in the process of being deleted or updated. Note that since
+ * a read lock on the groups container is held while searching, and
+ * a group is ever write locked only while holding a write lock
+ * on the container, the user's of groups will never face a group
+ * in the write locked state. */
+ struct ovs_rwlock rwlock;
+ struct hmap_node hmap_node; /* In struct ofproto's "groups" hmap. */
+ struct ofproto *ofproto; /* The ofproto that contains this group. */
+ uint32_t group_id;
+ enum ofp11_group_type type; /* One of OFPGT_*. */
+
+ long long int created; /* Creation time. */
+ long long int modified; /* Time of last modification. */
+
+ struct list buckets; /* Contains "struct ofputil_bucket"s. */
+ uint32_t n_buckets;
+};
+
+bool ofproto_group_lookup(const struct ofproto *ofproto, uint32_t group_id,
+ struct ofgroup **group)
+ OVS_TRY_RDLOCK(true, (*group)->rwlock);
+
+void ofproto_group_release(struct ofgroup *group)
+ OVS_RELEASES(group->rwlock);
+
/* ofproto class structure, to be defined by each ofproto implementation.
*
*
* Data Structures
* ===============
*
- * These functions work primarily with three different kinds of data
+ * These functions work primarily with four different kinds of data
* structures:
*
* - "struct ofproto", which represents an OpenFlow switch.
*
* - "struct rule", which represents an OpenFlow flow within an ofproto.
*
+ * - "struct ofgroup", which represents an OpenFlow 1.1+ group within an
+ * ofproto.
+ *
* Each of these data structures contains all of the implementation-independent
* generic state for the respective concept, called the "base" state. None of
* them contains any extra space for ofproto implementations to use. Instead,
* ofproto ->alloc ->construct ->destruct ->dealloc
* ofport ->port_alloc ->port_construct ->port_destruct ->port_dealloc
* rule ->rule_alloc ->rule_construct ->rule_destruct ->rule_dealloc
+ * group ->group_alloc ->group_construct ->group_destruct ->group_dealloc
*
- * "ofproto" and "ofport" have this exact life cycle. The "rule" data
- * structure also follow this life cycle with some additional elaborations
+ * "ofproto", "ofport", and "group" have this exact life cycle. The "rule"
+ * data structure also follow this life cycle with some additional elaborations
* described under "Rule Life Cycle" below.
*
* Any instance of a given data structure goes through the following life
/* Deletes a meter, making the 'ofproto_meter_id' invalid for any
* further calls. */
void (*meter_del)(struct ofproto *, ofproto_meter_id);
+
+
+/* ## -------------------- ## */
+/* ## OpenFlow 1.1+ groups ## */
+/* ## -------------------- ## */
+
+ struct ofgroup *(*group_alloc)(void);
+ enum ofperr (*group_construct)(struct ofgroup *);
+ void (*group_destruct)(struct ofgroup *);
+ void (*group_dealloc)(struct ofgroup *);
+
+ enum ofperr (*group_modify)(struct ofgroup *, struct ofgroup *victim);
+
+ enum ofperr (*group_get_stats)(const struct ofgroup *,
+ struct ofputil_group_stats *);
};
extern const struct ofproto_class ofproto_dpif_class;