/* Definitions for use within ofproto. */
-#include "ofproto/ofproto.h"
#include "cfm.h"
#include "classifier.h"
#include "heap.h"
#include "list.h"
#include "ofp-errors.h"
#include "ofp-util.h"
+#include "ofproto/ofproto.h"
+#include "ovs-thread.h"
#include "shash.h"
#include "simap.h"
#include "timeval.h"
struct shash port_by_name;
unsigned long *ofp_port_ids;/* Bitmap of used OpenFlow port numbers. */
struct simap ofp_requests; /* OpenFlow port number requests. */
- ofp_port_t alloc_port_no; /* Last allocated OpenFlow port number. */
- ofp_port_t max_ports; /* Max possible OpenFlow port num, plus one. */
+ uint16_t alloc_port_no; /* Last allocated OpenFlow port number. */
+ uint16_t max_ports; /* Max possible OpenFlow port num, plus one. */
/* Flow tables. */
struct oftable *tables;
/* Optimisation for flow expiry.
* These flows should all be present in tables. */
- struct list expirable; /* Expirable 'struct rule"s in all tables. */
+ struct ovs_mutex expirable_mutex;
+ struct list expirable OVS_GUARDED; /* Expirable 'struct rule"s in all
+ tables. */
/* Meter table.
* OpenFlow meters start at 1. To avoid confusion we leave the first
};
void ofproto_init_tables(struct ofproto *, int n_tables);
-void ofproto_init_max_ports(struct ofproto *, ofp_port_t max_ports);
+void ofproto_init_max_ports(struct ofproto *, uint16_t max_ports);
struct ofproto *ofproto_lookup(const char *name);
struct ofport *ofproto_get_port(const struct ofproto *, ofp_port_t ofp_port);
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. */
- uint16_t hard_timeout; /* In seconds from ->modified. */
- uint16_t idle_timeout; /* In seconds from ->used. */
uint8_t table_id; /* Index in ofproto's 'tables' array. */
bool send_flow_removed; /* Send a flow removed message? */
+ struct ovs_mutex timeout_mutex;
+ uint16_t hard_timeout OVS_GUARDED; /* In seconds from ->modified. */
+ uint16_t idle_timeout OVS_GUARDED; /* In seconds from ->used. */
+
/* Eviction groups. */
- bool evictable; /* If false, prevents eviction. */
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;
+
struct ofpact *ofpacts; /* Sequence of "struct ofpacts". */
unsigned int ofpacts_len; /* Size of 'ofpacts', in bytes. */
* ofproto-dpif implementation */
extern unsigned flow_eviction_threshold;
+/* Number of upcall handler threads. Only affects the ofproto-dpif
+ * implementation. */
+extern unsigned n_handler_threads;
+
/* Determines which model to use for handling misses in the ofproto-dpif
* implementation */
extern enum ofproto_flow_miss_model flow_miss_model;
}
void ofproto_rule_update_used(struct rule *, long long int used);
-void ofproto_rule_expire(struct rule *, uint8_t reason);
-void ofproto_rule_destroy(struct rule *);
+void ofproto_rule_expire(struct rule *rule, uint8_t reason)
+ OVS_RELEASES(rule->evict);
+void ofproto_rule_destroy(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);
bool ofproto_rule_has_out_port(const struct rule *, ofp_port_t out_port);
void ofoperation_complete(struct ofoperation *, enum ofperr);
-struct rule *ofoperation_get_victim(struct ofoperation *);
bool ofoperation_has_out_port(const struct ofoperation *, ofp_port_t out_port);
* An ofproto implementation reports the success or failure of an
* asynchronous operation on a rule using the rule's 'pending' member,
* which points to a opaque "struct ofoperation" that represents the
- * ongoing opreation. When the operation completes, the ofproto
+ * ongoing operation. When the operation completes, the ofproto
* implementation calls ofoperation_complete(), passing the ofoperation and
* an error indication.
*
* The ofproto base code updates the flow table optimistically, assuming
* that the operation will probably succeed:
*
- * - ofproto adds or replaces the rule in the flow table before calling
+ * - ofproto adds the rule in the flow table before calling
* ->rule_construct().
*
- * - ofproto updates the rule's actions before calling
- * ->rule_modify_actions().
+ * - ofproto updates the rule's actions and other properties before
+ * calling ->rule_modify_actions().
*
* - ofproto removes the rule before calling ->rule_destruct().
*
* With one exception, when an asynchronous operation completes with an
* error, ofoperation_complete() backs out the already applied changes:
*
- * - If adding or replacing a rule in the flow table fails, ofproto
- * removes the new rule or restores the original rule.
+ * - If adding a rule in the flow table fails, ofproto removes the new
+ * rule.
*
- * - If modifying a rule's actions fails, ofproto restores the original
- * actions.
+ * - If modifying a rule fails, ofproto restores the original actions
+ * (and other properties).
*
* - Removing a rule is not allowed to fail. It must always succeed.
*
* Construction
* ============
*
- * When ->rule_construct() is called, the caller has already inserted
- * 'rule' into 'rule->ofproto''s flow table numbered 'rule->table_id'.
- * There are two cases:
- *
- * - 'rule' is a new rule in its flow table. In this case,
- * ofoperation_get_victim(rule) returns NULL.
- *
- * - 'rule' is replacing an existing rule in its flow table that had the
- * same matching criteria and priority. In this case,
- * ofoperation_get_victim(rule) returns the rule being replaced (the
- * "victim" rule).
+ * When ->rule_construct() is called, 'rule' is a new rule in its flow
+ * table. The caller has already inserted 'rule' into 'rule->ofproto''s
+ * flow table numbered 'rule->table_id'.
*
* ->rule_construct() should set the following in motion:
*
*
* - Validate that the datapath can correctly implement 'rule->ofpacts'.
*
- * - If the rule is valid, update the datapath flow table, adding the new
- * rule or replacing the existing one.
- *
- * - If 'rule' is replacing an existing rule, uninitialize any derived
- * state for the victim rule, as in step 5 in the "Life Cycle"
- * described above.
+ * - If the rule is valid, add the new rule to the datapath flow table.
*
* (On failure, the ofproto code will roll back the insertion from the flow
- * table, either removing 'rule' or replacing it by the victim rule if
- * there is one.)
+ * table by removing 'rule'.)
*
* ->rule_construct() must act in one of the following ways:
*
*
* - Update the datapath flow table with the new actions.
*
+ * - Only if 'reset_counters' is true, reset any packet or byte counters
+ * associated with the rule to zero, so that rule_get_stats() will not
+ * longer count those packets or bytes.
+ *
* If the operation synchronously completes, ->rule_modify_actions() may
* call ofoperation_complete() before it returns. Otherwise, ->run()
* should call ofoperation_complete() later, after the operation does
*
* ->rule_modify_actions() should not modify any base members of struct
* rule. */
- void (*rule_modify_actions)(struct rule *rule);
+ void (*rule_modify_actions)(struct rule *rule, bool reset_counters);
/* Changes the OpenFlow IP fragment handling policy to 'frag_handling',
* which takes one of the following values, with the corresponding