&next->hmap_node)));
 }
 
-static void
-cls_rule_init__(struct cls_rule *rule,
-                const struct flow *flow, uint32_t wildcards)
+/* Converts the flow in 'flow' into a cls_rule in 'rule', with the given
+ * 'wildcards' and 'priority'. */
+void
+cls_rule_init(const struct flow *flow, const struct flow_wildcards *wildcards,
+              unsigned int priority, struct cls_rule *rule)
 {
     rule->flow = *flow;
-    flow_wildcards_init(&rule->wc, wildcards);
+    rule->wc = *wildcards;
+    rule->priority = priority;
     cls_rule_zero_wildcarded_fields(rule);
 }
 
-/* Converts the flow in 'flow' into a cls_rule in 'rule', with the given
- * 'wildcards' and 'priority'.*/
+/* Converts the flow in 'flow' into an exact-match cls_rule in 'rule', with the
+ * given 'priority'.  (For OpenFlow 1.0, exact-match rule are always highest
+ * priority, so 'priority' should be at least 65535.) */
 void
-cls_rule_from_flow(const struct flow *flow, uint32_t wildcards,
-                   unsigned int priority, struct cls_rule *rule)
+cls_rule_init_exact(const struct flow *flow,
+                    unsigned int priority, struct cls_rule *rule)
 {
-    cls_rule_init__(rule, flow, wildcards);
+    rule->flow = *flow;
+    flow_wildcards_init_exact(&rule->wc);
     rule->priority = priority;
 }
 
                     int flow_format, uint64_t cookie,
                     struct cls_rule *rule)
 {
-    uint32_t wildcards;
-    struct flow flow;
-
-    flow_from_match(match, flow_format, cookie, &flow, &wildcards);
-    cls_rule_init__(rule, &flow, wildcards);
-    rule->priority = rule->wc.wildcards ? priority : UINT16_MAX;
+    flow_from_match(match, flow_format, cookie, &rule->flow, &rule->wc);
+    rule->priority = !rule->wc.wildcards ? UINT16_MAX : priority;
+    cls_rule_zero_wildcarded_fields(rule);
 }
 
 /* Initializes 'rule' as a "catch-all" rule that matches every packet, with
 
     CLS_INC_ALL = CLS_INC_EXACT | CLS_INC_WILD
 };
 
-void cls_rule_from_flow(const struct flow *, uint32_t wildcards,
-                        unsigned int priority, struct cls_rule *);
+void cls_rule_init(const struct flow *, const struct flow_wildcards *,
+                   unsigned int priority, struct cls_rule *);
+void cls_rule_init_exact(const struct flow *, unsigned int priority,
+                         struct cls_rule *);
 void cls_rule_from_match(const struct ofp_match *, unsigned int priority,
                          int flow_format, uint64_t cookie, struct cls_rule *);
 void cls_rule_init_catchall(struct cls_rule *, unsigned int priority);
 
 
 void
 flow_from_match(const struct ofp_match *match, int flow_format,
-                ovs_be64 cookie, struct flow *flow, uint32_t *flow_wildcards)
+                ovs_be64 cookie, struct flow *flow,
+                struct flow_wildcards *wc)
 {
-       uint32_t wildcards = ntohl(match->wildcards);
-
-    flow->nw_src = match->nw_src;
-    flow->nw_dst = match->nw_dst;
-    if (flow_format == NXFF_TUN_ID_FROM_COOKIE && !(wildcards & NXFW_TUN_ID)) {
+    flow_wildcards_init(wc, ntohl(match->wildcards));
+    if (flow_format == NXFF_TUN_ID_FROM_COOKIE
+        && !(wc->wildcards & NXFW_TUN_ID)) {
         flow->tun_id = htonl(ntohll(cookie) >> 32);
     } else {
-        wildcards |= NXFW_TUN_ID;
+        wc->wildcards |= NXFW_TUN_ID;
         flow->tun_id = 0;
     }
+
+    flow->nw_src = match->nw_src;
+    flow->nw_dst = match->nw_dst;
     flow->in_port = (match->in_port == htons(OFPP_LOCAL) ? ODPP_LOCAL
                      : ntohs(match->in_port));
     flow->dl_vlan = match->dl_vlan;
     memcpy(flow->dl_dst, match->dl_dst, ETH_ADDR_LEN);
     flow->nw_tos = match->nw_tos;
     flow->nw_proto = match->nw_proto;
-    if (flow_wildcards) {
-        *flow_wildcards = wildcards;
-    }
 }
 
 char *
 
 #include "util.h"
 
 struct ds;
+struct flow_wildcards;
 struct ofp_match;
 struct ofpbuf;
 
 void flow_to_match(const struct flow *, uint32_t wildcards, int flow_format,
                    struct ofp_match *);
 void flow_from_match(const struct ofp_match *, int flow_format,
-                     ovs_be64 cookie, struct flow *, uint32_t *wildcards);
+                     ovs_be64 cookie, struct flow *, struct flow_wildcards *);
 char *flow_to_string(const struct flow *);
 void flow_format(struct ds *, const struct flow *);
 void flow_print(FILE *, const struct flow *);
 
                                        rule->idle_timeout, rule->hard_timeout,
                                        0, false);
     COVERAGE_INC(ofproto_subrule_create);
-    cls_rule_from_flow(flow, 0, (rule->cr.priority <= UINT16_MAX ? UINT16_MAX
-                        : rule->cr.priority), &subrule->cr);
+    cls_rule_init_exact(flow, (rule->cr.priority <= UINT16_MAX ? UINT16_MAX
+                               : rule->cr.priority),
+                        &subrule->cr);
 
     if (classifier_insert(&ofproto->cls, &subrule->cr)) {
         /* Can't happen,  */
         struct flow flow;
 
         odp_flow_key_to_flow(&f->key, &flow);
-        cls_rule_from_flow(&flow, 0, UINT16_MAX, &target);
+        cls_rule_init_exact(&flow, UINT16_MAX, &target);
 
         rule = rule_from_cls_rule(classifier_find_rule_exactly(&p->cls,
                                                                &target));
 
 make_rule(int wc_fields, unsigned int priority, int value_pat)
 {
     const struct cls_field *f;
+    struct flow_wildcards wc;
     struct test_rule *rule;
     uint32_t wildcards;
     struct flow flow;
     }
 
     rule = xzalloc(sizeof *rule);
-    cls_rule_from_flow(&flow, wildcards, !wildcards ? UINT_MAX : priority,
-                       &rule->cls_rule);
+    flow_wildcards_init(&wc, wildcards);
+    cls_rule_init(&flow, &wc, !wildcards ? UINT_MAX : priority,
+                  &rule->cls_rule);
     return rule;
 }