flow: Separate "flow_t" from "struct odp_flow_key".
authorBen Pfaff <blp@nicira.com>
Thu, 1 Apr 2010 22:27:11 +0000 (15:27 -0700)
committerBen Pfaff <blp@nicira.com>
Thu, 1 Apr 2010 22:27:11 +0000 (15:27 -0700)
The "struct odp_flow_key" used in the kernel datapath is conceptually
separate from the "flow_t" used in userspace, but until now we have
used the latter as a typedef for the former for convenience.  This commit
separates them.  This makes it possible in upcoming commits to change
them independently.

lib/classifier.c
lib/dpif-netdev.c
lib/dpif.c
lib/flow.c
lib/flow.h
lib/odp-util.c
lib/odp-util.h
ofproto/ofproto.c
tests/test-classifier.c

index ee78dad..d9345f6 100644 (file)
@@ -58,7 +58,6 @@ void
 cls_rule_from_flow(struct cls_rule *rule, const flow_t *flow,
                    uint32_t wildcards, unsigned int priority)
 {
-    assert(!flow->reserved[0] && !flow->reserved[1] && !flow->reserved[2]);
     rule->flow = *flow;
     flow_wildcards_init(&rule->wc, wildcards);
     rule->priority = priority;
index 1cc4ed4..ab8910a 100644 (file)
@@ -95,14 +95,14 @@ struct dp_netdev_port {
 /* A flow in dp_netdev's 'flow_table'. */
 struct dp_netdev_flow {
     struct hmap_node node;      /* Element in dp_netdev's 'flow_table'. */
-    flow_t key;
+    struct odp_flow_key key;
 
     /* Statistics. */
-       struct timeval used;        /* Last used time, in milliseconds. */
-       long long int packet_count; /* Number of packets matched. */
-       long long int byte_count;   /* Number of bytes matched. */
-       uint8_t ip_tos;             /* IP TOS value. */
-       uint16_t tcp_ctl;           /* Bitwise-OR of seen tcp_ctl values. */
+    struct timeval used;        /* Last used time, in milliseconds. */
+    long long int packet_count; /* Number of packets matched. */
+    long long int byte_count;   /* Number of bytes matched. */
+    uint8_t ip_tos;             /* IP TOS value. */
+    uint16_t tcp_ctl;           /* Bitwise-OR of seen tcp_ctl values. */
 
     /* Actions. */
     union odp_action *actions;
@@ -137,7 +137,7 @@ static int do_del_port(struct dp_netdev *, uint16_t port_no);
 static int dp_netdev_output_control(struct dp_netdev *, const struct ofpbuf *,
                                     int queue_no, int port_no, uint32_t arg);
 static int dp_netdev_execute_actions(struct dp_netdev *,
-                                     struct ofpbuf *, flow_t *,
+                                     struct ofpbuf *, struct odp_flow_key *,
                                      const union odp_action *, int n);
 
 static struct dpif_netdev *
@@ -659,14 +659,14 @@ dpif_netdev_port_group_set(struct dpif *dpif, int group_no,
 }
 
 static struct dp_netdev_flow *
-dp_netdev_lookup_flow(const struct dp_netdev *dp, const flow_t *key)
+dp_netdev_lookup_flow(const struct dp_netdev *dp,
+                      const struct odp_flow_key *key)
 {
     struct dp_netdev_flow *flow;
 
-    assert(!key->reserved[0] && !key->reserved[1] && !key->reserved[2]);
     HMAP_FOR_EACH_WITH_HASH (flow, struct dp_netdev_flow, node,
-                             flow_hash(key, 0), &dp->flow_table) {
-        if (flow_equal(&flow->key, key)) {
+                             odp_flow_key_hash(key, 0), &dp->flow_table) {
+        if (odp_flow_key_equal(&flow->key, key)) {
             return flow;
         }
     }
@@ -812,7 +812,6 @@ add_flow(struct dpif *dpif, struct odp_flow *odp_flow)
 
     flow = xzalloc(sizeof *flow);
     flow->key = odp_flow->key;
-    memset(flow->key.reserved, 0, sizeof flow->key.reserved);
 
     error = set_flow_actions(flow, odp_flow);
     if (error) {
@@ -820,7 +819,8 @@ add_flow(struct dpif *dpif, struct odp_flow *odp_flow)
         return error;
     }
 
-    hmap_insert(&dp->flow_table, &flow->node, flow_hash(&flow->key, 0));
+    hmap_insert(&dp->flow_table, &flow->node,
+                odp_flow_key_hash(&flow->key, 0));
     return 0;
 }
 
@@ -907,6 +907,7 @@ dpif_netdev_execute(struct dpif *dpif, uint16_t in_port,
     struct dp_netdev *dp = get_dp_netdev(dpif);
     struct ofpbuf copy;
     bool mutates;
+    struct odp_flow_key key;
     flow_t flow;
     int error;
 
@@ -933,7 +934,8 @@ dpif_netdev_execute(struct dpif *dpif, uint16_t in_port,
         copy = *packet;
     }
     flow_extract(&copy, in_port, &flow);
-    error = dp_netdev_execute_actions(dp, &copy, &flow, actions, n_actions);
+    odp_flow_key_from_flow(&key, &flow);
+    error = dp_netdev_execute_actions(dp, &copy, &key, actions, n_actions);
     if (mutates) {
         ofpbuf_uninit(&copy);
     }
@@ -1002,7 +1004,8 @@ dpif_netdev_recv_wait(struct dpif *dpif)
 }
 \f
 static void
-dp_netdev_flow_used(struct dp_netdev_flow *flow, const flow_t *key,
+dp_netdev_flow_used(struct dp_netdev_flow *flow,
+                    const struct odp_flow_key *key,
                     const struct ofpbuf *packet)
 {
     time_timeval(&flow->used);
@@ -1024,12 +1027,14 @@ dp_netdev_port_input(struct dp_netdev *dp, struct dp_netdev_port *port,
                      struct ofpbuf *packet)
 {
     struct dp_netdev_flow *flow;
-    flow_t key;
+    struct odp_flow_key key;
+    flow_t f;
 
-    if (flow_extract(packet, port->port_no, &key) && dp->drop_frags) {
+    if (flow_extract(packet, port->port_no, &f) && dp->drop_frags) {
         dp->n_frags++;
         return;
     }
+    odp_flow_key_from_flow(&key, &f);
 
     flow = dp_netdev_lookup_flow(dp, &key);
     if (flow) {
@@ -1096,7 +1101,7 @@ dp_netdev_wait(void)
  * bits outside of 'mask'.
  */
 static void
-dp_netdev_modify_vlan_tci(struct ofpbuf *packet, flow_t *key,
+dp_netdev_modify_vlan_tci(struct ofpbuf *packet, struct odp_flow_key *key,
                           uint16_t tci, uint16_t mask)
 {
     struct vlan_eth_header *veh;
@@ -1125,7 +1130,7 @@ dp_netdev_modify_vlan_tci(struct ofpbuf *packet, flow_t *key,
 }
 
 static void
-dp_netdev_strip_vlan(struct ofpbuf *packet, flow_t *key)
+dp_netdev_strip_vlan(struct ofpbuf *packet, struct odp_flow_key *key)
 {
     struct vlan_eth_header *veh = packet->l2;
     if (veh->veth_type == htons(ETH_TYPE_VLAN)) {
@@ -1145,7 +1150,7 @@ dp_netdev_strip_vlan(struct ofpbuf *packet, flow_t *key)
 }
 
 static void
-dp_netdev_set_dl_src(struct ofpbuf *packet, flow_t *key,
+dp_netdev_set_dl_src(struct ofpbuf *packet, struct odp_flow_key *key,
                      const uint8_t dl_addr[ETH_ADDR_LEN])
 {
     struct eth_header *eh = packet->l2;
@@ -1154,7 +1159,7 @@ dp_netdev_set_dl_src(struct ofpbuf *packet, flow_t *key,
 }
 
 static void
-dp_netdev_set_dl_dst(struct ofpbuf *packet, flow_t *key,
+dp_netdev_set_dl_dst(struct ofpbuf *packet, struct odp_flow_key *key,
                      const uint8_t dl_addr[ETH_ADDR_LEN])
 {
     struct eth_header *eh = packet->l2;
@@ -1163,7 +1168,7 @@ dp_netdev_set_dl_dst(struct ofpbuf *packet, flow_t *key,
 }
 
 static void
-dp_netdev_set_nw_addr(struct ofpbuf *packet, flow_t *key,
+dp_netdev_set_nw_addr(struct ofpbuf *packet, struct odp_flow_key *key,
                       const struct odp_action_nw_addr *a)
 {
     if (key->dl_type == htons(ETH_TYPE_IP)) {
@@ -1195,7 +1200,7 @@ dp_netdev_set_nw_addr(struct ofpbuf *packet, flow_t *key,
 }
 
 static void
-dp_netdev_set_nw_tos(struct ofpbuf *packet, flow_t *key,
+dp_netdev_set_nw_tos(struct ofpbuf *packet, struct odp_flow_key *key,
                      const struct odp_action_nw_tos *a)
 {
     if (key->dl_type == htons(ETH_TYPE_IP)) {
@@ -1213,10 +1218,10 @@ dp_netdev_set_nw_tos(struct ofpbuf *packet, flow_t *key,
 }
 
 static void
-dp_netdev_set_tp_port(struct ofpbuf *packet, flow_t *key,
+dp_netdev_set_tp_port(struct ofpbuf *packet, struct odp_flow_key *key,
                       const struct odp_action_tp_port *a)
 {
-       if (key->dl_type == htons(ETH_TYPE_IP)) {
+    if (key->dl_type == htons(ETH_TYPE_IP)) {
         uint16_t *field;
         if (key->nw_proto == IPPROTO_TCP) {
             struct tcp_header *th = packet->l4;
@@ -1244,7 +1249,7 @@ static void
 dp_netdev_output_port(struct dp_netdev *dp, struct ofpbuf *packet,
                       uint16_t out_port)
 {
-       struct dp_netdev_port *p = dp->ports[out_port];
+    struct dp_netdev_port *p = dp->ports[out_port];
     if (p) {
         netdev_send(p->netdev, packet);
     }
@@ -1254,15 +1259,15 @@ static void
 dp_netdev_output_group(struct dp_netdev *dp, uint16_t group, uint16_t in_port,
                        struct ofpbuf *packet)
 {
-       struct odp_port_group *g = &dp->groups[group];
-       int i;
+    struct odp_port_group *g = &dp->groups[group];
+    int i;
 
-       for (i = 0; i < g->n_ports; i++) {
+    for (i = 0; i < g->n_ports; i++) {
         uint16_t out_port = g->ports[i];
         if (out_port != in_port) {
             dp_netdev_output_port(dp, packet, out_port);
         }
-       }
+    }
 }
 
 static int
@@ -1294,66 +1299,66 @@ dp_netdev_output_control(struct dp_netdev *dp, const struct ofpbuf *packet,
 
 static int
 dp_netdev_execute_actions(struct dp_netdev *dp,
-                          struct ofpbuf *packet, flow_t *key,
+                          struct ofpbuf *packet, struct odp_flow_key *key,
                           const union odp_action *actions, int n_actions)
 {
     int i;
     for (i = 0; i < n_actions; i++) {
         const union odp_action *a = &actions[i];
 
-               switch (a->type) {
-               case ODPAT_OUTPUT:
+        switch (a->type) {
+        case ODPAT_OUTPUT:
             dp_netdev_output_port(dp, packet, a->output.port);
-                       break;
+            break;
 
-               case ODPAT_OUTPUT_GROUP:
-                       dp_netdev_output_group(dp, a->output_group.group, key->in_port,
+        case ODPAT_OUTPUT_GROUP:
+            dp_netdev_output_group(dp, a->output_group.group, key->in_port,
                                    packet);
-                       break;
+            break;
 
-               case ODPAT_CONTROLLER:
+        case ODPAT_CONTROLLER:
             dp_netdev_output_control(dp, packet, _ODPL_ACTION_NR,
                                      key->in_port, a->controller.arg);
-                       break;
+            break;
 
-               case ODPAT_SET_VLAN_VID:
-                       dp_netdev_modify_vlan_tci(packet, key, ntohs(a->vlan_vid.vlan_vid),
+               case ODPAT_SET_VLAN_VID:
+                       dp_netdev_modify_vlan_tci(packet, key, ntohs(a->vlan_vid.vlan_vid),
                                       VLAN_VID_MASK);
-            break;
+             break;
 
-               case ODPAT_SET_VLAN_PCP:
-                       dp_netdev_modify_vlan_tci(
-                packet, key, a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT,
-                VLAN_PCP_MASK);
-            break;
+               case ODPAT_SET_VLAN_PCP:
+                       dp_netdev_modify_vlan_tci(
+                 packet, key, a->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT,
+                 VLAN_PCP_MASK);
+              break;
 
-               case ODPAT_STRIP_VLAN:
-                       dp_netdev_strip_vlan(packet, key);
-                       break;
+        case ODPAT_STRIP_VLAN:
+            dp_netdev_strip_vlan(packet, key);
+            break;
 
-               case ODPAT_SET_DL_SRC:
+        case ODPAT_SET_DL_SRC:
             dp_netdev_set_dl_src(packet, key, a->dl_addr.dl_addr);
-                       break;
+            break;
 
-               case ODPAT_SET_DL_DST:
+        case ODPAT_SET_DL_DST:
             dp_netdev_set_dl_dst(packet, key, a->dl_addr.dl_addr);
-                       break;
-
-               case ODPAT_SET_NW_SRC:
-               case ODPAT_SET_NW_DST:
-                       dp_netdev_set_nw_addr(packet, key, &a->nw_addr);
-                       break;
-
-               case ODPAT_SET_NW_TOS:
-                       dp_netdev_set_nw_tos(packet, key, &a->nw_tos);
-                       break;
-
-               case ODPAT_SET_TP_SRC:
-               case ODPAT_SET_TP_DST:
-                       dp_netdev_set_tp_port(packet, key, &a->tp_port);
-                       break;
-               }
-       }
+            break;
+
+        case ODPAT_SET_NW_SRC:
+        case ODPAT_SET_NW_DST:
+            dp_netdev_set_nw_addr(packet, key, &a->nw_addr);
+            break;
+
+        case ODPAT_SET_NW_TOS:
+            dp_netdev_set_nw_tos(packet, key, &a->nw_tos);
+            break;
+
+        case ODPAT_SET_TP_SRC:
+        case ODPAT_SET_TP_DST:
+            dp_netdev_set_tp_port(packet, key, &a->tp_port);
+            break;
+        }
+    }
     return 0;
 }
 
index 315f11f..44d74b8 100644 (file)
@@ -1145,7 +1145,8 @@ should_log_flow_message(int error)
 
 static void
 log_flow_message(const struct dpif *dpif, int error, const char *operation,
-                 const flow_t *flow, const struct odp_flow_stats *stats,
+                 const struct odp_flow_key *flow,
+                 const struct odp_flow_stats *stats,
                  const union odp_action *actions, size_t n_actions)
 {
     struct ds ds = DS_EMPTY_INITIALIZER;
@@ -1157,7 +1158,7 @@ log_flow_message(const struct dpif *dpif, int error, const char *operation,
     if (error) {
         ds_put_format(&ds, "(%s) ", strerror(error));
     }
-    flow_format(&ds, flow);
+    format_odp_flow_key(&ds, flow);
     if (stats) {
         ds_put_cstr(&ds, ", ");
         format_odp_flow_stats(&ds, stats);
index 7d368bb..28aec66 100644 (file)
@@ -280,7 +280,6 @@ flow_from_match(flow_t *flow, uint32_t *wildcards,
     memcpy(flow->dl_dst, match->dl_dst, ETH_ADDR_LEN);
     flow->nw_tos = match->nw_tos;
     flow->nw_proto = match->nw_proto;
-    memset(flow->reserved, 0, sizeof flow->reserved);
 }
 
 char *
index ca140af..9eace03 100644 (file)
@@ -31,7 +31,29 @@ struct ds;
 struct ofp_match;
 struct ofpbuf;
 
-typedef struct odp_flow_key flow_t;
+typedef struct flow flow_t;
+struct flow {
+    uint32_t nw_src;            /* IP source address. */
+    uint32_t nw_dst;            /* IP destination address. */
+    uint16_t in_port;           /* Input switch port. */
+    uint16_t dl_vlan;           /* Input VLAN. */
+    uint16_t dl_type;           /* Ethernet frame type. */
+    uint16_t tp_src;            /* TCP/UDP source port. */
+    uint16_t tp_dst;            /* TCP/UDP destination port. */
+    uint8_t dl_src[ETH_ALEN];   /* Ethernet source address. */
+    uint8_t dl_dst[ETH_ALEN];   /* Ethernet destination address. */
+    uint8_t nw_proto;           /* IP protocol or low 8 bits of ARP opcode. */
+    uint8_t dl_vlan_pcp;        /* Input VLAN priority. */
+    uint8_t nw_tos;             /* IP ToS (DSCP field, 6 bits). */
+};
+
+/* Assert that there are FLOW_SIG_SIZE bytes of significant data in "struct
+ * flow", followed by FLOW_PAD_SIZE bytes of padding. */
+#define FLOW_SIG_SIZE 33
+#define FLOW_PAD_SIZE 3
+BUILD_ASSERT_DECL(offsetof(struct flow, nw_tos) == FLOW_SIG_SIZE - 1);
+BUILD_ASSERT_DECL(sizeof(((struct flow *)0)->nw_tos) == 1);
+BUILD_ASSERT_DECL(sizeof(struct flow) == FLOW_SIG_SIZE + FLOW_PAD_SIZE);
 
 int flow_extract(struct ofpbuf *, uint16_t in_port, flow_t *);
 void flow_extract_stats(const flow_t *flow, struct ofpbuf *packet, 
@@ -48,7 +70,7 @@ static inline size_t flow_hash(const flow_t *, uint32_t basis);
 static inline int
 flow_compare(const flow_t *a, const flow_t *b)
 {
-    return memcmp(a, b, sizeof *a);
+    return memcmp(a, b, FLOW_SIG_SIZE);
 }
 
 static inline bool
@@ -60,9 +82,7 @@ flow_equal(const flow_t *a, const flow_t *b)
 static inline size_t
 flow_hash(const flow_t *flow, uint32_t basis)
 {
-    BUILD_ASSERT_DECL(!(sizeof *flow % sizeof(uint32_t)));
-    return hash_words((const uint32_t *) flow,
-                      sizeof *flow / sizeof(uint32_t), basis);
+    return hash_bytes(flow, FLOW_SIG_SIZE, basis);
 }
 
 /* Information on wildcards for a flow, as a supplement to flow_t. */
index 87ac92b..09d067c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -42,6 +42,19 @@ odp_actions_add(struct odp_actions *actions, uint16_t type)
     return a;
 }
 
+void
+format_odp_flow_key(struct ds *ds, const struct odp_flow_key *key)
+{
+    ds_put_format(ds, "in_port%04x:vlan%d:pcp%d mac"ETH_ADDR_FMT
+                  "->"ETH_ADDR_FMT" type%04x proto%"PRId8" tos%"PRIu8
+                  " ip"IP_FMT"->"IP_FMT" port%d->%d",
+                  key->in_port, ntohs(key->dl_vlan), key->dl_vlan_pcp,
+                  ETH_ADDR_ARGS(key->dl_src), ETH_ADDR_ARGS(key->dl_dst),
+                  ntohs(key->dl_type), key->nw_proto, key->nw_tos,
+                  IP_ARGS(&key->nw_src), IP_ARGS(&key->nw_dst),
+                  ntohs(key->tp_src), ntohs(key->tp_dst));
+}
+
 void
 format_odp_action(struct ds *ds, const union odp_action *a)
 {
@@ -128,10 +141,44 @@ format_odp_flow_stats(struct ds *ds, const struct odp_flow_stats *s)
 void
 format_odp_flow(struct ds *ds, const struct odp_flow *f)
 {
-    flow_format(ds, &f->key);
+    format_odp_flow_key(ds, &f->key);
     ds_put_cstr(ds, ", ");
     format_odp_flow_stats(ds, &f->stats);
     ds_put_cstr(ds, ", actions:");
     format_odp_actions(ds, f->actions, f->n_actions);
 }
+\f
+void
+odp_flow_key_from_flow(struct odp_flow_key *key, const struct flow *flow)
+{
+    key->nw_src = flow->nw_src;
+    key->nw_dst = flow->nw_dst;
+    key->in_port = flow->in_port;
+    key->dl_vlan = flow->dl_vlan;
+    key->dl_type = flow->dl_type;
+    key->tp_src = flow->tp_src;
+    key->tp_dst = flow->tp_dst;
+    memcpy(key->dl_src, flow->dl_src, ETH_ALEN);
+    memcpy(key->dl_dst, flow->dl_dst, ETH_ALEN);
+    key->nw_proto = flow->nw_proto;
+    key->dl_vlan_pcp = flow->dl_vlan_pcp;
+    key->nw_tos = flow->nw_tos;
+    memset(key->reserved, 0, sizeof key->reserved);
+}
 
+void
+odp_flow_key_to_flow(const struct odp_flow_key *key, struct flow *flow)
+{
+    flow->nw_src = key->nw_src;
+    flow->nw_dst = key->nw_dst;
+    flow->in_port = key->in_port;
+    flow->dl_vlan = key->dl_vlan;
+    flow->dl_type = key->dl_type;
+    flow->tp_src = key->tp_src;
+    flow->tp_dst = key->tp_dst;
+    memcpy(flow->dl_src, key->dl_src, ETH_ALEN);
+    memcpy(flow->dl_dst, key->dl_dst, ETH_ALEN);
+    flow->nw_proto = key->nw_proto;
+    flow->dl_vlan_pcp = key->dl_vlan_pcp;
+    flow->nw_tos = key->nw_tos;
+}
index 6d67ec2..4c9cb91 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include <stdbool.h>
 #include <stdint.h>
+#include <string.h>
+#include "hash.h"
 #include "openflow/openflow.h"
 #include "openvswitch/datapath-protocol.h"
 
 struct ds;
+struct flow;
 
 /* The kernel datapaths limits actions to those that fit in a single page of
  * memory, so there is no point in allocating more than that.  */
@@ -73,10 +76,28 @@ odp_port_to_ofp_port(uint16_t odp_port)
     }
 }
 
+void format_odp_flow_key(struct ds *, const struct odp_flow_key *);
 void format_odp_action(struct ds *, const union odp_action *);
 void format_odp_actions(struct ds *, const union odp_action *actions,
                         size_t n_actions);
 void format_odp_flow_stats(struct ds *, const struct odp_flow_stats *);
 void format_odp_flow(struct ds *, const struct odp_flow *);
 
+void odp_flow_key_from_flow(struct odp_flow_key *, const struct flow *);
+void odp_flow_key_to_flow(const struct odp_flow_key *, struct flow *);
+
+static inline bool
+odp_flow_key_equal(const struct odp_flow_key *a, const struct odp_flow_key *b)
+{
+    return !memcmp(a, b, sizeof *a);
+}
+
+static inline size_t
+odp_flow_key_hash(const struct odp_flow_key *flow, uint32_t basis)
+{
+    BUILD_ASSERT_DECL(!(sizeof *flow % sizeof(uint32_t)));
+    return hash_words((const uint32_t *) flow,
+                      sizeof *flow / sizeof(uint32_t), basis);
+}
+
 #endif /* odp-util.h */
index 6976a0e..a9df90e 100644 (file)
@@ -1663,7 +1663,7 @@ do_put_flow(struct ofproto *ofproto, struct rule *rule, int flags,
             struct odp_flow_put *put)
 {
     memset(&put->flow.stats, 0, sizeof put->flow.stats);
-    put->flow.key = rule->cr.flow;
+    odp_flow_key_from_flow(&put->flow.key, &rule->cr.flow);
     put->flow.actions = rule->odp_actions;
     put->flow.n_actions = rule->n_odp_actions;
     put->flags = flags;
@@ -1758,7 +1758,7 @@ rule_uninstall(struct ofproto *p, struct rule *rule)
     if (rule->installed) {
         struct odp_flow odp_flow;
 
-        odp_flow.key = rule->cr.flow;
+        odp_flow_key_from_flow(&odp_flow.key, &rule->cr.flow);
         odp_flow.actions = NULL;
         odp_flow.n_actions = 0;
         if (!dpif_flow_del(p->dpif, &odp_flow)) {
@@ -2589,12 +2589,12 @@ query_stats(struct ofproto *p, struct rule *rule,
     if (rule->cr.wc.wildcards) {
         size_t i = 0;
         LIST_FOR_EACH (subrule, struct rule, list, &rule->list) {
-            odp_flows[i++].key = subrule->cr.flow;
+            odp_flow_key_from_flow(&odp_flows[i++].key, &subrule->cr.flow);
             packet_count += subrule->packet_count;
             byte_count += subrule->byte_count;
         }
     } else {
-        odp_flows[0].key = rule->cr.flow;
+        odp_flow_key_from_flow(&odp_flows[0].key, &rule->cr.flow);
     }
 
     /* Fetch up-to-date statistics from the datapath and add them in. */
@@ -3454,7 +3454,7 @@ active_timeout(struct ofproto *ofproto, struct rule *rule)
         /* Get updated flow stats. */
         memset(&odp_flow, 0, sizeof odp_flow);
         if (rule->installed) {
-            odp_flow.key = rule->cr.flow;
+            odp_flow_key_from_flow(&odp_flow.key, &rule->cr.flow);
             odp_flow.flags = ODPFF_ZERO_TCP_FLAGS;
             dpif_flow_get(ofproto->dpif, &odp_flow);
 
@@ -3495,9 +3495,12 @@ update_used(struct ofproto *p)
     for (i = 0; i < n_flows; i++) {
         struct odp_flow *f = &flows[i];
         struct rule *rule;
+        flow_t flow;
+
+        odp_flow_key_to_flow(&f->key, &flow);
 
         rule = rule_from_cls_rule(
-            classifier_find_rule_exactly(&p->cls, &f->key, 0, UINT16_MAX));
+            classifier_find_rule_exactly(&p->cls, &flow, 0, UINT16_MAX));
         if (!rule || !rule->installed) {
             COVERAGE_INC(ofproto_unexpected_rule);
             dpif_flow_del(p->dpif, f);
index 563690d..3fb05b6 100644 (file)
@@ -373,7 +373,6 @@ compare_classifiers(struct classifier *cls, struct tcls *tcls)
                ETH_ADDR_LEN);
         flow.nw_proto = nw_proto_values[get_value(&x, N_NW_PROTO_VALUES)];
         flow.nw_tos = nw_tos_values[get_value(&x, N_NW_TOS_VALUES)];
-        memset(flow.reserved, 0, sizeof flow.reserved);
 
         for (include = 1; include <= 3; include++) {
             cr0 = lookup_with_include_bits(cls, &flow, include);