X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-provider.h;h=9431be875d13e6642d9a97aacae8c6afd6495dc2;hb=dc723c447a797e555d400594133a35b9841eb1de;hp=a3640bd8e28c08eae8f8aacbbeed0cab05deacf7;hpb=49a0e0eb3f85502ae6bc91151e345e67eb79314c;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index a3640bd8e..9431be875 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -1,5 +1,5 @@ /* - * 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. @@ -17,7 +17,21 @@ #ifndef OFPROTO_OFPROTO_PROVIDER_H #define OFPROTO_OFPROTO_PROVIDER_H 1 -/* Definitions for use within ofproto. */ +/* Definitions for use within ofproto. + * + * + * Thread-safety + * ============= + * + * Lots of ofproto data structures are only accessed from a single thread. + * Those data structures are generally not thread-safe. + * + * The ofproto-dpif ofproto implementation accesses the flow table from + * multiple threads, including modifying the flow table from multiple threads + * via the "learn" action, so the flow table and various structures that index + * it have been made thread-safe. Refer to comments on individual data + * structures for details. + */ #include "cfm.h" #include "classifier.h" @@ -25,17 +39,18 @@ #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; @@ -67,10 +82,11 @@ struct ofproto { /* Datapath. */ struct hmap ports; /* Contains "struct ofport"s. */ struct shash port_by_name; - unsigned long *ofp_port_ids;/* Bitmap of used OpenFlow port numbers. */ struct simap ofp_requests; /* OpenFlow port number requests. */ uint16_t alloc_port_no; /* Last allocated OpenFlow port number. */ uint16_t max_ports; /* Max possible OpenFlow port num, plus one. */ + struct hmap ofport_usage; /* Map ofport to last used time. */ + uint64_t change_seq; /* Change sequence for netdev status. */ /* Flow tables. */ long long int eviction_group_timer; /* For rate limited reheapification. */ @@ -93,11 +109,21 @@ struct ofproto { /* OpenFlow connections. */ struct connmgr *connmgr; - /* 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. */ + /* 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. * @@ -105,7 +131,7 @@ struct ofproto { * 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; + 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. */ @@ -137,6 +163,8 @@ struct ofproto *ofproto_lookup(const char *name); struct ofport *ofproto_get_port(const struct ofproto *, ofp_port_t ofp_port); /* An OpenFlow port within a "struct ofproto". + * + * The port's name is netdev_get_name(port->netdev). * * With few exceptions, ofproto implementations may look at these fields but * should not modify them. */ @@ -146,7 +174,7 @@ struct ofport { struct netdev *netdev; struct ofputil_phy_port pp; ofp_port_t ofp_port; /* OpenFlow port number. */ - unsigned int change_seq; + uint64_t change_seq; long long int created; /* Time created, in msec. */ int mtu; }; @@ -178,10 +206,33 @@ void ofproto_port_set_state(struct ofport *, enum ofputil_port_state); */ 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". */ +/* 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. + * + * 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. + * + * 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. + * + * 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). + * + * Refer to the thread-safety notes on struct rule for more information.*/ struct oftable { enum oftable_flags flags; struct classifier cls; /* Contains "struct rule"s. */ @@ -212,6 +263,9 @@ struct oftable { uint32_t eviction_group_id_basis; struct hmap eviction_groups_by_id; struct heap eviction_groups_by_size; + + /* Table config: contains enum ofproto_table_config; accessed atomically. */ + atomic_uint config; }; /* Assigns TABLE to each oftable, in turn, in OFPROTO. @@ -225,7 +279,59 @@ struct oftable { /* An OpenFlow flow within a "struct ofproto". * * With few exceptions, ofproto implementations may look at these fields but - * should not modify them. */ + * should not modify them. + * + * + * Thread-safety + * ============= + * + * Except near the beginning or ending of its lifespan, rule 'rule' belongs to + * the classifier rule->ofproto->tables[rule->table_id].cls. The text below + * calls this classifier 'cls'. + * + * Motivation + * ---------- + * + * The thread safety rules described here for "struct rule" are motivated by + * two goals: + * + * - Prevent threads that read members of "struct rule" from reading bad + * data due to changes by some thread concurrently modifying those + * members. + * + * - Prevent two threads making changes to members of a given "struct rule" + * from interfering with each other. + * + * + * 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'. + * + * '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 + * 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'). + * + * Regarding thread safety, the members of a rule fall into the following + * categories: + * + * - Immutable. These members are marked 'const'. + * + * - Members that may be safely read or written only by code holding + * ofproto_mutex. These are marked OVS_GUARDED_BY(ofproto_mutex). + * + * - Members that may be safely read only by code holding ofproto_mutex or + * 'rule->mutex', and safely written only by coding holding ofproto_mutex + * AND 'rule->mutex'. These are marked OVS_GUARDED. + */ struct rule { /* Where this rule resides in an OpenFlow switch. * @@ -234,80 +340,113 @@ struct 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. Guarded by - mutex. */ + /* Protects members marked OVS_GUARDED. + * Readers only need to hold this 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. */ + struct ovs_refcount ref_count; + + /* Operation now in progress, if nonnull. */ + struct ofoperation *pending OVS_GUARDED_BY(ofproto_mutex); + + /* 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); - 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. */ - enum ofputil_flow_mod_flags flags; + enum ofputil_flow_mod_flags flags OVS_GUARDED; + /* Timeouts. */ uint16_t hard_timeout OVS_GUARDED; /* In seconds from ->modified. */ uint16_t idle_timeout OVS_GUARDED; /* In seconds from ->used. */ - /* Eviction groups. */ - struct heap_node evg_node; /* In eviction_group's "rules" heap. */ - struct eviction_group *eviction_group; /* NULL if not in any group. */ - - /* 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. + /* Eviction groups (see comment on struct eviction_group for explanation) . * - * 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; + * 'eviction_group' is this rule's eviction group, or NULL if it is not in + * any eviction group. When 'eviction_group' is nonnull, 'evg_node' is in + * the ->eviction_group->rules hmap. */ + struct eviction_group *eviction_group OVS_GUARDED_BY(ofproto_mutex); + struct heap_node evg_node OVS_GUARDED_BY(ofproto_mutex); - /* Guarded by mutex. */ - struct rule_actions *actions; + /* OpenFlow actions. See struct rule_actions for more thread-safety + * notes. */ + OVSRCU_TYPE(const struct rule_actions *) actions; - struct list meter_list_node; /* In owning meter's 'rules' list. */ + /* In owning meter's 'rules' list. An empty list if there is no meter. */ + struct list meter_list_node OVS_GUARDED_BY(ofproto_mutex); - /* 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. */ + /* Flow monitors (e.g. for NXST_FLOW_MONITOR, related to struct ofmonitor). + * + * 'add_seqno' is the sequence number when this rule was created. + * 'modify_seqno' is the sequence number when this rule was last modified. + * See 'monitor_seqno' in connmgr.c for more information. */ + enum nx_flow_monitor_flags monitor_flags OVS_GUARDED_BY(ofproto_mutex); + uint64_t add_seqno OVS_GUARDED_BY(ofproto_mutex); + uint64_t modify_seqno 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 *); void ofproto_rule_unref(struct rule *); +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); +} +bool rule_is_internal(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 + * A struct rule_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). */ + * 'rule' is the rule for which 'rule->actions == actions') or during the RCU + * active period. */ 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. */ + uint32_t ofpacts_len; /* Size of 'ofpacts', in bytes. */ + uint32_t provider_meter_id; /* Datapath meter_id, or UINT32_MAX. */ + 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 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 ofproto *, + const struct ofpact *, size_t); +void rule_actions_destroy(const struct rule_actions *); /* A set of rules to which an OpenFlow operation applies. */ struct rule_collection { @@ -320,19 +459,22 @@ struct rule_collection { void rule_collection_init(struct rule_collection *); void rule_collection_add(struct rule_collection *, struct rule *); +void rule_collection_ref(struct rule_collection *) OVS_REQUIRES(ofproto_mutex); +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) @@ -340,16 +482,18 @@ rule_from_cls_rule(const struct cls_rule *cls_rule) return cls_rule ? CONTAINER_OF(cls_rule, struct rule, cr) : NULL; } -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_expire(struct rule *rule, uint8_t reason) + OVS_REQUIRES(ofproto_mutex); +void ofproto_rule_delete(struct ofproto *, struct rule *) + OVS_EXCLUDED(ofproto_mutex); void ofproto_rule_reduce_timeouts(struct rule *rule, uint16_t idle_timeout, uint16_t hard_timeout) - OVS_EXCLUDED(ofproto_mutex, rule->mutex); + OVS_EXCLUDED(ofproto_mutex); void ofoperation_complete(struct ofoperation *, enum ofperr); -bool ofoperation_has_out_port(const struct ofoperation *, ofp_port_t out_port); +bool ofoperation_has_out_port(const struct ofoperation *, ofp_port_t out_port) + OVS_REQUIRES(ofproto_mutex); /* A group within a "struct ofproto". * @@ -364,7 +508,7 @@ struct ofgroup { * 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 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; @@ -556,16 +700,6 @@ struct ofproto_class { * Returns 0 if successful, otherwise a positive errno value. */ int (*type_run)(const char *type); - /* Performs periodic activity required on ofprotos of type 'type' - * that needs to be done with the least possible latency. - * - * This is run multiple times per main loop. An ofproto provider may - * implement it or not, according to whether it provides a performance - * boost for that ofproto implementation. - * - * Returns 0 if successful, otherwise a positive errno value. */ - int (*type_run_fast)(const char *type); - /* Causes the poll loop to wake up when a type 'type''s 'run' * function needs to be called, e.g. by calling the timer or fd * waiting functions in poll-loop.h. @@ -649,14 +783,6 @@ struct ofproto_class { * Returns 0 if successful, otherwise a positive errno value. */ int (*run)(struct ofproto *ofproto); - /* Performs periodic activity required by 'ofproto' that needs to be done - * with the least possible latency. - * - * This is run multiple times per main loop. An ofproto provider may - * implement it or not, according to whether it provides a performance - * boost for that ofproto implementation. */ - int (*run_fast)(struct ofproto *ofproto); - /* Causes the poll loop to wake up when 'ofproto''s 'run' function needs to * be called, e.g. by calling the timer or fd waiting functions in * poll-loop.h. */ @@ -669,6 +795,12 @@ struct ofproto_class { 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 @@ -706,7 +838,7 @@ struct ofproto_class { * * - 'write_setfields' and 'apply_setfields' to OFPXMT12_MASK. * - * - 'metadata_match' and 'metadata_write' to UINT64_MAX. + * - 'metadata_match' and 'metadata_write' to OVS_BE64_MAX. * * - 'instructions' to OFPIT11_ALL. * @@ -813,8 +945,9 @@ struct ofproto_class { 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. */ @@ -1144,9 +1277,10 @@ struct ofproto_class { * * 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); + enum ofperr (*rule_construct)(struct rule *rule) + /* OVS_REQUIRES(ofproto_mutex) */; + void (*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); @@ -1155,7 +1289,8 @@ struct ofproto_class { * 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 * buffered packets for OpenFlow OFPT_FLOW_MOD commands.) @@ -1167,8 +1302,8 @@ struct ofproto_class { * 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'. * @@ -1201,7 +1336,8 @@ struct ofproto_class { * * ->rule_modify_actions() should not modify any base members of struct * rule. */ - void (*rule_modify_actions)(struct rule *rule, bool reset_counters); + void (*rule_modify_actions)(struct rule *rule, bool reset_counters) + /* OVS_REQUIRES(ofproto_mutex) */; /* Changes the OpenFlow IP fragment handling policy to 'frag_handling', * which takes one of the following values, with the corresponding @@ -1325,15 +1461,19 @@ struct ofproto_class { * 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 of CFM configured on 'ofport'. Returns 0 if the + * port's CFM status was successfully stored into '*status'. Returns + * negative number if there is no status change since last update. + * Returns positive errno otherwise. + * + * 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 ofproto_cfm_status *status); /* Configures BFD on 'ofport'. * @@ -1346,8 +1486,11 @@ struct ofproto_class { 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. */ + * success. Returns a negative number if there is no status change since + * last update. Returns a positive errno otherwise. + * + * 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 @@ -1397,6 +1540,16 @@ struct ofproto_class { int (*get_stp_port_status)(struct ofport *ofport, struct ofproto_port_stp_status *s); + /* Retrieves spanning tree protocol (STP) port statistics of 'ofport'. + * + * Stores STP state for 'ofport' in 's'. If the 'enabled' member is + * false, the other member values are not meaningful. + * + * EOPNOTSUPP as a return value indicates that this ofproto_class does not + * support STP, as does a null pointer. */ + int (*get_stp_port_stats)(struct ofport *ofport, + struct ofproto_port_stp_stats *s); + /* Registers meta-data associated with the 'n_qdscp' Qualities of Service * 'queues' attached to 'ofport'. This data is not intended to be * sufficient to implement QoS. Instead, providers may use this @@ -1528,10 +1681,9 @@ struct ofproto_class { * 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. */ + * with that meter provider ID to have configuration 'config', while + * leaving '*id' unchanged. On failure, the existing meter configuration + * is left intact. */ enum ofperr (*meter_set)(struct ofproto *ofproto, ofproto_meter_id *id, const struct ofputil_meter_config *config); @@ -1581,12 +1733,17 @@ 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 *, struct ofputil_flow_mod *); +int ofproto_flow_mod(struct ofproto *, struct ofputil_flow_mod *) + OVS_EXCLUDED(ofproto_mutex); +struct rule *ofproto_refresh_rule(struct rule *rule) + OVS_EXCLUDED(ofproto_mutex); void ofproto_add_flow(struct ofproto *, const struct match *, unsigned int priority, - const struct ofpact *ofpacts, size_t ofpacts_len); + const struct ofpact *ofpacts, size_t ofpacts_len) + OVS_EXCLUDED(ofproto_mutex); bool ofproto_delete_flow(struct ofproto *, - const struct match *, unsigned int priority); + const struct match *, unsigned int priority) + OVS_EXCLUDED(ofproto_mutex); void ofproto_flush_flows(struct ofproto *); #endif /* ofproto/ofproto-provider.h */