+ criteria->table_id = table_id;
+ cls_rule_init(&criteria->cr, match, priority);
+ criteria->cookie = cookie;
+ criteria->cookie_mask = cookie_mask;
+ criteria->out_port = out_port;
+ criteria->out_group = out_group;
+}
+
+static void
+rule_criteria_destroy(struct rule_criteria *criteria)
+{
+ cls_rule_destroy(&criteria->cr);
+}
+
+void
+rule_collection_init(struct rule_collection *rules)
+{
+ rules->rules = rules->stub;
+ rules->n = 0;
+ rules->capacity = ARRAY_SIZE(rules->stub);
+}
+
+void
+rule_collection_add(struct rule_collection *rules, struct rule *rule)
+{
+ if (rules->n >= rules->capacity) {
+ size_t old_size, new_size;
+
+ old_size = rules->capacity * sizeof *rules->rules;
+ rules->capacity *= 2;
+ new_size = rules->capacity * sizeof *rules->rules;
+
+ if (rules->rules == rules->stub) {
+ rules->rules = xmalloc(new_size);
+ memcpy(rules->rules, rules->stub, old_size);
+ } else {
+ rules->rules = xrealloc(rules->rules, new_size);
+ }
+ }
+
+ rules->rules[rules->n++] = rule;
+}
+
+void
+rule_collection_ref(struct rule_collection *rules)
+ OVS_REQUIRES(ofproto_mutex)
+{
+ size_t i;
+
+ for (i = 0; i < rules->n; i++) {
+ ofproto_rule_ref(rules->rules[i]);
+ }
+}
+
+void
+rule_collection_unref(struct rule_collection *rules)
+{
+ size_t i;
+
+ for (i = 0; i < rules->n; i++) {
+ ofproto_rule_unref(rules->rules[i]);
+ }
+}
+
+void
+rule_collection_destroy(struct rule_collection *rules)
+{
+ if (rules->rules != rules->stub) {
+ free(rules->rules);
+ }
+}
+
+static enum ofperr
+collect_rule(struct rule *rule, const struct rule_criteria *c,
+ struct rule_collection *rules)
+ OVS_REQUIRES(ofproto_mutex)
+{
+ /* We ordinarily want to skip hidden rules, but there has to be a way for
+ * code internal to OVS to modify and delete them, so if the criteria
+ * specify a priority that can only be for a hidden flow, then allow hidden
+ * rules to be selected. (This doesn't allow OpenFlow clients to meddle
+ * with hidden flows because OpenFlow uses only a 16-bit field to specify
+ * priority.) */
+ if (ofproto_rule_is_hidden(rule) && c->cr.priority <= UINT16_MAX) {