/* 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 ofpact;
struct ofputil_flow_mod;
struct bfd_cfg;
+struct meter;
/* An OpenFlow switch.
*
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
+ * pointer in the array un-used, and index directly with the OpenFlow
+ * meter_id. */
+ struct ofputil_meter_features meter_features;
+ struct meter **meters; /* 'meter_features.max_meter' + 1 pointers. */
/* OpenFlow connections. */
struct connmgr *connmgr;
};
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. */
+ uint32_t meter_id; /* Non-zero OF meter_id, or zero. */
+ struct list meter_list_node; /* In owning meter's 'rules' list. */
+
/* Flow monitors. */
enum nx_flow_monitor_flags monitor_flags;
uint64_t add_seqno; /* Sequence number when added. */
* 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);
+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);
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);
* ofport ->port_alloc ->port_construct ->port_destruct ->port_dealloc
* rule ->rule_alloc ->rule_construct ->rule_destruct ->rule_dealloc
*
+ * "ofproto" and "ofport" 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
* cycle:
*
* must complete all of them by calling ofoperation_complete().
*
* ->destruct() must also destroy all remaining rules in the ofproto's
- * tables, by passing each remaining rule to ofproto_rule_destroy(). The
- * client will destroy the flow tables themselves after ->destruct()
+ * tables, by passing each remaining rule to ofproto_rule_delete(), and
+ * then complete each of those deletions in turn by calling
+ * ofoperation_complete().
+ *
+ * (Thus, there is a multi-step process for any rule currently being
+ * inserted or modified at the beginning of destruction: first
+ * ofoperation_complete() that operation, then ofproto_rule_delete() the
+ * rule, then ofoperation_complete() the deletion operation.)
+ *
+ * The client will destroy the flow tables themselves after ->destruct()
* returns.
*/
struct ofproto *(*alloc)(void);
const struct match *match,
uint8_t *table_idp);
- /* Life-cycle functions for a "struct rule" (see "Life Cycle" above).
+ /* Life-cycle functions for a "struct rule".
+ *
+ *
+ * Rule Life Cycle
+ * ===============
+ *
+ * The life cycle of a struct rule is an elaboration of the basic life
+ * cycle described above under "Life Cycle".
+ *
+ * After a rule is successfully constructed, it is then inserted. If
+ * insertion completes successfully, then before it is later destructed, it
+ * is deleted.
+ *
+ * You can think of a rule as having the following extra steps inserted
+ * between "Life Cycle" steps 4 and 5:
+ *
+ * 4.1. The client inserts the rule into the flow table, making it
+ * visible in flow table lookups.
+ *
+ * 4.2. The client calls "rule_insert". Immediately or eventually, the
+ * implementation calls ofoperation_complete() to indicate that the
+ * insertion completed. If the operation failed, skip to step 5.
+ *
+ * 4.3. The rule is now installed in the flow table. Eventually it will
+ * be deleted.
+ *
+ * 4.4. The client removes the rule from the flow table. It is no longer
+ * visible in flow table lookups.
+ *
+ * 4.5. The client calls "rule_delete". Immediately or eventually, the
+ * implementation calls ofoperation_complete() to indicate that the
+ * deletion completed. Deletion is not allowed to fail, so it must
+ * be successful.
*
*
* Asynchronous Operation Support
* ==============================
*
- * The life-cycle operations on rules can operate asynchronously, meaning
- * that ->rule_construct() and ->rule_destruct() only need to initiate
- * their respective operations and do not need to wait for them to complete
- * before they return. ->rule_modify_actions() also operates
- * asynchronously.
+ * The "insert" and "delete" life-cycle operations on rules can operate
+ * asynchronously, meaning that ->rule_insert() and ->rule_delete() only
+ * need to initiate their respective operations and do not need to wait for
+ * them to complete before they return. ->rule_modify_actions() also
+ * operates asynchronously.
*
* 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.
*
* Only the following contexts may call ofoperation_complete():
*
- * - The function called to initiate the operation,
- * e.g. ->rule_construct() or ->rule_destruct(). This is the best
- * choice if the operation completes quickly.
+ * - The function called to initiate the operation, e.g. ->rule_insert()
+ * or ->rule_delete(). This is the best choice if the operation
+ * completes quickly.
*
* - The implementation's ->run() function.
*
* 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
- * ->rule_construct().
+ * - ofproto adds the rule in the flow table before calling
+ * ->rule_insert().
*
- * - 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().
+ * - ofproto removes the rule before calling ->rule_delete().
*
* 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.
+ * When ->rule_construct() is called, 'rule' is a new rule that is not yet
+ * inserted into a flow table. ->rule_construct() should initialize enough
+ * of the rule's derived state for 'rule' to be suitable for inserting into
+ * a flow table. ->rule_construct() should not modify any base members of
+ * struct rule.
*
- * - '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).
+ * If ->rule_construct() fails (as indicated by returning a nonzero
+ * OpenFlow error code), the ofproto base code will uninitialize and
+ * deallocate 'rule'. See "Rule Life Cycle" above for more details.
*
- * ->rule_construct() should set the following in motion:
+ * ->rule_construct() may also:
*
- * - Validate that the matching rule in 'rule->cr' is supported by the
+ * - Validate that the datapath supports the matching rule in 'rule->cr'
* datapath. For example, if the rule's table does not support
* registers, then it is an error if 'rule->cr' does not wildcard all
* registers.
*
* - 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.
+ * Some implementations might need to defer these tasks to ->rule_insert(),
+ * which is also acceptable.
+ *
*
- * - 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.
+ * Insertion
+ * =========
*
- * (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.)
+ * Following successful construction, the ofproto base case inserts 'rule'
+ * into its flow table, then it calls ->rule_insert(). ->rule_insert()
+ * should set in motion adding the new rule to the datapath flow table. It
+ * must act as follows:
*
- * ->rule_construct() must act in one of the following ways:
+ * - If it completes insertion, either by succeeding or failing, it must
+ * call ofoperation_complete()
*
- * - If it succeeds, it must call ofoperation_complete() and return 0.
+ * - If insertion is only partially complete, then it must return without
+ * calling ofoperation_complete(). Later, when the insertion is
+ * complete, the ->run() or ->destruct() function must call
+ * ofoperation_complete() to report success or failure.
*
- * - If it fails, it must act in one of the following ways:
+ * If ->rule_insert() fails, the ofproto base code will remove 'rule' from
+ * the flow table, destruct, uninitialize, and deallocate 'rule'. See
+ * "Rule Life Cycle" above for more details.
*
- * * Call ofoperation_complete() and return 0.
*
- * * Return an OpenFlow error code. (Do not call
- * ofoperation_complete() in this case.)
+ * Deletion
+ * ========
*
- * Either way, ->rule_destruct() will not be called for 'rule', but
- * ->rule_dealloc() will be.
+ * The ofproto base code removes 'rule' from its flow table before it calls
+ * ->rule_delete(). ->rule_delete() should set in motion removing 'rule'
+ * from the datapath flow table. It must act as follows:
*
- * - If the operation is only partially complete, then it must return 0.
- * Later, when the operation is complete, the ->run() or ->destruct()
- * function must call ofoperation_complete() to report success or
- * failure.
+ * - If it completes deletion, it must call ofoperation_complete().
*
- * ->rule_construct() should not modify any base members of struct rule.
+ * - If deletion is only partially complete, then it must return without
+ * calling ofoperation_complete(). Later, when the deletion is
+ * complete, the ->run() or ->destruct() function must call
+ * ofoperation_complete().
+ *
+ * Rule deletion must not fail.
*
*
* Destruction
* ===========
*
- * When ->rule_destruct() is called, the caller has already removed 'rule'
- * from 'rule->ofproto''s flow table. ->rule_destruct() should set in
- * motion removing 'rule' from the datapath flow table. If removal
- * completes synchronously, it should call ofoperation_complete().
- * Otherwise, the ->run() or ->destruct() function must later call
- * ofoperation_complete() after the operation completes.
+ * ->rule_destruct() must uninitialize derived state.
*
* Rule destruction must not fail. */
struct rule *(*rule_alloc)(void);
enum ofperr (*rule_construct)(struct rule *rule);
+ void (*rule_insert)(struct rule *rule);
+ void (*rule_delete)(struct rule *rule);
void (*rule_destruct)(struct rule *rule);
void (*rule_dealloc)(struct rule *rule);
* flow->tunnel and flow->in_port, which are assigned the correct values
* for the incoming packet. The register values are zeroed. 'packet''s
* header pointers (e.g. packet->l3) are appropriately initialized.
+ * packet->l3 is aligned on a 32-bit boundary.
*
* The implementation should add the statistics for 'packet' into 'rule'.
*
*
* - 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
* If 'realdev_ofp_port' is zero, then this function deconfigures 'ofport'
* as a VLAN splinter port.
*
- * This function should be NULL if a an implementation does not support
- * it. */
+ * This function should be NULL if an implementation does not support it.
+ */
int (*set_realdev)(struct ofport *ofport,
ofp_port_t realdev_ofp_port, int vid);
+
+/* ## ------------------------ ## */
+/* ## OpenFlow meter functions ## */
+/* ## ------------------------ ## */
+
+ /* These functions should be NULL if an implementation does not support
+ * them. They must be all null or all non-null.. */
+
+ /* Initializes 'features' to describe the metering features supported by
+ * 'ofproto'. */
+ void (*meter_get_features)(const struct ofproto *ofproto,
+ struct ofputil_meter_features *features);
+
+ /* If '*id' is UINT32_MAX, adds a new meter with the given 'config'. On
+ * success the function must store a provider meter ID other than
+ * UINT32_MAX in '*id'. All further references to the meter will be made
+ * with the returned provider meter id rather than the OpenFlow meter id.
+ * The caller does not try to interpret the provider meter id, giving the
+ * implementation the freedom to either use the OpenFlow meter_id value
+ * provided in the meter configuration, or any other value suitable for the
+ * implementation.
+ *
+ * If '*id' is a value other than UINT32_MAX, modifies the existing meter
+ * with that meter provider ID to have configuration 'config'. On failure,
+ * the existing meter configuration is left intact. Regardless of success,
+ * any change to '*id' updates the provider meter id used for this
+ * meter. */
+ enum ofperr (*meter_set)(struct ofproto *ofproto, ofproto_meter_id *id,
+ const struct ofputil_meter_config *config);
+
+ /* Gets the meter and meter band packet and byte counts for maximum of
+ * 'stats->n_bands' bands for the meter with provider ID 'id' within
+ * 'ofproto'. The caller fills in the other stats values. The band stats
+ * are copied to memory at 'stats->bands' provided by the caller. The
+ * number of returned band stats is returned in 'stats->n_bands'. */
+ enum ofperr (*meter_get)(const struct ofproto *ofproto,
+ ofproto_meter_id id,
+ struct ofputil_meter_stats *stats);
+
+ /* Deletes a meter, making the 'ofproto_meter_id' invalid for any
+ * further calls. */
+ void (*meter_del)(struct ofproto *, ofproto_meter_id);
};
extern const struct ofproto_class ofproto_dpif_class;
enum { OFPROTO_POSTPONE = 1 << 16 };
BUILD_ASSERT_DECL(OFPROTO_POSTPONE < OFPERR_OFS);
-int ofproto_flow_mod(struct ofproto *, const struct ofputil_flow_mod *);
+int ofproto_flow_mod(struct ofproto *, struct ofputil_flow_mod *);
void ofproto_add_flow(struct ofproto *, const struct match *,
unsigned int priority,
const struct ofpact *ofpacts, size_t ofpacts_len);