X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ofproto%2Fofproto-provider.h;h=be5632eb787a08e410deba16b96b0c2f2e454e42;hb=6dd3c787f5914ea27b239b6852d8fc0815033128;hp=0148fe6123e2a4b18442dc8240e1261b28a4f13e;hpb=62c70c9d47edf2dbf5c9d0c8cd6c15c8c43dc7a8;p=mirror_ovs.git diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 0148fe612..be5632eb7 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,22 +38,26 @@ #include "guarded-list.h" #include "heap.h" #include "hindex.h" -#include "list.h" -#include "ofp-errors.h" -#include "ofp-util.h" +#include "object-collection.h" #include "ofproto/ofproto.h" +#include "openvswitch/list.h" +#include "openvswitch/ofp-actions.h" +#include "openvswitch/ofp-util.h" +#include "openvswitch/ofp-errors.h" #include "ovs-atomic.h" #include "ovs-rcu.h" #include "ovs-thread.h" -#include "shash.h" +#include "openvswitch/shash.h" #include "simap.h" #include "timeval.h" +#include "versions.h" struct match; -struct ofpact; struct ofputil_flow_mod; struct bfd_cfg; struct meter; +struct ofoperation; +struct ofproto_packet_out; extern struct ovs_mutex ofproto_mutex; @@ -72,12 +76,12 @@ struct ofproto { 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). */ char *dp_desc; /* Datapath description (NULL for default). */ - enum ofp_config_flags frag_handling; /* One of OFPC_*. */ + enum ofputil_frag_handling frag_handling; /* Datapath. */ struct hmap ports; /* Contains "struct ofport"s. */ @@ -92,12 +96,15 @@ struct ofproto { long long int eviction_group_timer; /* For rate limited reheapification. */ struct oftable *tables; int n_tables; + ovs_version_t tables_version; /* Controls which rules are visible to + * table lookups. */ /* 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); + struct ovs_list expirable OVS_GUARDED_BY(ofproto_mutex); /* Meter table. * OpenFlow meters start at 1. To avoid confusion we leave the first @@ -109,49 +116,10 @@ struct ofproto { /* 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 - * 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; /* 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 - * drivers in old versions of Linux that do not properly support VLANs when - * VLAN devices are not used. When broken device drivers are no longer in - * widespread use, we will delete these interfaces. */ - 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. */ + struct cmap groups; /* Contains "struct ofgroup"s. */ uint32_t n_groups[4] OVS_GUARDED; /* # of existing groups of each type. */ struct ofputil_group_features ogf; }; @@ -216,21 +184,18 @@ enum oftable_flags { * 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 { @@ -241,6 +206,9 @@ struct oftable { /* Maximum number of flows or UINT_MAX if there is no limit besides any * limit imposed by resource limitations. */ unsigned int max_flows; + /* Current number of flows, not counting temporary duplicates nor deferred + * deletions. */ + unsigned int n_flows; /* These members determine the handling of an attempt to add a flow that * would cause the table to have more than 'max_flows' flows. @@ -264,8 +232,30 @@ struct oftable { struct hmap eviction_groups_by_id; struct heap eviction_groups_by_size; - /* Table config: contains enum ofproto_table_config; accessed atomically. */ - atomic_uint config; + /* Flow table miss handling configuration. */ + ATOMIC(enum ofputil_table_miss) miss_config; + + /* Eviction is enabled if either the client (vswitchd) enables it or an + * OpenFlow controller enables it; thus, a nonzero value indicates that + * eviction is enabled. */ +#define EVICTION_CLIENT (1 << 0) /* Set to 1 if client enables eviction. */ +#define EVICTION_OPENFLOW (1 << 1) /* Set to 1 if OpenFlow enables eviction. */ + unsigned int eviction; + + /* If zero, vacancy events are disabled. If nonzero, this is the type of + vacancy event that is enabled: either OFPTR_VACANCY_DOWN or + OFPTR_VACANCY_UP. Only one type of vacancy event can be enabled at a + time. */ + enum ofp14_table_reason vacancy_event; + + /* Non-zero values for vacancy_up and vacancy_down indicates that vacancy + * is enabled by table-mod, else these values are set to zero when + * vacancy is disabled */ + uint8_t vacancy_down; /* Vacancy threshold when space decreases (%). */ + uint8_t vacancy_up; /* Vacancy threshold when space increases (%). */ + + atomic_ulong n_matched; + atomic_ulong n_missed; }; /* Assigns TABLE to each oftable, in turn, in OFPROTO. @@ -306,19 +296,21 @@ struct oftable { * 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: @@ -332,6 +324,19 @@ struct oftable { * 'rule->mutex', and safely written only by coding holding ofproto_mutex * AND 'rule->mutex'. These are marked OVS_GUARDED. */ +enum OVS_PACKED_ENUM rule_state { + RULE_INITIALIZED, /* Rule has been initialized, but not inserted to the + * ofproto data structures. Versioning makes sure the + * rule is not visible to lookups by other threads, even + * if the rule is added to a classifier. */ + RULE_INSERTED, /* Rule has been inserted to ofproto data structures and + * may be visible to lookups by other threads. */ + RULE_REMOVED, /* Rule has been removed from ofproto data structures, + * and may still be visible to lookups by other threads + * until they quiesce, after which the rule will be + * removed from the classifier as well. */ +}; + struct rule { /* Where this rule resides in an OpenFlow switch. * @@ -340,6 +345,8 @@ struct rule { const struct cls_rule cr; /* In owning ofproto's classifier. */ const uint8_t table_id; /* Index in ofproto's 'tables' array. */ + enum rule_state state; + /* Protects members marked OVS_GUARDED. * Readers only need to hold this mutex. * Writers must hold both this mutex AND ofproto_mutex. @@ -353,9 +360,6 @@ struct rule { * 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; @@ -367,6 +371,14 @@ struct rule { uint16_t hard_timeout OVS_GUARDED; /* In seconds from ->modified. */ uint16_t idle_timeout OVS_GUARDED; /* In seconds from ->used. */ + /* Eviction precedence. */ + const uint16_t importance; + + /* Removal reason for sending flow removed message. + * Used only if 'flags' has OFPUTIL_FF_SEND_FLOW_REM set and if the + * value is not OVS_OFPRR_NONE. */ + uint8_t removed_reason; + /* Eviction groups (see comment on struct eviction_group for explanation) . * * 'eviction_group' is this rule's eviction group, or NULL if it is not in @@ -377,10 +389,10 @@ struct rule { /* OpenFlow actions. See struct rule_actions for more thread-safety * notes. */ - OVSRCU_TYPE(struct rule_actions *) actions; + const struct rule_actions * const 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); + struct ovs_list meter_list_node OVS_GUARDED_BY(ofproto_mutex); /* Flow monitors (e.g. for NXST_FLOW_MONITOR, related to struct ofmonitor). * @@ -393,7 +405,7 @@ struct rule { /* Optimisation for flow expiry. In ofproto's 'expirable' list if this * rule is expirable, otherwise empty. */ - struct list expirable OVS_GUARDED_BY(ofproto_mutex); + struct ovs_list expirable OVS_GUARDED_BY(ofproto_mutex); /* Times. Last so that they are more likely close to the stats managed * by the provider. */ @@ -404,26 +416,12 @@ struct rule { }; void ofproto_rule_ref(struct rule *); +bool ofproto_rule_try_ref(struct rule *); void ofproto_rule_unref(struct rule *); -static inline struct rule_actions * -rule_get_actions(const struct rule *rule) -{ - return ovsrcu_get(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 *); +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". * @@ -431,36 +429,67 @@ bool rule_is_internal(const 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 rule's + * lifetime. */ struct rule_actions { - /* 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. */ + /* 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; + bool has_groups; + + /* 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_destroy(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); + +#define DECL_OFPROTO_COLLECTION(TYPE, NAME) \ + DECL_OBJECT_COLLECTION(TYPE, NAME) \ +static inline void NAME##_collection_ref(struct NAME##_collection *coll) \ +{ \ + for (size_t i = 0; i < coll->collection.n; i++) { \ + ofproto_##NAME##_ref((TYPE)coll->collection.objs[i]); \ + } \ +} \ + \ +static inline void NAME##_collection_unref(struct NAME##_collection *coll) \ +{ \ + for (size_t i = 0; i < coll->collection.n; i++) { \ + ofproto_##NAME##_unref((TYPE)coll->collection.objs[i]); \ + } \ +} -/* 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. */ +DECL_OFPROTO_COLLECTION (struct rule *, rule) - size_t capacity; /* Number of rules that will fit in 'rules'. */ - struct rule *stub[64]; /* Preallocated rules to avoid malloc(). */ -}; +#define RULE_COLLECTION_FOR_EACH(RULE, RULES) \ + for (size_t i__ = 0; \ + i__ < rule_collection_n(RULES) \ + ? (RULE = rule_collection_rules(RULES)[i__]) != NULL : false; \ + i__++) -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 *); +/* Pairwise iteration through two rule collections that must be of the same + * size. */ +#define RULE_COLLECTIONS_FOR_EACH(RULE1, RULE2, RULES1, RULES2) \ + for (size_t i__ = 0; \ + i__ < rule_collection_n(RULES1) \ + ? ((RULE1 = rule_collection_rules(RULES1)[i__]), \ + (RULE2 = rule_collection_rules(RULES2)[i__]) != NULL) \ + : false; \ + i__++) /* Limits the number of flows allowed in the datapath. Only affects the * ofproto-dpif implementation. */ @@ -475,57 +504,89 @@ extern unsigned ofproto_max_idle; * 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; -} +/* Cpu mask for pmd threads. */ +extern char *pmd_cpu_mask; + +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); 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_REQUIRES(ofproto_mutex) OVS_EXCLUDED(rule->mutex); void ofproto_rule_reduce_timeouts(struct rule *rule, uint16_t idle_timeout, 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". +/* A group within a "struct ofproto", RCU-protected. * * 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 list buckets; /* Contains "struct ofputil_bucket"s. */ - uint32_t n_buckets; + struct cmap_node cmap_node; /* In ofproto's "groups" cmap. */ + + /* Group versioning. */ + struct versions versions; + + /* 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. */ + struct ofproto * const ofproto; /* The ofproto that contains this group. */ + const uint32_t group_id; + const enum ofp11_group_type type; /* One of OFPGT_*. */ + bool being_deleted; /* Group removal has begun. */ + + const long long int created; /* Creation time. */ + const long long int modified; /* Time of last modification. */ + + const struct ovs_list buckets; /* Contains "struct ofputil_bucket"s. */ + const uint32_t n_buckets; + + const struct ofputil_group_props props; + + struct rule_collection rules OVS_GUARDED; /* Referring rules. */ }; -bool ofproto_group_lookup(const struct ofproto *ofproto, uint32_t group_id, - struct ofgroup **group) - OVS_TRY_RDLOCK(true, (*group)->rwlock); +struct ofgroup *ofproto_group_lookup(const struct ofproto *ofproto, + uint32_t group_id, ovs_version_t version, + bool take_ref); + +void ofproto_group_ref(struct ofgroup *); +bool ofproto_group_try_ref(struct ofgroup *); +void ofproto_group_unref(struct ofgroup *); + +void ofproto_group_delete_all(struct ofproto *) + OVS_EXCLUDED(ofproto_mutex); + +DECL_OFPROTO_COLLECTION (struct ofgroup *, group) -void ofproto_group_release(struct ofgroup *group) - OVS_RELEASES(group->rwlock); +#define GROUP_COLLECTION_FOR_EACH(GROUP, GROUPS) \ + for (size_t i__ = 0; \ + i__ < group_collection_n(GROUPS) \ + ? (GROUP = group_collection_groups(GROUPS)[i__]) != NULL: false; \ + i__++) + +/* Pairwise iteration through two group collections that must be of the same + * size. */ +#define GROUP_COLLECTIONS_FOR_EACH(GROUP1, GROUP2, GROUPS1, GROUPS2) \ + for (size_t i__ = 0; \ + i__ < group_collection_n(GROUPS1) \ + ? ((GROUP1 = group_collection_groups(GROUPS1)[i__]), \ + (GROUP2 = group_collection_groups(GROUPS2)[i__]) != NULL) \ + : false; \ + i__++) /* ofproto class structure, to be defined by each ofproto implementation. * @@ -616,7 +677,7 @@ void ofproto_group_release(struct ofgroup *group) * not yet been uninitialized, so the "destruct" function may refer to it. The * "destruct" function is not allowed to fail. * - * Each "dealloc" function frees raw memory that was allocated by the the + * Each "dealloc" function frees raw memory that was allocated by the * "alloc" function. The memory's base and derived members might not have ever * been initialized (but if "construct" returned successfully, then it has been * "destruct"ed already). The "dealloc" function is not allowed to fail. @@ -649,9 +710,10 @@ struct ofproto_class { * may choose to remove it all. */ void (*init)(const struct shash *iface_hints); - /* Enumerates the types of all support ofproto types into 'types'. The - * caller has already initialized 'types' and other ofproto classes might - * already have added names to it. */ + /* Enumerates the types of all supported ofproto types into 'types'. The + * caller has already initialized 'types'. The implementation should add + * its own types to 'types' but not remove any existing ones, because other + * ofproto classes might already have added names to it. */ void (*enumerate_types)(struct sset *types); /* Enumerates the names of all existing datapath of the specified 'type' @@ -746,18 +808,9 @@ struct ofproto_class { * 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(), then + * destroy all remaining groups by calling ofproto_group_delete_all(). * * The client will destroy the flow tables themselves after ->destruct() * returns. @@ -776,9 +829,6 @@ struct ofproto_class { * - 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); @@ -810,81 +860,65 @@ struct ofproto_class { * 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. - * - * 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. + /* Helper for the OpenFlow OFPT_TABLE_FEATURES 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. - * - * - 'write_actions' and 'apply_actions' to OFPAT12_OUTPUT. - * - * - 'write_setfields' and 'apply_setfields' to OFPXMT12_MASK. - * * - 'metadata_match' and 'metadata_write' to OVS_BE64_MAX. * - * - 'instructions' to OFPIT11_ALL. - * - * - 'config' to OFPTC11_TABLE_MISS_MASK. + * - 'config' to the table miss configuration. * * - 'max_entries' to 1,000,000. * - * - 'active_count' to the classifier_count() for the table. + * - Both 'nonmiss' and 'miss' to: * - * - 'lookup_count' and 'matched_count' to 0. + * * 'next' to all 1-bits for all later tables. * - * The implementation should update any members in each element for which - * it has better values: + * * 'instructions' to all instructions. * - * - 'name' to a more meaningful name. + * * 'write' and 'apply' both to: * - * - 'wildcards' to the set of wildcards actually supported by the table - * (if it doesn't support all OpenFlow wildcards). + * - 'ofpacts': All actions. * - * - 'instructions' to set the instructions actually supported by - * the table. + * - 'set_fields': All fields. * - * - 'write_actions' to set the write actions actually supported by - * the table (if it doesn't support all OpenFlow actions). + * - 'match', 'mask', and 'wildcard' to all fields. * - * - 'apply_actions' to set the apply actions actually supported by - * the table (if it doesn't support all OpenFlow actions). + * If 'stats' is nonnull, it also contains 'ofproto->n_tables' elements. + * Each element is initialized as: * - * - 'write_setfields' to set the write setfields actually supported by - * the table. + * - 'table_id' to the array index. + * + * - 'active_count' to the 'n_flows' of struct ofproto for 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); + + /* Sets the current tables version the provider should use for classifier + * lookups. This must be called with a new version number after each set + * of flow table changes has been completed, so that datapath revalidation + * can be triggered. */ + void (*set_tables_version)(struct ofproto *ofproto, ovs_version_t version); /* ## ---------------- ## */ /* ## ofport Functions ## */ @@ -917,12 +951,36 @@ struct ofproto_class { * initialization, and construct and destruct ofports to reflect all of * the changes. * + * - On graceful shutdown, the base ofproto code will destruct all + * the ports. + * * ->port_construct() returns 0 if successful, otherwise a positive errno * value. + * + * + * ->port_destruct() + * ================= + * + * ->port_destruct() takes a 'del' parameter. If the provider implements + * the datapath itself (e.g. dpif-netdev, it can ignore 'del'. On the + * other hand, if the provider is an interface to an external datapath + * (e.g. to a kernel module that implement the datapath) then 'del' should + * influence destruction behavior in the following way: + * + * - If 'del' is true, it should remove the port from the underlying + * implementation. This is the common case. + * + * - If 'del' is false, it should leave the port in the underlying + * implementation. This is used when Open vSwitch is performing a + * graceful shutdown and ensures that, across Open vSwitch restarts, + * the underlying ports are not removed and recreated. That makes an + * important difference for, e.g., "internal" ports that have + * configured IP addresses; without this distinction, the IP address + * and other configured state for the port is lost. */ struct ofport *(*port_alloc)(void); int (*port_construct)(struct ofport *ofport); - void (*port_destruct)(struct ofport *ofport); + void (*port_destruct)(struct ofport *ofport, bool del); void (*port_dealloc)(struct ofport *ofport); /* Called after 'ofport->netdev' is replaced by a new netdev object. If @@ -971,6 +1029,10 @@ struct ofproto_class { * convenient. */ int (*port_del)(struct ofproto *ofproto, ofp_port_t ofp_port); + /* Refreshes datapath configuration of 'port'. + * Returns 0 if successful, otherwise a positive errno value. */ + int (*port_set_config)(const struct ofport *port, const struct smap *cfg); + /* Get port stats */ int (*port_get_stats)(const struct ofport *port, struct netdev_stats *stats); @@ -1088,9 +1150,18 @@ struct ofproto_class { * problem), or -1 if LACP is not enabled on 'port'. * * This function may be a null pointer if the ofproto implementation does - * not support LACP. */ + * not support LACP. + */ int (*port_is_lacp_current)(const struct ofport *port); + /* Get LACP port stats. Returns -1 if LACP is not enabled on 'port'. + * + * This function may be a null pointer if the ofproto implementation does + * not support LACP. + */ + int (*port_get_lacp_stats)(const struct ofport *port, + struct lacp_slave_stats *stats); + /* ## ----------------------- ## */ /* ## OpenFlow Rule Functions ## */ /* ## ----------------------- ## */ @@ -1123,8 +1194,8 @@ struct ofproto_class { * 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: @@ -1132,9 +1203,10 @@ struct ofproto_class { * 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. @@ -1142,67 +1214,9 @@ struct ofproto_class { * 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 @@ -1218,7 +1232,7 @@ struct ofproto_class { * OpenFlow error code), the ofproto base code will uninitialize and * deallocate 'rule'. See "Rule Life Cycle" above for more details. * - * ->rule_construct() may also: + * ->rule_construct() must also: * * - Validate that the datapath supports the matching rule in 'rule->cr' * datapath. For example, if the rule's table does not support @@ -1227,8 +1241,9 @@ struct ofproto_class { * * - Validate that the datapath can correctly implement 'rule->ofpacts'. * - * Some implementations might need to defer these tasks to ->rule_insert(), - * which is also acceptable. + * After a successful construction the rest of the rule life cycle calls + * may not fail, so ->rule_construct() must also make sure that the rule + * can be inserted in to the datapath. * * * Insertion @@ -1236,35 +1251,21 @@ struct ofproto_class { * * 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. - * - * 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. + * must add the new rule to the datapath flow table and return only after + * this is complete. The 'new_rule' may be a duplicate of an 'old_rule'. + * In this case the 'old_rule' is non-null, and the implementation should + * forward rule statistics counts from the 'old_rule' to the 'new_rule' if + * 'forward_counts' is 'true', 'used' timestamp is always forwarded. This + * may not fail. * * * Deletion * ======== * * 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() (if non-null). ->rule_delete() must remove 'rule' from + * the datapath flow table and return only after this has completed + * successfully. * * Rule deletion must not fail. * @@ -1278,7 +1279,9 @@ struct ofproto_class { 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) */; + void (*rule_insert)(struct rule *rule, struct rule *old_rule, + bool forward_counts) + /* 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); @@ -1291,73 +1294,55 @@ struct ofproto_class { 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.) + /* Translates actions in 'opo->ofpacts', for 'opo->packet' in flow tables + * in version 'opo->version'. This is useful for OpenFlow OFPT_PACKET_OUT. * - * Takes ownership of 'packet' (so it should eventually free it, with - * ofpbuf_delete()). + * This function must validate that it can correctly translate + * 'opo->ofpacts'. If not, then it should return an OpenFlow error code. * - * 'flow' reflects the flow information for 'packet'. All of the - * 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 + * 'opo->flow' reflects the flow information for 'opo->packet'. All of the + * information in 'opo->flow' is extracted from 'opo->packet', except for + * 'in_port', which is assigned to the correct value for the incoming + * packet. 'tunnel' and register values should be zeroed. 'packet''s * 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'. + * Returns 0 if successful, otherwise an OpenFlow error code. * - * Returns 0 if successful, otherwise an OpenFlow error code. */ - enum ofperr (*rule_execute)(struct rule *rule, const struct flow *flow, - struct ofpbuf *packet); + * This function may be called with 'ofproto_mutex' held. */ + enum ofperr (*packet_xlate)(struct ofproto *, + struct ofproto_packet_out *opo); - /* 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.) - * - * ->rule_modify_actions() should set the following in motion: - * - * - Validate that the datapath can correctly implement the actions now - * in 'rule'. - * - * - Update the datapath flow table with the new actions. - * - * - Only if 'reset_counters' is true, reset any packet or byte counters - * associated with the rule to zero, so that rule_get_stats() will not - * longer count those packets or bytes. - * - * If the operation synchronously completes, ->rule_modify_actions() may - * call ofoperation_complete() before it returns. Otherwise, ->run() - * should call ofoperation_complete() later, after the operation does - * complete. - * - * If the operation fails, then the base ofproto code will restore the - * original 'actions' and 'n_actions' of 'rule'. - * - * ->rule_modify_actions() should not modify any base members of struct - * rule. */ - void (*rule_modify_actions)(struct rule *rule, bool reset_counters) - /* OVS_REQUIRES(ofproto_mutex) */; + /* Free resources taken by a successful packet_xlate(). If multiple + * packet_xlate() calls have been made in sequence, the corresponding + * packet_xlate_revert() calls have to be made in reverse order. */ + void (*packet_xlate_revert)(struct ofproto *, struct ofproto_packet_out *); + + /* Executes the datapath actions, translation side-effects, and stats as + * produced by ->packet_xlate(). The caller retains ownership of 'opo'. + */ + void (*packet_execute)(struct ofproto *, struct ofproto_packet_out *opo); /* Changes the OpenFlow IP fragment handling policy to 'frag_handling', * which takes one of the following values, with the corresponding * meanings: * - * - OFPC_FRAG_NORMAL: The switch should treat IP fragments the same way - * as other packets, omitting TCP and UDP port numbers (always setting - * them to 0). + * - OFPUTIL_FRAG_NORMAL: The switch should treat IP fragments the same + * way as other packets, omitting TCP and UDP port numbers (always + * setting them to 0). * - * - OFPC_FRAG_DROP: The switch should drop all IP fragments without + * - OFPUTIL_FRAG_DROP: The switch should drop all IP fragments without * passing them through the flow table. * - * - OFPC_FRAG_REASM: The switch should reassemble IP fragments before + * - OFPUTIL_FRAG_REASM: The switch should reassemble IP fragments before * passing packets through the flow table. * - * - OFPC_FRAG_NX_MATCH (a Nicira extension): Similar to OFPC_FRAG_NORMAL, - * except that TCP and UDP port numbers should be included in fragments - * with offset 0. + * - OFPUTIL_FRAG_NX_MATCH (a Nicira extension): Similar to + * OFPUTIL_FRAG_NORMAL, except that TCP and UDP port numbers should be + * included in fragments with offset 0. * * Implementations are not required to support every mode. - * OFPC_FRAG_NORMAL is the default mode when an ofproto is created. + * OFPUTIL_FRAG_NORMAL is the default mode when an ofproto is created. * * At the time of the call to ->set_frag_handling(), the current mode is * available in 'ofproto->frag_handling'. ->set_frag_handling() returns @@ -1367,50 +1352,10 @@ struct ofproto_class { * reflect the new mode. */ bool (*set_frag_handling)(struct ofproto *ofproto, - enum ofp_config_flags frag_handling); - - /* Implements the OpenFlow OFPT_PACKET_OUT command. The datapath should - * execute the 'ofpacts_len' bytes of "struct ofpacts" in 'ofpacts'. - * - * The caller retains ownership of 'packet' and of 'ofpacts', so - * ->packet_out() should not modify or free them. - * - * This function must validate that it can correctly implement 'ofpacts'. - * If not, then it should return an OpenFlow error code. - * - * 'flow' reflects the flow information for 'packet'. All of the - * information in 'flow' is extracted from 'packet', except for - * flow->in_port (see below). flow->tunnel and its register values are - * zeroed. - * - * flow->in_port comes from the OpenFlow OFPT_PACKET_OUT message. The - * implementation should reject invalid flow->in_port values by returning - * OFPERR_OFPBRC_BAD_PORT. (If the implementation called - * ofproto_init_max_ports(), then the client will reject these ports - * itself.) For consistency, the implementation should consider valid for - * flow->in_port any value that could possibly be seen in a packet that it - * passes to connmgr_send_packet_in(). Ideally, even an implementation - * that never generates packet-ins (e.g. due to hardware limitations) - * should still allow flow->in_port values for every possible physical port - * and OFPP_LOCAL. The only virtual ports (those above OFPP_MAX) that the - * caller will ever pass in as flow->in_port, other than OFPP_LOCAL, are - * OFPP_NONE and OFPP_CONTROLLER. The implementation should allow both of - * these, treating each of them as packets generated by the controller as - * opposed to packets originating from some switch port. - * - * (Ordinarily the only effect of flow->in_port is on output actions that - * involve the input port, such as actions that output to OFPP_IN_PORT, - * OFPP_FLOOD, or OFPP_ALL. flow->in_port can also affect Nicira extension - * "resubmit" actions.) - * - * 'packet' is not matched against the OpenFlow flow table, so its - * statistics should not be included in OpenFlow flow statistics. - * - * Returns 0 if successful, otherwise an OpenFlow error code. */ - enum ofperr (*packet_out)(struct ofproto *ofproto, struct ofpbuf *packet, - const struct flow *flow, - const struct ofpact *ofpacts, - size_t ofpacts_len); + enum ofputil_frag_handling frag_handling); + + enum ofperr (*nxt_resume)(struct ofproto *ofproto, + const struct ofputil_packet_in_private *); /* ## ------------------------- ## */ /* ## OFPP_NORMAL configuration ## */ @@ -1449,6 +1394,16 @@ struct ofproto_class { const struct ofproto_ipfix_flow_exporter_options *flow_exporters_options, size_t n_flow_exporters_options); + /* Gets IPFIX stats on 'ofproto' according to the exporter of birdge + * IPFIX or flow-based IPFIX. + * + * OFPERR_NXST_NOT_CONFIGURED as a return value indicates that bridge + * IPFIX or flow-based IPFIX is not configured. */ + int (*get_ipfix_stats)( + const struct ofproto *ofproto, + bool bridge_ipfix, struct ovs_list *replies + ); + /* Configures connectivity fault management on 'ofport'. * * If 'cfm_settings' is nonnull, configures CFM according to its members. @@ -1460,15 +1415,90 @@ 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 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 LLDP on 'ofport'. + * + * EOPNOTSUPP as a return value indicates that this ofproto_class does not + * support LLDP, as does a null pointer. */ + int (*set_lldp)(struct ofport *ofport, const struct smap *cfg); + + /* Checks the status of LLDP configured on 'ofport'. Returns true if the + * port's LLDP status was successfully stored into '*status'. Returns + * false if the port did not have LLDP configured, in which case '*status' + * is indeterminate. + * + * The caller must provide and own '*status'. '*status' is indeterminate + * if the return value is non-zero. */ + bool (*get_lldp_status)(const struct ofport *ofport, + struct lldp_status *status); + + /* Configures Auto Attach. + * + * If 's' is nonnull, configures Auto Attach according to its members. + * + * If 's' is null, removes any Auto Attach configuration. + */ + int (*set_aa)(struct ofproto *ofproto, + const struct aa_settings *s); + + /* If 's' is nonnull, this function registers a mapping associated with + * client data pointer 'aux' in 'ofproto'. If 'aux' is already registered + * then this function updates its configuration to 's'. Otherwise, this + * function registers a new mapping. + * + * An implementation that does not support mapping at all may set + * it to NULL or return EOPNOTSUPP. An implementation that supports + * only a subset of the functionality should implement what it can + * and return 0. + */ + int (*aa_mapping_set)(struct ofproto *ofproto, void *aux, + const struct aa_mapping_settings *s); + + /* If 's' is nonnull, this function unregisters a mapping associated with + * client data pointer 'aux' in 'ofproto'. If 'aux' is already registered + * then this function updates its configuration to 's'. Otherwise, this + * function unregisters a new mapping. + * + * An implementation that does not support mapping at all may set + * it to NULL or return EOPNOTSUPP. An implementation that supports + * only a subset of the functionality should implement what it can + * and return 0. + */ + int (*aa_mapping_unset)(struct ofproto *ofproto, void *aux); + + /* + * Returns the a list of AutoAttach VLAN operations. When Auto Attach is + * enabled, the VLAN associated with an I-SID/VLAN mapping is first + * negotiated with an Auto Attach Server. Once an I-SID VLAN mapping + * becomes active, the corresponding VLAN needs to be communicated to the + * bridge in order to add the VLAN to the trunk port linking the Auto + * Attach Client (in this case openvswitch) and the Auto Attach Server. + * + * The list entries are of type "struct bridge_aa_vlan". Each entry + * specifies the operation (add or remove), the interface on which to + * execute the operation and the VLAN. + */ + int (*aa_vlan_get_queued)(struct ofproto *ofproto, struct ovs_list *list); + + /* + * Returns the current number of entries in the list of VLAN operations + * in the Auto Attach Client (see previous function description + * aa_vlan_get_queued). Returns 0 if Auto Attach is disabled. + */ + unsigned int (*aa_vlan_get_queue_size)(struct ofproto *ofproto); /* Configures BFD on 'ofport'. * @@ -1480,6 +1510,10 @@ struct ofproto_class { * 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. */ @@ -1542,6 +1576,53 @@ struct ofproto_class { int (*get_stp_port_stats)(struct ofport *ofport, struct ofproto_port_stp_stats *s); + /* Configures Rapid Spanning Tree Protocol (RSTP) on 'ofproto' using the + * settings defined in 's'. + * + * If 's' is nonnull, configures RSTP according to its members. + * + * If 's' is null, removes any RSTP configuration from 'ofproto'. + * + * EOPNOTSUPP as a return value indicates that this ofproto_class does not + * support RSTP, as does a null pointer. */ + void (*set_rstp)(struct ofproto *ofproto, + const struct ofproto_rstp_settings *s); + + /* Retrieves state of Rapid Spanning Tree Protocol (RSTP) on 'ofproto'. + * + * Stores RSTP state for 'ofproto' 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 RSTP, as does a null pointer. */ + void (*get_rstp_status)(struct ofproto *ofproto, + struct ofproto_rstp_status *s); + + /* Configures Rapid Spanning Tree Protocol (RSTP) on 'ofport' using the + * settings defined in 's'. + * + * If 's' is nonnull, configures RSTP according to its members. The + * caller is responsible for assigning RSTP port numbers (using the + * 'port_num' member in the range of 1 through 255, inclusive) and + * ensuring there are no duplicates. + * + * If 's' is null, removes any RSTP configuration from 'ofport'. + * + * EOPNOTSUPP as a return value indicates that this ofproto_class does not + * support STP, as does a null pointer. */ + void (*set_rstp_port)(struct ofport *ofport, + const struct ofproto_port_rstp_settings *s); + + /* Retrieves Rapid Spanning Tree Protocol (RSTP) port status of 'ofport'. + * + * Stores RSTP 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 RSTP, as does a null pointer. */ + void (*get_rstp_port_status)(struct ofport *ofport, + struct ofproto_port_rstp_status *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 @@ -1632,24 +1713,31 @@ struct ofproto_class { void (*set_mac_table_config)(struct ofproto *ofproto, unsigned int idle_time, size_t max_entries); -/* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.) - * - * This is deprecated. It is only for compatibility with broken device drivers - * in old versions of Linux that do not properly support VLANs when VLAN - * devices are not used. When broken device drivers are no longer in - * widespread use, we will delete these interfaces. */ + /* 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); - /* If 'realdev_ofp_port' is nonzero, then this function configures 'ofport' - * as a VLAN splinter port for VLAN 'vid', associated with the real device - * that has OpenFlow port number 'realdev_ofp_port'. + /* Configures multicast snooping port's flood setting on 'ofproto'. * - * If 'realdev_ofp_port' is zero, then this function deconfigures 'ofport' - * as a VLAN splinter port. + * If 's' is nonnull, this function updates multicast snooping + * configuration to 's' in 'ofproto'. * - * This function should be NULL if an implementation does not support it. - */ - int (*set_realdev)(struct ofport *ofport, - ofp_port_t realdev_ofp_port, int vid); + * If 's' is NULL, this function doesn't change anything. + * + * 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, + const struct ofproto_mcast_snooping_port_settings *s); /* ## ------------------------ ## */ /* ## OpenFlow meter functions ## */ @@ -1702,10 +1790,23 @@ struct ofproto_class { void (*group_destruct)(struct ofgroup *); void (*group_dealloc)(struct ofgroup *); - enum ofperr (*group_modify)(struct ofgroup *, struct ofgroup *victim); + void (*group_modify)(struct ofgroup *); enum ofperr (*group_get_stats)(const struct ofgroup *, struct ofputil_group_stats *); + +/* ## --------------------- ## */ +/* ## Datapath information ## */ +/* ## --------------------- ## */ + /* Retrieve the version string of the datapath. The version + * string can be NULL if it can not be determined. + * + * The version retuned is read only. The caller should not + * free it. + * + * This function should be NULL if an implementation does not support it. + */ + const char *(*get_datapath_version)(const struct ofproto *); }; extern const struct ofproto_class ofproto_dpif_class; @@ -1713,29 +1814,153 @@ 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 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); +/* Criteria that flow_mod and other operations use for selecting rules on + * which to operate. */ +struct rule_criteria { + /* An OpenFlow table or 255 for all tables. */ + uint8_t table_id; + + /* OpenFlow matching criteria. Interpreted different in "loose" way by + * collect_rules_loose() and "strict" way by collect_rules_strict(), as + * defined in the OpenFlow spec. */ + struct cls_rule cr; + ovs_version_t version; + + /* Matching criteria for the OpenFlow cookie. Consider a bit B in a rule's + * cookie and the corresponding bits C in 'cookie' and M in 'cookie_mask'. + * The rule will not be selected if M is 1 and B != C. */ + ovs_be64 cookie; + ovs_be64 cookie_mask; + + /* Selection based on actions within a rule: + * + * If out_port != OFPP_ANY, selects only rules that output to out_port. + * If out_group != OFPG_ALL, select only rules that output to out_group. */ + ofp_port_t out_port; + uint32_t out_group; + + /* If true, collects only rules that are modifiable. */ + bool include_hidden; + bool include_readonly; +}; -int ofproto_flow_mod(struct ofproto *, struct ofputil_flow_mod *) +/* flow_mod with execution context. */ +struct ofproto_flow_mod { + /* Allocated by 'init' phase, may be freed after 'start' phase, as these + * are not needed for 'revert' nor 'finish'. */ + struct rule *temp_rule; + struct rule_criteria criteria; + struct cls_conjunction *conjs; + size_t n_conjs; + + /* Replicate needed fields from ofputil_flow_mod to not need it after the + * flow has been created. */ + uint16_t command; + bool modify_cookie; + /* Fields derived from ofputil_flow_mod. */ + bool modify_may_add_flow; + enum nx_flow_update_event event; + + /* These are only used during commit execution. + * ofproto_flow_mod_uninit() does NOT clean these up. */ + ovs_version_t version; /* Version in which changes take + * effect. */ + bool learn_adds_rule; /* Learn execution adds a rule. */ + struct rule_collection old_rules; /* Affected rules. */ + struct rule_collection new_rules; /* Replacement rules. */ +}; + +void ofproto_flow_mod_uninit(struct ofproto_flow_mod *); + +/* port_mod with execution context. */ +struct ofproto_port_mod { + struct ofputil_port_mod pm; + struct ofport *port; /* Affected port. */ +}; + +/* flow_mod with execution context. */ +struct ofproto_group_mod { + struct ofputil_group_mod gm; + + ovs_version_t version; /* Version in which changes take + * effect. */ + struct ofgroup *new_group; /* New group. */ + struct group_collection old_groups; /* Affected groups. */ +}; + +/* packet_out with execution context. */ +struct ofproto_packet_out { + ovs_version_t version; + struct dp_packet *packet; + struct flow *flow; + struct ofpact *ofpacts; + size_t ofpacts_len; + + void *aux; /* Provider private. */ +}; + +void ofproto_packet_out_uninit(struct ofproto_packet_out *); + +enum ofperr ofproto_flow_mod(struct ofproto *, const struct ofputil_flow_mod *) OVS_EXCLUDED(ofproto_mutex); -struct rule *ofproto_refresh_rule(struct rule *rule) +enum ofperr ofproto_flow_mod_init_for_learn(struct ofproto *, + const struct ofputil_flow_mod *, + struct ofproto_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) +enum ofperr ofproto_flow_mod_learn(struct ofproto_flow_mod *, bool keep_ref) OVS_EXCLUDED(ofproto_mutex); -bool ofproto_delete_flow(struct ofproto *, - const struct match *, unsigned int priority) +enum ofperr ofproto_flow_mod_learn_refresh(struct ofproto_flow_mod *ofm); +enum ofperr ofproto_flow_mod_learn_start(struct ofproto_flow_mod *ofm) + OVS_REQUIRES(ofproto_mutex); +void ofproto_flow_mod_learn_revert(struct ofproto_flow_mod *ofm) + OVS_REQUIRES(ofproto_mutex); +void ofproto_flow_mod_learn_finish(struct ofproto_flow_mod *ofm, + struct ofproto *orig_ofproto) + OVS_REQUIRES(ofproto_mutex); +void ofproto_add_flow(struct ofproto *, const struct match *, int priority, + const struct ofpact *ofpacts, size_t ofpacts_len) OVS_EXCLUDED(ofproto_mutex); +void ofproto_delete_flow(struct ofproto *, const struct match *, int priority) + OVS_REQUIRES(ofproto_mutex); void ofproto_flush_flows(struct ofproto *); +enum ofperr ofproto_check_ofpacts(struct ofproto *, + const struct ofpact ofpacts[], + size_t ofpacts_len); + +static inline const struct rule_actions * +rule_get_actions(const struct rule *rule) +{ + return 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 */