/* Definitions for use within ofproto. */
#include "ofproto/ofproto.h"
+#include "cfm.h"
#include "classifier.h"
#include "list.h"
#include "shash.h"
#include "timeval.h"
+struct ofputil_flow_mod;
+
/* An OpenFlow switch.
*
* With few exceptions, ofproto implementations may look at these fields but
unsigned flow_eviction_threshold; /* Threshold at which to begin flow
* table eviction. Only affects the
* ofproto-dpif implementation */
+ bool forward_bpdu; /* Option to allow forwarding of BPDU frames
+ * when NORMAL action is invoked. */
char *mfr_desc; /* Manufacturer. */
char *hw_desc; /* Hardware. */
char *sw_desc; /* Software version. */
/* Flow table operation tracking. */
int state; /* Internal state. */
struct list pending; /* List of "struct ofopgroup"s. */
+ unsigned int n_pending; /* list_size(&pending). */
struct hmap deletions; /* All OFOPERATION_DELETE "ofoperation"s. */
};
struct ofproto *ofproto_lookup(const char *name);
struct ofport *ofproto_get_port(const struct ofproto *, uint16_t ofp_port);
+/* Assigns CLS to each classifier table, in turn, in OFPROTO.
+ *
+ * All parameters are evaluated multiple times. */
+#define OFPROTO_FOR_EACH_TABLE(CLS, OFPROTO) \
+ for ((CLS) = (OFPROTO)->tables; \
+ (CLS) < &(OFPROTO)->tables[(OFPROTO)->n_tables]; \
+ (CLS)++)
+
+
/* An OpenFlow port within a "struct ofproto".
*
* With few exceptions, ofproto implementations may look at these fields but
struct ofp_phy_port opp;
uint16_t ofp_port; /* OpenFlow port number. */
unsigned int change_seq;
+ int mtu;
};
/* An OpenFlow flow within a "struct ofproto".
ovs_be64 flow_cookie; /* Controller-issued identifier. */
long long int created; /* Creation time. */
+ long long int modified; /* Time of last modification. */
uint16_t idle_timeout; /* In seconds from time of last use. */
- uint16_t hard_timeout; /* In seconds from time of creation. */
+ uint16_t hard_timeout; /* In seconds from last modification. */
uint8_t table_id; /* Index in ofproto's 'tables' array. */
bool send_flow_removed; /* Send a flow removed message? */
* Construction
* ============
*
- * ->construct() should not modify most base members of the ofproto. In
- * particular, the client will initialize the ofproto's 'ports' member
- * after construction is complete.
- *
- * ->construct() should initialize the base 'n_tables' member to the number
- * of flow tables supported by the datapath (between 1 and 255, inclusive),
- * initialize the base 'tables' member with space for one classifier per
- * table, and initialize each classifier with classifier_init. Each flow
- * table should be initially empty, so ->construct() should delete flows
- * from the underlying datapath, if necessary, rather than populating the
- * tables.
+ * ->construct() should not modify any base members of the ofproto. The
+ * client will initialize the ofproto's 'ports' and 'tables' members after
+ * construction is complete.
+ *
+ * When ->construct() is called, the client does not yet know how many flow
+ * tables the datapath supports, so ofproto->n_tables will be 0 and
+ * ofproto->tables will be NULL. ->construct() should store the number of
+ * flow tables supported by the datapath (between 1 and 255, inclusive)
+ * into '*n_tables'. After a successful return, the client will initialize
+ * the base 'n_tables' member to '*n_tables' and allocate and initialize
+ * the base 'tables' member as the specified number of empty flow tables.
+ * Each flow table will be initially empty, so ->construct() should delete
+ * flows from the underlying datapath, if necessary, rather than populating
+ * the tables.
*
* Only one ofproto instance needs to be supported for any given datapath.
* If a datapath is already open as part of one "ofproto", then another
* Destruction
* ===========
*
- * ->destruct() must do at least the following:
- *
- * - If 'ofproto' has any pending asynchronous operations, ->destruct()
- * must complete all of them by calling ofoperation_complete().
+ * If 'ofproto' has any pending asynchronous operations, ->destruct()
+ * must complete all of them by calling ofoperation_complete().
*
- * - If 'ofproto' has any rules left in any of its flow tables, ->
+ * ->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()
+ * returns.
*/
struct ofproto *(*alloc)(void);
- int (*construct)(struct ofproto *ofproto);
+ int (*construct)(struct ofproto *ofproto, int *n_tables);
void (*destruct)(struct ofproto *ofproto);
void (*dealloc)(struct ofproto *ofproto);
* If multiple tables are candidates for inserting the flow, the function
* should choose one arbitrarily (but deterministically).
*
- * This function will never be called for an ofproto that has only one
- * table, so it may be NULL in that case. */
+ * If this function is NULL then table 0 is always chosen. */
int (*rule_choose_table)(const struct ofproto *ofproto,
const struct cls_rule *cls_rule,
uint8_t *table_idp);
*
* - '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.
+ * ofoperation_get_victim(rule) returns the rule being replaced (the
+ * "victim" rule).
*
* ->rule_construct() should set the following in motion:
*
* - 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.
+ *
* (On failure, the ofproto code will roll back the insertion from the flow
- * table, either removing 'rule' or replacing it by the flow that was
- * originally in its place.)
+ * table, either removing 'rule' or replacing it by the victim rule if
+ * there is one.)
*
* ->rule_construct() must act in one of the following ways:
*
* * Return an OpenFlow error code (as returned by ofp_mkerr()). (Do
* not call ofoperation_complete() in this case.)
*
- * In the former case, ->rule_destruct() will be called; in the latter
- * case, it will not. ->rule_dealloc() will be called in either case.
+ * Either way, ->rule_destruct() will not be called for 'rule', but
+ * ->rule_dealloc() will be.
*
* - If the operation is only partially complete, then it must return 0.
* Later, when the operation is complete, the ->run() or ->destruct()
* not support CFM. */
int (*get_cfm_fault)(const struct ofport *ofport);
+ /* Gets the MPIDs of the remote maintenance points broadcasting to
+ * 'ofport'. Populates 'rmps' with a provider owned array of MPIDs, and
+ * 'n_rmps' with the number of MPIDs in 'rmps'. Returns a number less than
+ * 0 if CFM is not enabled of 'ofport'.
+ *
+ * This function may be a null pointer if the ofproto implementation does
+ * not support CFM. */
+ int (*get_cfm_remote_mpids)(const struct ofport *ofport,
+ const uint64_t **rmps, size_t *n_rmps);
+
/* If 's' is nonnull, this function registers a "bundle" associated with
* client data pointer 'aux' in 'ofproto'. A bundle is the same concept as
* a Port in OVSDB, that is, it consists of one or more "slave" devices
/* Returns true if 'aux' is a registered bundle that is currently in use as
* the output for a mirror. */
bool (*is_mirror_output_bundle)(struct ofproto *ofproto, void *aux);
+
+ /* When the configuration option of forward_bpdu changes, this function
+ * will be invoked. */
+ void (*forward_bpdu_changed)(struct ofproto *ofproto);
};
extern const struct ofproto_class ofproto_dpif_class;
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 negative (so it won't
+ * collide with any errno value or any value returned by ofp_mkerr()) and large
+ * (so it won't accidentally collide with EOF or a negative errno value). */
+enum { OFPROTO_POSTPONE = -100000 };
+
+int ofproto_flow_mod(struct ofproto *, const struct ofputil_flow_mod *);
void ofproto_add_flow(struct ofproto *, const struct cls_rule *,
const union ofp_action *, size_t n_actions);
bool ofproto_delete_flow(struct ofproto *, const struct cls_rule *);