X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-provider.h;h=a3640bd8e28c08eae8f8aacbbeed0cab05deacf7;hb=49a0e0eb3f85502ae6bc91151e345e67eb79314c;hp=d8db3aee7724596a81517e678e4e0ee84e3d8cab;hpb=9a9e3786b3a8065723887ab009aedb7f6d2667aa;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index d8db3aee7..a3640bd8e 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -19,13 +19,17 @@ /* Definitions for use within ofproto. */ -#include "ofproto/ofproto.h" #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" #include "timeval.h" @@ -33,6 +37,10 @@ struct match; struct ofpact; struct ofputil_flow_mod; +struct bfd_cfg; +struct meter; + +extern struct ovs_mutex ofproto_mutex; /* An OpenFlow switch. * @@ -47,9 +55,6 @@ struct ofproto { /* Settings. */ uint64_t fallback_dpid; /* Datapath ID if no better choice found. */ uint64_t datapath_id; /* Datapath ID. */ - 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 (NULL for default)b. */ @@ -68,12 +73,22 @@ struct ofproto { 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; - /* Optimisation for flow expiry. - * These flows should all be present in tables. */ - struct list expirable; /* Expirable 'struct rule"s in all tables. */ + /* Rules indexed on their cookie values, in all flow tables. */ + struct hindex cookies OVS_GUARDED_BY(ofproto_mutex); + + /* 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 + * 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; @@ -84,6 +99,14 @@ struct ofproto { 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. */ @@ -99,13 +122,19 @@ struct ofproto { 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); 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 *, uint16_t ofp_port); +struct ofport *ofproto_get_port(const struct ofproto *, ofp_port_t ofp_port); /* An OpenFlow port within a "struct ofproto". * @@ -116,8 +145,9 @@ struct ofport { struct ofproto *ofproto; /* The ofproto that contains this port. */ struct netdev *netdev; struct ofputil_phy_port pp; - uint16_t ofp_port; /* OpenFlow port number. */ + ofp_port_t ofp_port; /* OpenFlow port number. */ unsigned int change_seq; + long long int created; /* Time created, in msec. */ int mtu; }; @@ -197,58 +227,162 @@ struct oftable { * 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. */ + /* Where this rule resides in an OpenFlow switch. + * + * These are immutable once the rule is constructed, hence 'const'. */ + struct ofproto *const ofproto; /* The ofproto that contains this rule. */ + const struct cls_rule cr; /* In owning ofproto's classifier. */ + const uint8_t table_id; /* Index in ofproto's 'tables' array. */ + + atomic_uint ref_count; struct ofoperation *pending; /* Operation now in progress, if nonnull. */ - ovs_be64 flow_cookie; /* Controller-issued identifier. */ + 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. */ - 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? */ + enum ofputil_flow_mod_flags flags; + + 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. */ - struct ofpact *ofpacts; /* Sequence of "struct ofpacts". */ - unsigned int ofpacts_len; /* Size of 'ofpacts', in bytes. */ + /* 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; + + /* Guarded by mutex. */ + struct rule_actions *actions; + + 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. */ 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; + +/* 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; + 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; } -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 *); - -bool ofproto_rule_has_out_port(const struct rule *, uint16_t out_port); +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(ofproto_mutex, rule->mutex); void ofoperation_complete(struct ofoperation *, enum ofperr); -struct rule *ofoperation_get_victim(struct ofoperation *); -bool ofoperation_has_out_port(const struct ofoperation *, uint16_t out_port); +bool ofoperation_has_out_port(const struct ofoperation *, ofp_port_t out_port); -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. * @@ -256,7 +390,7 @@ bool ofproto_rule_is_hidden(const struct rule *); * 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. @@ -265,6 +399,9 @@ bool ofproto_rule_is_hidden(const struct rule *); * * - "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, @@ -286,6 +423,11 @@ bool ofproto_rule_is_hidden(const struct rule *); * 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", "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 * cycle: @@ -475,8 +617,16 @@ struct ofproto_class { * 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); @@ -687,7 +837,7 @@ struct ofproto_class { * It doesn't matter whether the new port will be returned by a later call * to ->port_poll(); the implementation may do whatever is more * convenient. */ - int (*port_del)(struct ofproto *ofproto, uint16_t ofp_port); + int (*port_del)(struct ofproto *ofproto, ofp_port_t ofp_port); /* Get port stats */ int (*port_get_stats)(const struct ofport *port, @@ -831,30 +981,62 @@ struct ofproto_class { 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. * @@ -863,22 +1045,22 @@ struct ofproto_class { * 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. * @@ -894,73 +1076,77 @@ struct ofproto_class { * 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. * - * (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.) + * Insertion + * ========= * - * ->rule_construct() must act in one of the following ways: + * 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 succeeds, it must call ofoperation_complete() and return 0. + * - If it completes insertion, either by succeeding or failing, it must + * call ofoperation_complete() * - * - If it fails, it must act in one of the following ways: + * - 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. * - * * Call ofoperation_complete() and return 0. + * 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. * - * * Return an OpenFlow error code. (Do not call - * ofoperation_complete() in this case.) * - * Either way, ->rule_destruct() will not be called for 'rule', but - * ->rule_dealloc() will be. + * Deletion + * ======== * - * - 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. + * 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: * - * ->rule_construct() should not modify any base members of struct rule. + * - 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 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); @@ -982,6 +1168,7 @@ struct ofproto_class { * 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'. * @@ -1000,6 +1187,10 @@ struct ofproto_class { * * - 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 @@ -1010,7 +1201,7 @@ struct ofproto_class { * * ->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 @@ -1109,6 +1300,20 @@ struct ofproto_class { int (*set_sflow)(struct ofproto *ofproto, const struct ofproto_sflow_options *sflow_options); + /* Configures IPFIX on 'ofproto' according to the options in + * 'bridge_exporter_options' and the 'flow_exporters_options' + * array, or turns off IPFIX if 'bridge_exporter_options' and + * 'flow_exporters_options' is NULL. + * + * EOPNOTSUPP as a return value indicates that 'ofproto' does not support + * IPFIX, as does a null pointer. */ + int (*set_ipfix)( + struct ofproto *ofproto, + const struct ofproto_ipfix_bridge_exporter_options + *bridge_exporter_options, + const struct ofproto_ipfix_flow_exporter_options + *flow_exporters_options, size_t n_flow_exporters_options); + /* Configures connectivity fault management on 'ofport'. * * If 'cfm_settings' is nonnull, configures CFM according to its members. @@ -1130,6 +1335,21 @@ struct ofproto_class { bool (*get_cfm_status)(const struct ofport *ofport, struct ofproto_cfm_status *status); + /* Configures BFD on 'ofport'. + * + * If 'cfg' is NULL, or 'cfg' does not contain the key value pair + * "enable=true", removes BFD from 'ofport'. Otherwise, configures BFD + * according to 'cfg'. + * + * EOPNOTSUPP as a return value indicates that this ofproto_class does not + * support BFD, as does a null pointer. */ + int (*set_bfd)(struct ofport *ofport, const struct smap *cfg); + + /* 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. */ + int (*get_bfd_status)(struct ofport *ofport, struct smap *smap); + /* Configures spanning tree protocol (STP) on 'ofproto' using the * settings defined in 's'. * @@ -1281,10 +1501,67 @@ struct ofproto_class { * 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, - uint16_t realdev_ofp_port, int vid); + 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); + + +/* ## -------------------- ## */ +/* ## 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; @@ -1304,7 +1581,7 @@ int ofproto_class_unregister(const struct ofproto_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);