- 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. */
-
- struct ofoperation *pending; /* Operation now in progress, if nonnull. */
-
- ovs_be64 flow_cookie; /* Controller-issued identifier. */
-
- 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? */
-
- /* 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. */
-
- /* 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. */
+ /* 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. */
+
+ /* 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);
+
+ 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 (see comment on struct eviction_group for explanation) .
+ *
+ * '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);
+
+ /* OpenFlow actions. See struct rule_actions for more thread-safety
+ * notes. */
+ OVSRCU_TYPE(struct rule_actions *) actions;
+
+ /* In owning meter's 'rules' list. An empty list if there is no meter. */
+ struct list meter_list_node OVS_GUARDED_BY(ofproto_mutex);
+
+ /* 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 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 *);
+
+/* 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 {
+ /* 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. */
+};
+
+struct rule_actions *rule_actions_create(const struct ofproto *,
+ const struct ofpact *, size_t);
+void rule_actions_destroy(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(). */