/*
- * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "heap.h"
#include "hindex.h"
#include "list.h"
+#include "ofp-actions.h"
#include "ofp-errors.h"
#include "ofp-util.h"
#include "ofproto/ofproto.h"
#include "ovs-atomic.h"
+#include "ovs-rcu.h"
#include "ovs-thread.h"
#include "shash.h"
#include "simap.h"
#include "timeval.h"
struct match;
-struct ofpact;
struct ofputil_flow_mod;
struct bfd_cfg;
struct meter;
+struct ofoperation;
extern struct ovs_mutex ofproto_mutex;
uint64_t datapath_id; /* Datapath ID. */
bool forward_bpdu; /* Option to allow forwarding of BPDU frames
* when NORMAL action is invoked. */
- char *mfr_desc; /* Manufacturer (NULL for default)b. */
+ char *mfr_desc; /* Manufacturer (NULL for default). */
char *hw_desc; /* Hardware (NULL for default). */
char *sw_desc; /* Software version (NULL for default). */
char *serial_desc; /* Serial number (NULL for default). */
/* Rules indexed on their cookie values, in all flow tables. */
struct hindex cookies OVS_GUARDED_BY(ofproto_mutex);
+ struct hmap learned_cookies OVS_GUARDED_BY(ofproto_mutex);
/* List of expirable flows, in all flow tables. */
struct list expirable OVS_GUARDED_BY(ofproto_mutex);
/* OpenFlow connections. */
struct connmgr *connmgr;
- /* Flow table operation tracking.
- *
- * 'state' is meaningful only within ofproto.c, one of the enum
- * ofproto_state constants defined there.
- *
- * 'pending' is the list of "struct ofopgroup"s currently pending.
- *
- * 'n_pending' is the number of elements in 'pending'.
- *
- * 'deletions' contains pending ofoperations of type OFOPERATION_DELETE,
- * indexed on its rule's flow.*/
- int state;
- struct list pending OVS_GUARDED_BY(ofproto_mutex);
- unsigned int n_pending OVS_GUARDED_BY(ofproto_mutex);
- struct hmap deletions OVS_GUARDED_BY(ofproto_mutex);
-
/* Delayed rule executions.
*
* We delay calls to ->ofproto_class->rule_execute() past releasing
* the flow table and reacquire the global lock. */
struct guarded_list rule_executes; /* Contains "struct rule_execute"s. */
- /* 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. */
- long long int next_op_report; /* Time to report ops, or LLONG_MAX. */
- long long int op_backoff; /* Earliest time to report ops again. */
-
/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
*
* This is deprecated. It is only for compatibility with broken device
struct netdev *netdev;
struct ofputil_phy_port pp;
ofp_port_t ofp_port; /* OpenFlow port number. */
+ uint64_t change_seq;
long long int created; /* Time created, in msec. */
int mtu;
};
*/
enum oftable_flags {
OFTABLE_HIDDEN = 1 << 0, /* Hide from most OpenFlow operations. */
- OFTABLE_READONLY = 1 << 1 /* Don't allow OpenFlow to change this table. */
+ OFTABLE_READONLY = 1 << 1 /* Don't allow OpenFlow controller to change
+ this table. */
};
/* A flow table within a "struct ofproto".
* Thread-safety
* =============
*
- * A cls->rwlock read-lock holder prevents rules from being added or deleted.
- *
- * Adding or removing rules requires holding ofproto_mutex AND the cls->rwlock
- * write-lock.
+ * Adding or removing rules requires holding ofproto_mutex.
*
- * cls->rwlock should be held only briefly. For extended access to a rule,
- * increment its ref_count with ofproto_rule_ref(). A rule will not be freed
- * until its ref_count reaches zero.
+ * Rules in 'cls' are RCU protected. For extended access to a rule, try
+ * incrementing its ref_count with ofproto_rule_try_ref(), or
+ * ofproto_rule_ref(), if the rule is still known to be in 'cls'. A rule
+ * will be freed using ovsrcu_postpone() once its 'ref_count' reaches zero.
*
- * Modifying a rule requires the rule's own mutex. Holding cls->rwlock (for
- * read or write) does not allow the holder to modify the rule.
+ * Modifying a rule requires the rule's own mutex.
*
- * Freeing a rule requires ofproto_mutex and the cls->rwlock write-lock. After
- * removing the rule from the classifier, release a ref_count from the rule
- * ('cls''s reference to the rule).
+ * Freeing a rule requires ofproto_mutex. After removing the rule from the
+ * classifier, release a ref_count from the rule ('cls''s reference to the
+ * rule).
*
* Refer to the thread-safety notes on struct rule for more information.*/
struct oftable {
uint32_t eviction_group_id_basis;
struct hmap eviction_groups_by_id;
struct heap eviction_groups_by_size;
+
+ /* Table configuration. */
+ ATOMIC(enum ofputil_table_miss) miss_config;
+
+ atomic_ulong n_matched;
+ atomic_ulong n_missed;
};
/* Assigns TABLE to each oftable, in turn, in OFPROTO.
* Rules
* -----
*
- * A rule 'rule' may be accessed without a risk of being freed by code that
- * holds a read-lock or write-lock on 'cls->rwlock' or that owns a reference to
- * 'rule->ref_count' (or both). Code that needs to hold onto a rule for a
- * while should take 'cls->rwlock', find the rule it needs, increment
- * 'rule->ref_count' with ofproto_rule_ref(), and drop 'cls->rwlock'.
+ * A rule 'rule' may be accessed without a risk of being freed by a thread
+ * until the thread quiesces (i.e., rules are RCU protected and destructed
+ * using ovsrcu_postpone()). Code that needs to hold onto a rule for a
+ * while should increment 'rule->ref_count' either with ofproto_rule_ref()
+ * (if 'ofproto_mutex' is held), or with ofproto_rule_try_ref() (when some
+ * other thread might remove the rule from 'cls'). ofproto_rule_try_ref()
+ * will fail if the rule has already been scheduled for destruction.
*
* 'rule->ref_count' protects 'rule' from being freed. It doesn't protect the
- * rule from being deleted from 'cls' (that's 'cls->rwlock') and it doesn't
+ * rule from being deleted from 'cls' (that's 'ofproto_mutex') and it doesn't
* protect members of 'rule' from modification (that's 'rule->mutex').
*
* 'rule->mutex' protects the members of 'rule' from modification. It doesn't
- * protect the rule from being deleted from 'cls' (that's 'cls->rwlock') and it
- * doesn't prevent the rule from being freed (that's 'rule->ref_count').
+ * protect the rule from being deleted from 'cls' (that's 'ofproto_mutex') and
+ * it doesn't prevent the rule from being freed (that's 'rule->ref_count').
*
* Regarding thread safety, the members of a rule fall into the following
* categories:
/* Protects members marked OVS_GUARDED.
* Readers only need to hold this mutex.
- * Writers must hold both this mutex AND ofproto_mutex. */
+ * Writers must hold both this mutex AND ofproto_mutex.
+ * By implication writers can read *without* taking this mutex while they
+ * hold ofproto_mutex. */
struct ovs_mutex mutex OVS_ACQ_AFTER(ofproto_mutex);
/* Number of references.
* The classifier owns one reference.
* Any thread trying to keep a rule from being freed should hold its own
* reference. */
- atomic_uint ref_count;
-
- /* Operation now in progress, if nonnull. */
- struct ofoperation *pending OVS_GUARDED_BY(ofproto_mutex);
+ struct ovs_refcount ref_count;
/* A "flow cookie" is the OpenFlow name for a 64-bit value associated with
* a flow.. */
ovs_be64 flow_cookie OVS_GUARDED;
struct hindex_node cookie_node OVS_GUARDED_BY(ofproto_mutex);
- /* Times. */
- long long int created OVS_GUARDED; /* Creation time. */
- long long int modified OVS_GUARDED; /* Time of last modification. */
- long long int used OVS_GUARDED; /* Last use; time created if never used. */
enum ofputil_flow_mod_flags flags OVS_GUARDED;
/* Timeouts. */
/* OpenFlow actions. See struct rule_actions for more thread-safety
* notes. */
- struct rule_actions *actions OVS_GUARDED;
+ OVSRCU_TYPE(const struct rule_actions *) actions;
/* In owning meter's 'rules' list. An empty list if there is no meter. */
struct list meter_list_node OVS_GUARDED_BY(ofproto_mutex);
/* Optimisation for flow expiry. In ofproto's 'expirable' list if this
* rule is expirable, otherwise empty. */
struct list expirable OVS_GUARDED_BY(ofproto_mutex);
+
+ /* Times. Last so that they are more likely close to the stats managed
+ * by the provider. */
+ long long int created OVS_GUARDED; /* Creation time. */
+
+ /* Must hold 'mutex' for both read/write, 'ofproto_mutex' not needed. */
+ long long int modified OVS_GUARDED; /* Time of last modification. */
};
void ofproto_rule_ref(struct rule *);
+bool ofproto_rule_try_ref(struct rule *);
void ofproto_rule_unref(struct rule *);
-struct rule_actions *rule_get_actions(const struct rule *rule)
- OVS_EXCLUDED(rule->mutex);
-struct rule_actions *rule_get_actions__(const struct rule *rule)
- OVS_REQUIRES(rule->mutex);
-
-/* Returns true if 'rule' is an OpenFlow 1.3 "table-miss" rule, false
- * otherwise.
- *
- * ("Table-miss" rules are special because a packet_in generated through one
- * uses OFPR_NO_MATCH as its reason, whereas packet_ins generated by any other
- * rule use OFPR_ACTION.) */
-static inline bool
-rule_is_table_miss(const struct rule *rule)
-{
- return rule->cr.priority == 0 && cls_rule_is_catchall(&rule->cr);
-}
+static inline const struct rule_actions * rule_get_actions(const struct rule *);
+static inline bool rule_is_table_miss(const struct rule *);
+static inline bool rule_is_hidden(const 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). */
+ * A struct rule_actions may be accessed without a risk of being freed by
+ * code that holds 'rule->mutex' (where 'rule' is the rule for which
+ * 'rule->actions == actions') or during the RCU active period.
+ *
+ * All members are immutable: they do not change during the struct's
+ * lifetime. */
struct rule_actions {
- atomic_uint ref_count;
+ /* Flags.
+ *
+ * 'has_meter' is true if 'ofpacts' contains an OFPACT_METER action.
+ *
+ * 'has_learn_with_delete' is true if 'ofpacts' contains an OFPACT_LEARN
+ * action whose flags include NX_LEARN_F_DELETE_LEARNED. */
+ bool has_meter;
+ bool has_learn_with_delete;
- /* 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 provider_meter_id; /* Datapath meter_id, or UINT32_MAX. */
+ /* Actions. */
+ uint32_t ofpacts_len; /* Size of 'ofpacts', in bytes. */
+ struct ofpact ofpacts[]; /* Sequence of "struct ofpacts". */
};
+BUILD_ASSERT_DECL(offsetof(struct rule_actions, ofpacts) % OFPACT_ALIGNTO == 0);
-struct rule_actions *rule_actions_create(const struct ofproto *,
- const struct ofpact *, size_t);
-void rule_actions_ref(struct rule_actions *);
-void rule_actions_unref(struct rule_actions *);
+const struct rule_actions *rule_actions_create(const struct ofpact *, size_t);
+void rule_actions_destroy(const struct rule_actions *);
+bool ofproto_rule_has_out_port(const struct rule *, ofp_port_t port)
+ OVS_REQUIRES(ofproto_mutex);
/* A set of rules to which an OpenFlow operation applies. */
struct rule_collection {
void rule_collection_unref(struct rule_collection *);
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;
+/* Limits the number of flows allowed in the datapath. Only affects the
+ * ofproto-dpif implementation. */
+extern unsigned ofproto_flow_limit;
-/* Number of upcall handler threads. Only affects the ofproto-dpif
- * implementation. */
-extern unsigned n_handler_threads;
+/* Maximum idle time (in ms) for flows to be cached in the datapath.
+ * Revalidators may expire flows more quickly than the configured value based
+ * on system load and other factors. This variable is subject to change. */
+extern unsigned ofproto_max_idle;
-/* Determines which model to use for handling misses in the ofproto-dpif
- * implementation */
-extern enum ofproto_flow_miss_model flow_miss_model;
+/* Number of upcall handler and revalidator threads. Only affects the
+ * ofproto-dpif implementation. */
+extern size_t n_handlers, n_revalidators;
-static inline struct rule *
-rule_from_cls_rule(const struct cls_rule *cls_rule)
-{
- return cls_rule ? CONTAINER_OF(cls_rule, struct rule, cr) : NULL;
-}
+static inline struct rule *rule_from_cls_rule(const struct cls_rule *);
void ofproto_rule_expire(struct rule *rule, uint8_t reason)
OVS_REQUIRES(ofproto_mutex);
uint16_t hard_timeout)
OVS_EXCLUDED(ofproto_mutex);
-void ofoperation_complete(struct ofoperation *, enum ofperr);
-
-bool ofoperation_has_out_port(const struct ofoperation *, ofp_port_t out_port)
- OVS_REQUIRES(ofproto_mutex);
-
/* 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 OVS_ACQ_AFTER(ofproto_mutex);
- 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 hmap_node hmap_node OVS_GUARDED; /* In ofproto's "groups" hmap. */
+
+ /* Number of references.
+ *
+ * This is needed to keep track of references to the group in the xlate
+ * module.
+ *
+ * If the main thread removes the group from an ofproto, we need to
+ * guarantee that the group remains accessible to users of
+ * xlate_group_actions and the xlate_cache, as the xlate_cache will not be
+ * cleaned up until the corresponding datapath flows are revalidated. */
+ struct ovs_refcount ref_count;
+
+ /* No lock is needed to protect the fields below since they are not
+ * modified after construction. */
+ const struct ofproto *ofproto; /* The ofproto that contains this group. */
+ const uint32_t group_id;
+ const enum ofp11_group_type type; /* One of OFPGT_*. */
+
+ const long long int created; /* Creation time. */
+ const long long int modified; /* Time of last modification. */
struct list buckets; /* Contains "struct ofputil_bucket"s. */
- uint32_t n_buckets;
+ const 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);
+ struct ofgroup **group);
-void ofproto_group_release(struct ofgroup *group)
- OVS_RELEASES(group->rwlock);
+void ofproto_group_ref(struct ofgroup *);
+void ofproto_group_unref(struct ofgroup *);
/* ofproto class structure, to be defined by each ofproto implementation.
*
* Destruction
* ===========
*
- * If 'ofproto' has any pending asynchronous operations, ->destruct()
- * 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_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.)
+ * tables, by passing each remaining rule to ofproto_rule_delete().
*
* The client will destroy the flow tables themselves after ->destruct()
* returns.
* - Call ofproto_rule_expire() for each OpenFlow flow that has reached
* its hard_timeout or idle_timeout, to expire the flow.
*
- * (But rules that are part of a pending operation, e.g. rules for
- * which ->pending is true, may not expire.)
- *
* Returns 0 if successful, otherwise a positive errno value. */
int (*run)(struct ofproto *ofproto);
void (*get_memory_usage)(const struct ofproto *ofproto,
struct simap *usage);
+ /* Adds some memory usage statistics for the implementation of 'type'
+ * into 'usage', for use with memory_report().
+ *
+ * This function is optional. */
+ void (*type_get_memory_usage)(const char *type, struct simap *usage);
+
/* Every "struct rule" in 'ofproto' is about to be deleted, one by one.
* This function may prepare for that, for example by clearing state in
* advance. It should *not* actually delete any "struct rule"s from
* than to do it one by one. */
void (*flush)(struct ofproto *ofproto);
- /* Helper for the OpenFlow OFPT_FEATURES_REQUEST request.
- *
- * The implementation should store true in '*arp_match_ip' if the switch
- * supports matching IP addresses inside ARP requests and replies, false
- * otherwise.
+ /* Helper for the OpenFlow OFPT_TABLE_FEATURES request.
*
- * The implementation should store in '*actions' a bitmap of the supported
- * OpenFlow actions. Vendor actions are not included in '*actions'. */
- void (*get_features)(struct ofproto *ofproto,
- bool *arp_match_ip,
- enum ofputil_action_bitmap *actions);
-
- /* Helper for the OpenFlow OFPST_TABLE statistics request.
- *
- * The 'ots' array contains 'ofproto->n_tables' elements. Each element is
- * initialized as:
+ * The 'features' array contains 'ofproto->n_tables' elements. Each
+ * element is initialized as:
*
* - 'table_id' to the array index.
*
* - 'name' to "table#" where # is the table ID.
*
- * - 'match' and 'wildcards' to OFPXMT12_MASK.
+ * - 'metadata_match' and 'metadata_write' to OVS_BE64_MAX.
*
- * - 'write_actions' and 'apply_actions' to OFPAT12_OUTPUT.
+ * - 'config' to the table miss configuration.
*
- * - 'write_setfields' and 'apply_setfields' to OFPXMT12_MASK.
+ * - 'max_entries' to 1,000,000.
*
- * - 'metadata_match' and 'metadata_write' to UINT64_MAX.
+ * - Both 'nonmiss' and 'miss' to:
*
- * - 'instructions' to OFPIT11_ALL.
+ * * 'next' to all 1-bits for all later tables.
*
- * - 'config' to OFPTC11_TABLE_MISS_MASK.
+ * * 'instructions' to all instructions.
*
- * - 'max_entries' to 1,000,000.
+ * * 'write' and 'apply' both to:
*
- * - 'active_count' to the classifier_count() for the table.
+ * - 'ofpacts': All actions.
*
- * - 'lookup_count' and 'matched_count' to 0.
+ * - 'set_fields': All fields.
*
- * The implementation should update any members in each element for which
- * it has better values:
- *
- * - 'name' to a more meaningful name.
+ * - 'match', 'mask', and 'wildcard' to all fields.
*
- * - 'wildcards' to the set of wildcards actually supported by the table
- * (if it doesn't support all OpenFlow wildcards).
+ * If 'stats' is nonnull, it also contains 'ofproto->n_tables' elements.
+ * Each element is initialized as:
*
- * - 'instructions' to set the instructions actually supported by
- * the table.
- *
- * - 'write_actions' to set the write actions actually supported by
- * the table (if it doesn't support all OpenFlow actions).
+ * - 'table_id' to the array index.
*
- * - 'apply_actions' to set the apply actions actually supported by
- * the table (if it doesn't support all OpenFlow actions).
+ * - 'active_count' to the classifier_count() for the table.
*
- * - 'write_setfields' to set the write setfields actually supported by
- * the table.
+ * - 'lookup_count' and 'matched_count' to 0.
*
- * - 'apply_setfields' to set the apply setfields actually supported by
- * the table.
+ * The implementation should update any members in each element for which
+ * it has better values:
*
- * - 'max_entries' to the maximum number of flows actually supported by
- * the hardware.
+ * - Any member of 'features' to better describe the implementation's
+ * capabilities.
*
* - 'lookup_count' to the number of packets looked up in this flow table
* so far.
*
* - 'matched_count' to the number of packets looked up in this flow
* table so far that matched one of the flow entries.
- *
- * All of the members of struct ofp12_table_stats are in network byte
- * order.
*/
- void (*get_tables)(struct ofproto *ofproto, struct ofp12_table_stats *ots);
+ void (*query_tables)(struct ofproto *ofproto,
+ struct ofputil_table_features *features,
+ struct ofputil_table_stats *stats);
/* ## ---------------- ## */
/* ## ofport Functions ## */
void (*port_reconfigured)(struct ofport *ofport,
enum ofputil_port_config old_config);
- /* Looks up a port named 'devname' in 'ofproto'. On success, initializes
- * '*port' appropriately.
+ /* Looks up a port named 'devname' in 'ofproto'. On success, returns 0 and
+ * initializes '*port' appropriately. Otherwise, returns a positive errno
+ * value.
*
* The caller owns the data in 'port' and must free it with
* ofproto_port_destroy() when it is no longer needed. */
* 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.
+ * insertion is successful, 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.2. The client calls "rule_insert" to insert the flow. The
+ * implementation attempts to install the flow in the underlying
+ * hardware and returns an error code indicate success or failure.
+ * On failure, go 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 "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 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_insert()
- * or ->rule_delete(). This is the best choice if the operation
- * completes quickly.
- *
- * - The implementation's ->run() function.
- *
- * - The implementation's ->destruct() function.
- *
- * The ofproto base code updates the flow table optimistically, assuming
- * that the operation will probably succeed:
- *
- * - ofproto adds the rule in the flow table before calling
- * ->rule_insert().
- *
- * - ofproto updates the rule's actions and other properties before
- * calling ->rule_modify_actions().
- *
- * - 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 a rule in the flow table fails, ofproto removes the new
- * rule.
- *
- * - 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.
- *
- * The ofproto base code serializes operations: if any operation is in
- * progress on a given rule, ofproto postpones initiating any new operation
- * on that rule until the pending operation completes. Therefore, every
- * operation must eventually complete through a call to
- * ofoperation_complete() to avoid delaying new operations indefinitely
- * (including any OpenFlow request that affects the rule in question, even
- * just to query its statistics).
+ * 4.5. The client calls "rule_delete". The implementation uninstalls
+ * the flow from the underlying hardware. Deletion is not allowed
+ * to fail.
*
*
* Construction
*
* 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:
- *
- * - If it completes insertion, either by succeeding or failing, it must
- * call ofoperation_complete()
- *
- * - 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.
+ * must add the new rule to the datapath flow table and return only after
+ * this is complete (whether it succeeds or fails).
*
* If ->rule_insert() fails, the ofproto base code will remove 'rule' from
* the flow table, destruct, uninitialize, and deallocate 'rule'. See
* ========
*
* 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 it completes deletion, it must call ofoperation_complete().
- *
- * - 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_delete(). ->rule_delete() must remove 'rule' from the datapath
+ * flow table and return only after this has completed successfully.
*
* Rule deletion must not fail.
*
struct rule *(*rule_alloc)(void);
enum ofperr (*rule_construct)(struct rule *rule)
/* OVS_REQUIRES(ofproto_mutex) */;
- void (*rule_insert)(struct rule *rule) /* OVS_REQUIRES(ofproto_mutex) */;
+ enum ofperr (*rule_insert)(struct rule *rule)
+ /* OVS_REQUIRES(ofproto_mutex) */;
void (*rule_delete)(struct rule *rule) /* OVS_REQUIRES(ofproto_mutex) */;
void (*rule_destruct)(struct rule *rule);
void (*rule_dealloc)(struct rule *rule);
* in '*byte_count'. UINT64_MAX indicates that the packet count or byte
* count is unknown. */
void (*rule_get_stats)(struct rule *rule, uint64_t *packet_count,
- uint64_t *byte_count)
+ uint64_t *byte_count, long long int *used)
/* OVS_EXCLUDED(ofproto_mutex) */;
/* Applies the actions in 'rule' to 'packet'. (This implements sending
* information in 'flow' is extracted from 'packet', except for
* 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.
+ * header pointers and offsets (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'.
*
enum ofperr (*rule_execute)(struct rule *rule, const struct flow *flow,
struct ofpbuf *packet);
- /* When ->rule_modify_actions() is called, the caller has already replaced
- * the OpenFlow actions in 'rule' by a new set. (The original actions are
- * in rule->pending->actions.)
+ /* If the datapath can properly implement changing 'rule''s actions to the
+ * 'ofpacts_len' bytes in 'ofpacts', returns 0. Otherwise, returns an enum
+ * ofperr indicating why the new actions wouldn't work.
*
- * ->rule_modify_actions() should set the following in motion:
+ * May be a null pointer if any set of actions is acceptable. */
+ enum ofperr (*rule_premodify_actions)(const struct rule *rule,
+ const struct ofpact *ofpacts,
+ size_t ofpacts_len)
+ /* OVS_REQUIRES(ofproto_mutex) */;
+
+ /* When ->rule_modify_actions() is called, the caller has already replaced
+ * the OpenFlow actions in 'rule' by a new set. (If
+ * ->rule_premodify_actions is nonnull, then it was previously called to
+ * verify that the new set of actions is acceptable.)
*
- * - Validate that the datapath can correctly implement the actions now
- * in 'rule'.
+ * ->rule_modify_actions() must:
*
* - Update the datapath flow table with the new actions.
*
* 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
- * complete.
- *
- * If the operation fails, then the base ofproto code will restore the
- * original 'actions' and 'n_actions' of 'rule'.
+ * Rule modification must not fail.
*
* ->rule_modify_actions() should not modify any base members of struct
* rule. */
* support CFM, as does a null pointer. */
int (*set_cfm)(struct ofport *ofport, const struct cfm_settings *s);
- /* Checks the status of CFM configured on 'ofport'. Returns true if the
- * port's CFM status was successfully stored into '*status'. Returns false
- * if the port did not have CFM configured, in which case '*status' is
- * indeterminate.
+ /* Checks the status change of CFM on 'ofport'. Returns true if
+ * there is status change since last call or if CFM is not specified. */
+ bool (*cfm_status_changed)(struct ofport *ofport);
+
+ /* Populates 'smap' with the status of CFM on 'ofport'. Returns 0 on
+ * success, or a positive errno. EOPNOTSUPP as a return value indicates
+ * that this ofproto_class does not support CFM, as does a null pointer.
*
- * The caller must provide and owns '*status', but it does not own and must
- * not modify or free the array returned in 'status->rmps'. */
- bool (*get_cfm_status)(const struct ofport *ofport,
- struct ofproto_cfm_status *status);
+ * The caller must provide and own '*status', and it must free the array
+ * returned in 'status->rmps'. '*status' is indeterminate if the return
+ * value is non-zero. */
+ int (*get_cfm_status)(const struct ofport *ofport,
+ struct cfm_status *status);
/* Configures BFD on 'ofport'.
*
* support BFD, as does a null pointer. */
int (*set_bfd)(struct ofport *ofport, const struct smap *cfg);
+ /* Checks the status change of BFD on 'ofport'. Returns true if there
+ * is status change since last call or if BFD is not specified. */
+ bool (*bfd_status_changed)(struct ofport *ofport);
+
/* Populates 'smap' with the status of BFD on 'ofport'. Returns 0 on
* success, or a positive errno. EOPNOTSUPP as a return value indicates
* that this ofproto_class does not support BFD, as does a null pointer. */
void (*set_mac_table_config)(struct ofproto *ofproto,
unsigned int idle_time, size_t max_entries);
+ /* Configures multicast snooping on 'ofport' using the settings
+ * defined in 's'.
+ *
+ * If 's' is nonnull, this function updates multicast snooping
+ * configuration to 's' in 'ofproto'.
+ *
+ * If 's' is NULL, this function disables multicast snooping
+ * on 'ofproto'.
+ *
+ * An implementation that does not support multicast snooping may set
+ * it to NULL or return EOPNOTSUPP. */
+ int (*set_mcast_snooping)(struct ofproto *ofproto,
+ const struct ofproto_mcast_snooping_settings *s);
+
+ /* Configures multicast snooping port's flood setting on 'ofproto'.
+ *
+ * All multicast traffic is sent to struct port 'aux' in 'ofproto'
+ * if 'flood' is true. Otherwise, struct port 'aux' is an ordinary
+ * switch port.
+ *
+ * An implementation that does not support multicast snooping may set
+ * it to NULL or return EOPNOTSUPP. */
+ int (*set_mcast_snooping_port)(struct ofproto *ofproto_, void *aux,
+ bool flood);
+
/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
*
* This is deprecated. It is only for compatibility with broken device drivers
void (*group_destruct)(struct ofgroup *);
void (*group_dealloc)(struct ofgroup *);
- enum ofperr (*group_modify)(struct ofgroup *, struct ofgroup *victim);
+ enum ofperr (*group_modify)(struct ofgroup *);
enum ofperr (*group_get_stats)(const struct ofgroup *,
struct ofputil_group_stats *);
int ofproto_class_register(const struct ofproto_class *);
int ofproto_class_unregister(const struct ofproto_class *);
-/* ofproto_flow_mod() returns this value if the flow_mod could not be processed
- * because it overlaps with an ongoing flow table operation that has not yet
- * completed. The caller should retry the operation later.
- *
- * ofproto.c also uses this value internally for additional (similar) purposes.
- *
- * This particular value is a good choice because it is large, so that it does
- * not collide with any errno value, but not large enough to collide with an
- * OFPERR_* value. */
-enum { OFPROTO_POSTPONE = 1 << 16 };
-BUILD_ASSERT_DECL(OFPROTO_POSTPONE < OFPERR_OFS);
-
int ofproto_flow_mod(struct ofproto *, struct ofputil_flow_mod *)
OVS_EXCLUDED(ofproto_mutex);
void ofproto_add_flow(struct ofproto *, const struct match *,
unsigned int priority,
const struct ofpact *ofpacts, size_t ofpacts_len)
OVS_EXCLUDED(ofproto_mutex);
-bool ofproto_delete_flow(struct ofproto *,
+void ofproto_delete_flow(struct ofproto *,
const struct match *, unsigned int priority)
OVS_EXCLUDED(ofproto_mutex);
void ofproto_flush_flows(struct ofproto *);
+\f
+static inline const struct rule_actions *
+rule_get_actions(const struct rule *rule)
+{
+ return ovsrcu_get(const struct rule_actions *, &rule->actions);
+}
+
+/* Returns true if 'rule' is an OpenFlow 1.3 "table-miss" rule, false
+ * otherwise.
+ *
+ * ("Table-miss" rules are special because a packet_in generated through one
+ * uses OFPR_NO_MATCH as its reason, whereas packet_ins generated by any other
+ * rule use OFPR_ACTION.) */
+static inline bool
+rule_is_table_miss(const struct rule *rule)
+{
+ return rule->cr.priority == 0 && cls_rule_is_catchall(&rule->cr);
+}
+
+/* Returns true if 'rule' should be hidden from the controller.
+ *
+ * Rules with priority higher than UINT16_MAX are set up by ofproto itself
+ * (e.g. by in-band control) and are intentionally hidden from the
+ * controller. */
+static inline bool
+rule_is_hidden(const struct rule *rule)
+{
+ return rule->cr.priority > UINT16_MAX;
+}
+
+static inline struct rule *
+rule_from_cls_rule(const struct cls_rule *cls_rule)
+{
+ return cls_rule ? CONTAINER_OF(cls_rule, struct rule, cr) : NULL;
+}
+
#endif /* ofproto/ofproto-provider.h */