[ovs-dev] [flow_metadata 4/5] flow: Use struct flow_metadata inside struct flow.

Ben Pfaff blp at nicira.com
Fri May 10 23:42:27 UTC 2013


This allows us to delete flow_get_metadata(), since it now just becomes a
struct assignment.

Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 lib/cfm.c               |    4 +-
 lib/dpif-netdev.c       |   10 ++--
 lib/flow.c              |   26 +++-------
 lib/flow.h              |   48 ++++++++-----------
 lib/learning-switch.c   |   11 ++---
 lib/match.c             |  122 +++++++++++++++++++++++------------------------
 lib/meta-flow.c         |   72 ++++++++++++++--------------
 lib/nx-match.c          |   17 +++----
 lib/odp-util.c          |   44 +++++++++--------
 lib/ofp-parse.c         |    6 +--
 lib/ofp-util.c          |   44 ++++++++---------
 ofproto/netflow.c       |    4 +-
 ofproto/ofproto-dpif.c  |  120 +++++++++++++++++++++++-----------------------
 ofproto/tunnel.c        |   32 ++++++-------
 ofproto/tunnel.h        |    2 +-
 tests/test-bundle.c     |    8 ++--
 tests/test-classifier.c |   58 +++++++++++-----------
 tests/test-multipath.c  |    6 +--
 tests/test-odp.c        |    2 +-
 19 files changed, 308 insertions(+), 328 deletions(-)

diff --git a/lib/cfm.c b/lib/cfm.c
index d232b34..cde2090 100644
--- a/lib/cfm.c
+++ b/lib/cfm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -535,7 +535,7 @@ cfm_should_process_flow(const struct cfm *cfm, const struct flow *flow)
 {
     return (ntohs(flow->dl_type) == ETH_TYPE_CFM
             && eth_addr_equals(flow->dl_dst, cfm_ccm_addr(cfm))
-            && (!cfm->check_tnl_key || flow->tunnel.tun_id == htonll(0)));
+            && (!cfm->check_tnl_key || flow->md.tunnel.tun_id == htonll(0)));
 }
 
 /* Updates internal statistics relevant to packet 'p'.  Should be called on
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 78bdedb..8984f7d 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -701,9 +701,9 @@ dpif_netdev_flow_from_nlattrs(const struct nlattr *key, uint32_t key_len,
         return EINVAL;
     }
 
-    if (flow->in_port < OFPP_MAX
-        ? flow->in_port >= MAX_PORTS
-        : flow->in_port != OFPP_LOCAL && flow->in_port != OFPP_NONE) {
+    if (flow->md.in_port < OFPP_MAX
+        ? flow->md.in_port >= MAX_PORTS
+        : flow->md.in_port != OFPP_LOCAL && flow->md.in_port != OFPP_NONE) {
         return EINVAL;
     }
 
@@ -891,7 +891,7 @@ dpif_netdev_flow_dump_next(const struct dpif *dpif, void *state_,
         struct ofpbuf buf;
 
         ofpbuf_use_stack(&buf, &state->keybuf, sizeof state->keybuf);
-        odp_flow_key_from_flow(&buf, &flow->key, flow->key.in_port);
+        odp_flow_key_from_flow(&buf, &flow->key, flow->key.md.in_port);
 
         *key = buf.data;
         *key_len = buf.size;
@@ -1135,7 +1135,7 @@ dp_netdev_output_userspace(struct dp_netdev *dp, const struct ofpbuf *packet,
         ofpbuf_init(buf, buf_size);
 
         /* Put ODP flow. */
-        odp_flow_key_from_flow(buf, flow, flow->in_port);
+        odp_flow_key_from_flow(buf, flow, flow->md.in_port);
         upcall->key = buf->data;
         upcall->key_len = buf->size;
 
diff --git a/lib/flow.c b/lib/flow.c
index ac3c32b..de4d171 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -368,12 +368,12 @@ flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t skb_mark,
     memset(flow, 0, sizeof *flow);
 
     if (tnl) {
-        ovs_assert(tnl != &flow->tunnel);
-        flow->tunnel = *tnl;
+        ovs_assert(tnl != &flow->md.tunnel);
+        flow->md.tunnel = *tnl;
     }
-    flow->in_port = ofp_in_port;
-    flow->skb_priority = skb_priority;
-    flow->skb_mark = skb_mark;
+    flow->md.in_port = ofp_in_port;
+    flow->md.skb_priority = skb_priority;
+    flow->md.skb_mark = skb_mark;
 
     packet->l2   = b.data;
     packet->l2_5 = NULL;
@@ -487,20 +487,6 @@ flow_zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards)
     }
 }
 
-/* Initializes 'fmd' with the metadata found in 'flow'. */
-void
-flow_get_metadata(const struct flow *flow, struct flow_metadata *fmd)
-{
-    BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
-
-    fmd->tunnel = flow->tunnel;
-    fmd->metadata = flow->metadata;
-    memcpy(fmd->regs, flow->regs, sizeof fmd->regs);
-    fmd->in_port = flow->in_port;
-    fmd->skb_priority = flow->skb_priority;
-    fmd->skb_mark = flow->skb_mark;
-}
-
 char *
 flow_to_string(const struct flow *flow)
 {
@@ -680,7 +666,7 @@ flow_equal_except(const struct flow *a, const struct flow *b,
 void
 flow_wildcards_set_reg_mask(struct flow_wildcards *wc, int idx, uint32_t mask)
 {
-    wc->masks.regs[idx] = mask;
+    wc->masks.md.regs[idx] = mask;
 }
 
 /* Hashes 'flow' based on its L2 through L4 protocol information. */
diff --git a/lib/flow.h b/lib/flow.h
index 40f5968..1610871 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -68,29 +68,30 @@ struct flow_tnl {
     uint8_t ip_ttl;
 };
 
-/*
-* A flow in the network.
-*
-* The meaning of 'in_port' is context-dependent.  In most cases, it is a
-* 16-bit OpenFlow 1.0 port number.  In the software datapath interface (dpif)
-* layer and its implementations (e.g. dpif-linux, dpif-netdev), it is instead
-* a 32-bit datapath port number.
-*/
+/* The meaning of 'in_port' is context-dependent.  In most cases, it is a
+ * 16-bit OpenFlow 1.0 port number.  In the software datapath interface (dpif)
+ * layer and its implementations (e.g. dpif-linux, dpif-netdev), it is instead
+ * a 32-bit datapath port number. */
+struct flow_metadata {
+    struct flow_tnl tunnel;          /* Encapsulating tunnel parameters. */
+    ovs_be64 metadata;               /* OpenFlow 1.1+ metadata field. */
+    uint32_t regs[FLOW_N_REGS];      /* Registers. */
+    uint32_t in_port;                /* Input port. OpenFlow port number unless
+                                        in DPIF code, in which case it is the
+                                        datapath port number. */
+    uint32_t skb_priority;           /* Packet priority for QoS. */
+    uint32_t skb_mark;               /* Packet mark. */
+};
+
+/* A flow in the network. */
 struct flow {
-    struct flow_tnl tunnel;     /* Encapsulating tunnel parameters. */
-    ovs_be64 metadata;          /* OpenFlow Metadata. */
+    struct flow_metadata md;
     struct in6_addr ipv6_src;   /* IPv6 source address. */
     struct in6_addr ipv6_dst;   /* IPv6 destination address. */
     struct in6_addr nd_target;  /* IPv6 neighbor discovery (ND) target. */
-    uint32_t skb_priority;      /* Packet priority for QoS. */
-    uint32_t regs[FLOW_N_REGS]; /* Registers. */
     ovs_be32 nw_src;            /* IPv4 source address. */
     ovs_be32 nw_dst;            /* IPv4 destination address. */
     ovs_be32 ipv6_label;        /* IPv6 flow label. */
-    uint32_t in_port;           /* Input port. OpenFlow port number
-                                   unless in DPIF code, in which case it
-                                   is the datapath port number. */
-    uint32_t skb_mark;          /* Packet mark. */
     ovs_be32 mpls_lse;          /* MPLS label stack entry. */
     uint16_t mpls_depth;        /* Depth of MPLS stack. */
     ovs_be16 vlan_tci;          /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */
@@ -105,31 +106,20 @@ struct flow {
     uint8_t arp_tha[6];         /* ARP/ND target hardware address. */
     uint8_t nw_ttl;             /* IP TTL/Hop Limit. */
     uint8_t nw_frag;            /* FLOW_FRAG_* flags. */
-    uint8_t zeros[6];
+    uint8_t zeros[2];
 };
 BUILD_ASSERT_DECL(sizeof(struct flow) % 4 == 0);
 
 #define FLOW_U32S (sizeof(struct flow) / 4)
 
 /* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
-BUILD_ASSERT_DECL(sizeof(struct flow) == sizeof(struct flow_tnl) + 160 &&
+BUILD_ASSERT_DECL(sizeof(struct flow) == sizeof(struct flow_metadata) + 104 &&
                   FLOW_WC_SEQ == 20);
 
-/* Represents the metadata fields of struct flow. */
-struct flow_metadata {
-    struct flow_tnl tunnel;          /* Encapsulating tunnel parameters. */
-    ovs_be64 metadata;               /* OpenFlow 1.1+ metadata field. */
-    uint32_t regs[FLOW_N_REGS];      /* Registers. */
-    uint32_t in_port;                /* OpenFlow port or zero. */
-    uint32_t skb_priority;           /* Packet priority for QoS. */
-    uint32_t skb_mark;               /* Packet mark. */
-};
-
 void flow_extract(struct ofpbuf *, uint32_t priority, uint32_t mark,
                   const struct flow_tnl *, uint16_t in_port, struct flow *);
 
 void flow_zero_wildcards(struct flow *, const struct flow_wildcards *);
-void flow_get_metadata(const struct flow *, struct flow_metadata *);
 
 char *flow_to_string(const struct flow *);
 void format_flags(struct ds *ds, const char *(*bit_to_string)(uint32_t),
diff --git a/lib/learning-switch.c b/lib/learning-switch.c
index 98923fb..ec308fe 100644
--- a/lib/learning-switch.c
+++ b/lib/learning-switch.c
@@ -474,12 +474,12 @@ lswitch_choose_destination(struct lswitch *sw, const struct flow *flow)
     /* Learn the source MAC. */
     if (mac_learning_may_learn(sw->ml, flow->dl_src, 0)) {
         struct mac_entry *mac = mac_learning_insert(sw->ml, flow->dl_src, 0);
-        if (mac_entry_is_new(mac) || mac->port.i != flow->in_port) {
+        if (mac_entry_is_new(mac) || mac->port.i != flow->md.in_port) {
             VLOG_DBG_RL(&rl, "%016llx: learned that "ETH_ADDR_FMT" is on "
                         "port %"PRIu16, sw->datapath_id,
-                        ETH_ADDR_ARGS(flow->dl_src), flow->in_port);
+                        ETH_ADDR_ARGS(flow->dl_src), flow->md.in_port);
 
-            mac->port.i = flow->in_port;
+            mac->port.i = flow->md.in_port;
             mac_learning_changed(sw->ml, mac);
         }
     }
@@ -496,7 +496,7 @@ lswitch_choose_destination(struct lswitch *sw, const struct flow *flow)
         mac = mac_learning_lookup(sw->ml, flow->dl_dst, 0, NULL);
         if (mac) {
             out_port = mac->port.i;
-            if (out_port == flow->in_port) {
+            if (out_port == flow->md.in_port) {
                 /* Don't send a packet back out its input port. */
                 return OFPP_NONE;
             }
@@ -558,8 +558,7 @@ process_packet_in(struct lswitch *sw, const struct ofp_header *oh)
 
     /* Extract flow data from 'opi' into 'flow'. */
     ofpbuf_use_const(&pkt, pi.packet, pi.packet_len);
-    flow_extract(&pkt, 0, 0, NULL, pi.fmd.in_port, &flow);
-    flow.tunnel = pi.fmd.tunnel;
+    flow_extract(&pkt, 0, 0, &pi.fmd.tunnel, pi.fmd.in_port, &flow);
 
     /* Choose output port. */
     out_port = lswitch_choose_destination(sw, &flow);
diff --git a/lib/match.c b/lib/match.c
index 512253e..354ea56 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -56,35 +56,35 @@ match_wc_init(struct match *match, const struct flow *flow)
         memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto);
     }
 
-    if (flow->skb_priority) {
-        memset(&wc->masks.skb_priority, 0xff, sizeof wc->masks.skb_priority);
+    if (flow->md.skb_priority) {
+        wc->masks.md.skb_priority = UINT32_MAX;
     }
 
-    if (flow->skb_mark) {
-        memset(&wc->masks.skb_mark, 0xff, sizeof wc->masks.skb_mark);
+    if (flow->md.skb_mark) {
+        wc->masks.md.skb_mark = UINT32_MAX;
     }
 
     for (i = 0; i < FLOW_N_REGS; i++) {
-        if (flow->regs[i]) {
-            memset(&wc->masks.regs[i], 0xff, sizeof wc->masks.regs[i]);
+        if (flow->md.regs[i]) {
+            wc->masks.md.regs[i] = UINT32_MAX;
         }
     }
 
-    if (flow->tunnel.ip_dst) {
-        if (flow->tunnel.flags & FLOW_TNL_F_KEY) {
-            memset(&wc->masks.tunnel.tun_id, 0xff, sizeof wc->masks.tunnel.tun_id);
+    if (flow->md.tunnel.ip_dst) {
+        if (flow->md.tunnel.flags & FLOW_TNL_F_KEY) {
+            wc->masks.md.tunnel.tun_id = htonll(UINT64_MAX);
         }
-        memset(&wc->masks.tunnel.ip_src, 0xff, sizeof wc->masks.tunnel.ip_src);
-        memset(&wc->masks.tunnel.ip_dst, 0xff, sizeof wc->masks.tunnel.ip_dst);
-        memset(&wc->masks.tunnel.flags, 0xff, sizeof wc->masks.tunnel.flags);
-        memset(&wc->masks.tunnel.ip_tos, 0xff, sizeof wc->masks.tunnel.ip_tos);
-        memset(&wc->masks.tunnel.ip_ttl, 0xff, sizeof wc->masks.tunnel.ip_ttl);
-    } else if (flow->tunnel.tun_id) {
-        memset(&wc->masks.tunnel.tun_id, 0xff, sizeof wc->masks.tunnel.tun_id);
+        wc->masks.md.tunnel.ip_src = htonll(UINT32_MAX);
+        wc->masks.md.tunnel.ip_dst = htonll(UINT32_MAX);
+        wc->masks.md.tunnel.flags = UINT16_MAX;
+        wc->masks.md.tunnel.ip_tos = UINT8_MAX;
+        wc->masks.md.tunnel.ip_ttl = UINT8_MAX;
+    } else if (flow->md.tunnel.tun_id) {
+        wc->masks.md.tunnel.tun_id = htonll(UINT64_MAX);
     }
 
-    memset(&wc->masks.metadata, 0xff, sizeof wc->masks.metadata);
-    memset(&wc->masks.in_port, 0xff, sizeof wc->masks.in_port);
+    wc->masks.md.metadata = htonll(UINT64_MAX);
+    wc->masks.md.in_port = htonl(UINT32_MAX);
     memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci);
     memset(&wc->masks.dl_src, 0xff, sizeof wc->masks.dl_src);
     memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst);
@@ -136,8 +136,8 @@ void
 match_init_exact(struct match *match, const struct flow *flow)
 {
     match->flow = *flow;
-    match->flow.skb_priority = 0;
-    match->flow.skb_mark = 0;
+    match->flow.md.skb_priority = 0;
+    match->flow.md.skb_mark = 0;
     flow_wildcards_init_exact(&match->wc);
 }
 
@@ -175,7 +175,7 @@ match_set_reg_masked(struct match *match, unsigned int reg_idx,
 {
     ovs_assert(reg_idx < FLOW_N_REGS);
     flow_wildcards_set_reg_mask(&match->wc, reg_idx, mask);
-    match->flow.regs[reg_idx] = value & mask;
+    match->flow.md.regs[reg_idx] = value & mask;
 }
 
 void
@@ -188,8 +188,8 @@ void
 match_set_metadata_masked(struct match *match,
                           ovs_be64 metadata, ovs_be64 mask)
 {
-    match->wc.masks.metadata = mask;
-    match->flow.metadata = metadata & mask;
+    match->wc.masks.md.metadata = mask;
+    match->flow.md.metadata = metadata & mask;
 }
 
 void
@@ -201,8 +201,8 @@ match_set_tun_id(struct match *match, ovs_be64 tun_id)
 void
 match_set_tun_id_masked(struct match *match, ovs_be64 tun_id, ovs_be64 mask)
 {
-    match->wc.masks.tunnel.tun_id = mask;
-    match->flow.tunnel.tun_id = tun_id & mask;
+    match->wc.masks.md.tunnel.tun_id = mask;
+    match->flow.md.tunnel.tun_id = tun_id & mask;
 }
 
 void
@@ -214,8 +214,8 @@ match_set_tun_src(struct match *match, ovs_be32 src)
 void
 match_set_tun_src_masked(struct match *match, ovs_be32 src, ovs_be32 mask)
 {
-    match->wc.masks.tunnel.ip_src = mask;
-    match->flow.tunnel.ip_src = src & mask;
+    match->wc.masks.md.tunnel.ip_src = mask;
+    match->flow.md.tunnel.ip_src = src & mask;
 }
 
 void
@@ -227,8 +227,8 @@ match_set_tun_dst(struct match *match, ovs_be32 dst)
 void
 match_set_tun_dst_masked(struct match *match, ovs_be32 dst, ovs_be32 mask)
 {
-    match->wc.masks.tunnel.ip_dst = mask;
-    match->flow.tunnel.ip_dst = dst & mask;
+    match->wc.masks.md.tunnel.ip_dst = mask;
+    match->flow.md.tunnel.ip_dst = dst & mask;
 }
 
 void
@@ -240,8 +240,8 @@ match_set_tun_ttl(struct match *match, uint8_t ttl)
 void
 match_set_tun_ttl_masked(struct match *match, uint8_t ttl, uint8_t mask)
 {
-    match->wc.masks.tunnel.ip_ttl = mask;
-    match->flow.tunnel.ip_ttl = ttl & mask;
+    match->wc.masks.md.tunnel.ip_ttl = mask;
+    match->flow.md.tunnel.ip_ttl = ttl & mask;
 }
 
 void
@@ -253,8 +253,8 @@ match_set_tun_tos(struct match *match, uint8_t tos)
 void
 match_set_tun_tos_masked(struct match *match, uint8_t tos, uint8_t mask)
 {
-    match->wc.masks.tunnel.ip_tos = mask;
-    match->flow.tunnel.ip_tos = tos & mask;
+    match->wc.masks.md.tunnel.ip_tos = mask;
+    match->flow.md.tunnel.ip_tos = tos & mask;
 }
 
 void
@@ -266,29 +266,29 @@ match_set_tun_flags(struct match *match, uint16_t flags)
 void
 match_set_tun_flags_masked(struct match *match, uint16_t flags, uint16_t mask)
 {
-    match->wc.masks.tunnel.flags = mask;
-    match->flow.tunnel.flags = flags & mask;
+    match->wc.masks.md.tunnel.flags = mask;
+    match->flow.md.tunnel.flags = flags & mask;
 }
 
 void
 match_set_in_port(struct match *match, uint16_t ofp_port)
 {
-    match->wc.masks.in_port = UINT16_MAX;
-    match->flow.in_port = ofp_port;
+    match->wc.masks.md.in_port = UINT16_MAX;
+    match->flow.md.in_port = ofp_port;
 }
 
 void
 match_set_skb_priority(struct match *match, uint32_t skb_priority)
 {
-    match->wc.masks.skb_priority = UINT32_MAX;
-    match->flow.skb_priority = skb_priority;
+    match->wc.masks.md.skb_priority = UINT32_MAX;
+    match->flow.md.skb_priority = skb_priority;
 }
 
 void
 match_set_skb_mark(struct match *match, uint32_t skb_mark)
 {
-    match->wc.masks.skb_mark = UINT32_MAX;
-    match->flow.skb_mark = skb_mark;
+    match->wc.masks.md.skb_mark = UINT32_MAX;
+    match->flow.md.skb_mark = skb_mark;
 }
 
 void
@@ -787,9 +787,9 @@ static void
 format_flow_tunnel(struct ds *s, const struct match *match)
 {
     const struct flow_wildcards *wc = &match->wc;
-    const struct flow_tnl *tnl = &match->flow.tunnel;
+    const struct flow_tnl *tnl = &match->flow.md.tunnel;
 
-    switch (wc->masks.tunnel.tun_id) {
+    switch (wc->masks.md.tunnel.tun_id) {
     case 0:
         break;
     case CONSTANT_HTONLL(UINT64_MAX):
@@ -798,19 +798,19 @@ format_flow_tunnel(struct ds *s, const struct match *match)
     default:
         ds_put_format(s, "tun_id=%#"PRIx64"/%#"PRIx64",",
                       ntohll(tnl->tun_id),
-                      ntohll(wc->masks.tunnel.tun_id));
+                      ntohll(wc->masks.md.tunnel.tun_id));
         break;
     }
-    format_ip_netmask(s, "tun_src", tnl->ip_src, wc->masks.tunnel.ip_src);
-    format_ip_netmask(s, "tun_dst", tnl->ip_dst, wc->masks.tunnel.ip_dst);
+    format_ip_netmask(s, "tun_src", tnl->ip_src, wc->masks.md.tunnel.ip_src);
+    format_ip_netmask(s, "tun_dst", tnl->ip_dst, wc->masks.md.tunnel.ip_dst);
 
-    if (wc->masks.tunnel.ip_tos) {
+    if (wc->masks.md.tunnel.ip_tos) {
         ds_put_format(s, "tun_tos=%"PRIx8",", tnl->ip_tos);
     }
-    if (wc->masks.tunnel.ip_ttl) {
+    if (wc->masks.md.tunnel.ip_ttl) {
         ds_put_format(s, "tun_ttl=%"PRIu8",", tnl->ip_ttl);
     }
-    if (wc->masks.tunnel.flags) {
+    if (wc->masks.md.tunnel.flags) {
         format_flags(s, flow_tun_flag_to_string, tnl->flags, '|');
         ds_put_char(s, ',');
     }
@@ -835,12 +835,12 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
         ds_put_format(s, "priority=%u,", priority);
     }
 
-    if (wc->masks.skb_mark) {
-        ds_put_format(s, "skb_mark=%#"PRIx32",", f->skb_mark);
+    if (wc->masks.md.skb_mark) {
+        ds_put_format(s, "skb_mark=%#"PRIx32",", f->md.skb_mark);
     }
 
-    if (wc->masks.skb_priority) {
-        ds_put_format(s, "skb_priority=%#"PRIx32",", f->skb_priority);
+    if (wc->masks.md.skb_priority) {
+        ds_put_format(s, "skb_priority=%#"PRIx32",", f->md.skb_priority);
     }
 
     if (wc->masks.dl_type) {
@@ -890,35 +890,35 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
         }
     }
     for (i = 0; i < FLOW_N_REGS; i++) {
-        switch (wc->masks.regs[i]) {
+        switch (wc->masks.md.regs[i]) {
         case 0:
             break;
         case UINT32_MAX:
-            ds_put_format(s, "reg%d=0x%"PRIx32",", i, f->regs[i]);
+            ds_put_format(s, "reg%d=0x%"PRIx32",", i, f->md.regs[i]);
             break;
         default:
             ds_put_format(s, "reg%d=0x%"PRIx32"/0x%"PRIx32",",
-                          i, f->regs[i], wc->masks.regs[i]);
+                          i, f->md.regs[i], wc->masks.md.regs[i]);
             break;
         }
     }
 
     format_flow_tunnel(s, match);
 
-    switch (wc->masks.metadata) {
+    switch (wc->masks.md.metadata) {
     case 0:
         break;
     case CONSTANT_HTONLL(UINT64_MAX):
-        ds_put_format(s, "metadata=%#"PRIx64",", ntohll(f->metadata));
+        ds_put_format(s, "metadata=%#"PRIx64",", ntohll(f->md.metadata));
         break;
     default:
         ds_put_format(s, "metadata=%#"PRIx64"/%#"PRIx64",",
-                      ntohll(f->metadata), ntohll(wc->masks.metadata));
+                      ntohll(f->md.metadata), ntohll(wc->masks.md.metadata));
         break;
     }
-    if (wc->masks.in_port) {
+    if (wc->masks.md.in_port) {
         ds_put_cstr(s, "in_port=");
-        ofputil_format_port(f->in_port, s);
+        ofputil_format_port(f->md.in_port, s);
         ds_put_char(s, ',');
     }
     if (wc->masks.vlan_tci) {
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index 16850ec..27bafae 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -677,24 +677,24 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
 {
     switch (mf->id) {
     case MFF_TUN_SRC:
-        return !wc->masks.tunnel.ip_src;
+        return !wc->masks.md.tunnel.ip_src;
     case MFF_TUN_DST:
-        return !wc->masks.tunnel.ip_dst;
+        return !wc->masks.md.tunnel.ip_dst;
     case MFF_TUN_ID:
     case MFF_TUN_TOS:
     case MFF_TUN_TTL:
     case MFF_TUN_FLAGS:
-        return !wc->masks.tunnel.tun_id;
+        return !wc->masks.md.tunnel.tun_id;
     case MFF_METADATA:
-        return !wc->masks.metadata;
+        return !wc->masks.md.metadata;
     case MFF_IN_PORT:
-        return !wc->masks.in_port;
+        return !wc->masks.md.in_port;
     case MFF_SKB_PRIORITY:
-        return !wc->masks.skb_priority;
+        return !wc->masks.md.skb_priority;
     case MFF_SKB_MARK:
-        return !wc->masks.skb_mark;
+        return !wc->masks.md.skb_mark;
     CASE_MFF_REGS:
-        return !wc->masks.regs[mf->id - MFF_REG0];
+        return !wc->masks.md.regs[mf->id - MFF_REG0];
 
     case MFF_ETH_SRC:
         return eth_addr_is_zero(wc->masks.dl_src);
@@ -973,42 +973,42 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
 {
     switch (mf->id) {
     case MFF_TUN_ID:
-        value->be64 = flow->tunnel.tun_id;
+        value->be64 = flow->md.tunnel.tun_id;
         break;
     case MFF_TUN_SRC:
-        value->be32 = flow->tunnel.ip_src;
+        value->be32 = flow->md.tunnel.ip_src;
         break;
     case MFF_TUN_DST:
-        value->be32 = flow->tunnel.ip_dst;
+        value->be32 = flow->md.tunnel.ip_dst;
         break;
     case MFF_TUN_FLAGS:
-        value->be16 = htons(flow->tunnel.flags);
+        value->be16 = htons(flow->md.tunnel.flags);
         break;
     case MFF_TUN_TTL:
-        value->u8 = flow->tunnel.ip_ttl;
+        value->u8 = flow->md.tunnel.ip_ttl;
         break;
     case MFF_TUN_TOS:
-        value->u8 = flow->tunnel.ip_tos;
+        value->u8 = flow->md.tunnel.ip_tos;
         break;
 
     case MFF_METADATA:
-        value->be64 = flow->metadata;
+        value->be64 = flow->md.metadata;
         break;
 
     case MFF_IN_PORT:
-        value->be16 = htons(flow->in_port);
+        value->be16 = htons(flow->md.in_port);
         break;
 
     case MFF_SKB_PRIORITY:
-        value->be32 = htonl(flow->skb_priority);
+        value->be32 = htonl(flow->md.skb_priority);
         break;
 
     case MFF_SKB_MARK:
-        value->be32 = htonl(flow->skb_mark);
+        value->be32 = htonl(flow->md.skb_mark);
         break;
 
     CASE_MFF_REGS:
-        value->be32 = htonl(flow->regs[mf->id - MFF_REG0]);
+        value->be32 = htonl(flow->md.regs[mf->id - MFF_REG0]);
         break;
 
     case MFF_ETH_SRC:
@@ -1339,42 +1339,42 @@ mf_set_flow_value(const struct mf_field *mf,
 {
     switch (mf->id) {
     case MFF_TUN_ID:
-        flow->tunnel.tun_id = value->be64;
+        flow->md.tunnel.tun_id = value->be64;
         break;
     case MFF_TUN_SRC:
-        flow->tunnel.ip_src = value->be32;
+        flow->md.tunnel.ip_src = value->be32;
         break;
     case MFF_TUN_DST:
-        flow->tunnel.ip_dst = value->be32;
+        flow->md.tunnel.ip_dst = value->be32;
         break;
     case MFF_TUN_FLAGS:
-        flow->tunnel.flags = ntohs(value->be16);
+        flow->md.tunnel.flags = ntohs(value->be16);
         break;
     case MFF_TUN_TOS:
-        flow->tunnel.ip_tos = value->u8;
+        flow->md.tunnel.ip_tos = value->u8;
         break;
     case MFF_TUN_TTL:
-        flow->tunnel.ip_ttl = value->u8;
+        flow->md.tunnel.ip_ttl = value->u8;
         break;
 
     case MFF_METADATA:
-        flow->metadata = value->be64;
+        flow->md.metadata = value->be64;
         break;
 
     case MFF_IN_PORT:
-        flow->in_port = ntohs(value->be16);
+        flow->md.in_port = ntohs(value->be16);
         break;
 
     case MFF_SKB_PRIORITY:
-        flow->skb_priority = ntohl(value->be32);
+        flow->md.skb_priority = ntohl(value->be32);
         break;
 
     case MFF_SKB_MARK:
-        flow->skb_mark = ntohl(value->be32);
+        flow->md.skb_mark = ntohl(value->be32);
         break;
 
     CASE_MFF_REGS:
-        flow->regs[mf->id - MFF_REG0] = ntohl(value->be32);
+        flow->md.regs[mf->id - MFF_REG0] = ntohl(value->be32);
         break;
 
     case MFF_ETH_SRC:
@@ -1561,18 +1561,18 @@ mf_set_wild(const struct mf_field *mf, struct match *match)
         break;
 
     case MFF_IN_PORT:
-        match->flow.in_port = 0;
-        match->wc.masks.in_port = 0;
+        match->flow.md.in_port = 0;
+        match->wc.masks.md.in_port = 0;
         break;
 
     case MFF_SKB_PRIORITY:
-        match->flow.skb_priority = 0;
-        match->wc.masks.skb_priority = 0;
+        match->flow.md.skb_priority = 0;
+        match->wc.masks.md.skb_priority = 0;
         break;
 
     case MFF_SKB_MARK:
-        match->flow.skb_mark = 0;
-        match->wc.masks.skb_mark = 0;
+        match->flow.md.skb_mark = 0;
+        match->wc.masks.md.skb_mark = 0;
         break;
 
     CASE_MFF_REGS:
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 51b6dc6..4e9c996 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -579,8 +579,8 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match *match,
     BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
 
     /* Metadata. */
-    if (match->wc.masks.in_port) {
-        uint16_t in_port = flow->in_port;
+    if (match->wc.masks.md.in_port) {
+        uint32_t in_port = flow->md.in_port;
         if (oxm) {
             nxm_put_32(b, OXM_OF_IN_PORT, ofputil_port_to_ofp11(in_port));
         } else {
@@ -690,22 +690,23 @@ nx_put_raw(struct ofpbuf *b, bool oxm, const struct match *match,
 
     /* Tunnel ID. */
     nxm_put_64m(b, oxm ? OXM_OF_TUNNEL_ID : NXM_NX_TUN_ID,
-                flow->tunnel.tun_id, match->wc.masks.tunnel.tun_id);
+                flow->md.tunnel.tun_id, match->wc.masks.md.tunnel.tun_id);
 
     /* Other tunnel metadata. */
     nxm_put_32m(b, NXM_NX_TUN_IPV4_SRC,
-                flow->tunnel.ip_src, match->wc.masks.tunnel.ip_src);
+                flow->md.tunnel.ip_src, match->wc.masks.md.tunnel.ip_src);
     nxm_put_32m(b, NXM_NX_TUN_IPV4_DST,
-                flow->tunnel.ip_dst, match->wc.masks.tunnel.ip_dst);
+                flow->md.tunnel.ip_dst, match->wc.masks.md.tunnel.ip_dst);
 
     /* Registers. */
     for (i = 0; i < FLOW_N_REGS; i++) {
-        nxm_put_32m(b, NXM_NX_REG(i),
-                    htonl(flow->regs[i]), htonl(match->wc.masks.regs[i]));
+        nxm_put_32m(b, NXM_NX_REG(i), htonl(flow->md.regs[i]),
+                    htonl(match->wc.masks.md.regs[i]));
     }
 
     /* OpenFlow 1.1+ Metadata. */
-    nxm_put_64m(b, OXM_OF_METADATA, flow->metadata, match->wc.masks.metadata);
+    nxm_put_64m(b, OXM_OF_METADATA,
+                flow->md.metadata, match->wc.masks.md.metadata);
 
     /* Cookie. */
     nxm_put_64m(b, NXM_NX_COOKIE, cookie, cookie_mask);
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 5bf94fe..04a54cb 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -1552,16 +1552,16 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow,
     struct ovs_key_ethernet *eth_key;
     size_t encap;
 
-    if (flow->skb_priority) {
-        nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, flow->skb_priority);
+    if (flow->md.skb_priority) {
+        nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, flow->md.skb_priority);
     }
 
-    if (flow->tunnel.ip_dst) {
-        tun_key_to_attr(buf, &flow->tunnel);
+    if (flow->md.tunnel.ip_dst) {
+        tun_key_to_attr(buf, &flow->md.tunnel);
     }
 
-    if (flow->skb_mark) {
-        nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, flow->skb_mark);
+    if (flow->md.skb_mark) {
+        nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, flow->md.skb_mark);
     }
 
     if (odp_in_port != OVSP_NONE) {
@@ -2066,19 +2066,19 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
 
     /* Metadata. */
     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_PRIORITY)) {
-        flow->skb_priority = nl_attr_get_u32(attrs[OVS_KEY_ATTR_PRIORITY]);
+        flow->md.skb_priority = nl_attr_get_u32(attrs[OVS_KEY_ATTR_PRIORITY]);
         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_PRIORITY;
     }
 
     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_SKB_MARK)) {
-        flow->skb_mark = nl_attr_get_u32(attrs[OVS_KEY_ATTR_SKB_MARK]);
+        flow->md.skb_mark = nl_attr_get_u32(attrs[OVS_KEY_ATTR_SKB_MARK]);
         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_SKB_MARK;
     }
 
     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_TUNNEL)) {
         enum odp_key_fitness res;
 
-        res = tun_key_from_attr(attrs[OVS_KEY_ATTR_TUNNEL], &flow->tunnel);
+        res = tun_key_from_attr(attrs[OVS_KEY_ATTR_TUNNEL], &flow->md.tunnel);
         if (res == ODP_FIT_ERROR) {
             return ODP_FIT_ERROR;
         } else if (res == ODP_FIT_PERFECT) {
@@ -2087,10 +2087,10 @@ odp_flow_key_to_flow(const struct nlattr *key, size_t key_len,
     }
 
     if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_IN_PORT)) {
-        flow->in_port = nl_attr_get_u32(attrs[OVS_KEY_ATTR_IN_PORT]);
+        flow->md.in_port = nl_attr_get_u32(attrs[OVS_KEY_ATTR_IN_PORT]);
         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IN_PORT;
     } else {
-        flow->in_port = OVSP_NONE;
+        flow->md.in_port = OVSP_NONE;
     }
 
     /* Ethernet header. */
@@ -2200,12 +2200,13 @@ commit_odp_tunnel_action(const struct flow *flow, struct flow *base,
                          struct ofpbuf *odp_actions)
 {
     /* A valid IPV4_TUNNEL must have non-zero ip_dst. */
-    if (flow->tunnel.ip_dst) {
-        if (!memcmp(&base->tunnel, &flow->tunnel, sizeof base->tunnel)) {
+    if (flow->md.tunnel.ip_dst) {
+        if (!memcmp(&base->md.tunnel, &flow->md.tunnel,
+                    sizeof base->md.tunnel)) {
             return;
         }
-        memcpy(&base->tunnel, &flow->tunnel, sizeof base->tunnel);
-        odp_put_tunnel_action(&base->tunnel, odp_actions);
+        base->md.tunnel = flow->md.tunnel;
+        odp_put_tunnel_action(&base->md.tunnel, odp_actions);
     }
 }
 
@@ -2405,26 +2406,27 @@ static void
 commit_set_priority_action(const struct flow *flow, struct flow *base,
                            struct ofpbuf *odp_actions)
 {
-    if (base->skb_priority == flow->skb_priority) {
+    if (base->md.skb_priority == flow->md.skb_priority) {
         return;
     }
-    base->skb_priority = flow->skb_priority;
+    base->md.skb_priority = flow->md.skb_priority;
 
     commit_set_action(odp_actions, OVS_KEY_ATTR_PRIORITY,
-                      &base->skb_priority, sizeof(base->skb_priority));
+                      &base->md.skb_priority, sizeof(base->md.skb_priority));
 }
 
 static void
 commit_set_skb_mark_action(const struct flow *flow, struct flow *base,
                            struct ofpbuf *odp_actions)
 {
-    if (base->skb_mark == flow->skb_mark) {
+    if (base->md.skb_mark == flow->md.skb_mark) {
         return;
     }
-    base->skb_mark = flow->skb_mark;
+    base->md.skb_mark = flow->md.skb_mark;
 
-    odp_put_skb_mark_action(base->skb_mark, odp_actions);
+    odp_put_skb_mark_action(base->md.skb_mark, odp_actions);
 }
+
 /* If any of the flow key data that ODP actions can modify are different in
  * 'base' and 'flow', appends ODP actions to 'odp_actions' that change the flow
  * key from 'base' into 'flow', and then changes 'base' the same way.  Does not
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 1c5c761..acefbbc 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -1229,8 +1229,8 @@ parse_ofp_exact_flow(struct flow *flow, const char *s)
         }
     }
 
-    if (!flow->in_port) {
-        flow->in_port = OFPP_NONE;
+    if (!flow->md.in_port) {
+        flow->md.in_port = OFPP_NONE;
     }
 
 exit:
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index da9af72..d5867bd 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -90,7 +90,7 @@ ofputil_wildcard_from_ofpfw10(uint32_t ofpfw, struct flow_wildcards *wc)
     flow_wildcards_init_catchall(wc);
 
     if (!(ofpfw & OFPFW10_IN_PORT)) {
-        wc->masks.in_port = UINT16_MAX;
+        wc->masks.md.in_port = UINT16_MAX;
     }
 
     if (!(ofpfw & OFPFW10_NW_TOS)) {
@@ -145,7 +145,7 @@ ofputil_match_from_ofp10_match(const struct ofp10_match *ofmatch,
     /* Initialize most of match->flow. */
     match->flow.nw_src = ofmatch->nw_src;
     match->flow.nw_dst = ofmatch->nw_dst;
-    match->flow.in_port = ntohs(ofmatch->in_port);
+    match->flow.md.in_port = ntohs(ofmatch->in_port);
     match->flow.dl_type = ofputil_dl_type_from_openflow(ofmatch->dl_type);
     match->flow.tp_src = ofmatch->tp_src;
     match->flow.tp_dst = ofmatch->tp_dst;
@@ -190,7 +190,7 @@ ofputil_match_to_ofp10_match(const struct match *match,
 
     /* Figure out most OpenFlow wildcards. */
     ofpfw = 0;
-    if (!wc->masks.in_port) {
+    if (!wc->masks.md.in_port) {
         ofpfw |= OFPFW10_IN_PORT;
     }
     if (!wc->masks.dl_type) {
@@ -244,7 +244,7 @@ ofputil_match_to_ofp10_match(const struct match *match,
 
     /* Compose most of the match structure. */
     ofmatch->wildcards = htonl(ofpfw);
-    ofmatch->in_port = htons(match->flow.in_port);
+    ofmatch->in_port = htons(match->flow.md.in_port);
     memcpy(ofmatch->dl_src, match->flow.dl_src, ETH_ADDR_LEN);
     memcpy(ofmatch->dl_dst, match->flow.dl_dst, ETH_ADDR_LEN);
     ofmatch->dl_type = ofputil_dl_type_to_openflow(match->flow.dl_type);
@@ -466,10 +466,10 @@ ofputil_match_to_ofp11_match(const struct match *match,
     ofmatch->omh.type = htons(OFPMT_STANDARD);
     ofmatch->omh.length = htons(OFPMT11_STANDARD_LENGTH);
 
-    if (!match->wc.masks.in_port) {
+    if (!match->wc.masks.md.in_port) {
         wc |= OFPFW11_IN_PORT;
     } else {
-        ofmatch->in_port = ofputil_port_to_ofp11(match->flow.in_port);
+        ofmatch->in_port = ofputil_port_to_ofp11(match->flow.md.in_port);
     }
 
     memcpy(ofmatch->dl_src, match->flow.dl_src, ETH_ADDR_LEN);
@@ -541,8 +541,8 @@ ofputil_match_to_ofp11_match(const struct match *match,
     wc |= OFPFW11_MPLS_LABEL;
     wc |= OFPFW11_MPLS_TC;
 
-    ofmatch->metadata = match->flow.metadata;
-    ofmatch->metadata_mask = ~match->wc.masks.metadata;
+    ofmatch->metadata = match->flow.md.metadata;
+    ofmatch->metadata_mask = ~match->wc.masks.md.metadata;
 
     ofmatch->wildcards = htonl(wc);
 }
@@ -1032,7 +1032,7 @@ regs_fully_wildcarded(const struct flow_wildcards *wc)
     int i;
 
     for (i = 0; i < FLOW_N_REGS; i++) {
-        if (wc->masks.regs[i] != 0) {
+        if (wc->masks.md.regs[i] != 0) {
             return false;
         }
     }
@@ -1051,13 +1051,13 @@ ofputil_usable_protocols(const struct match *match)
     BUILD_ASSERT_DECL(FLOW_WC_SEQ == 20);
 
     /* These tunnel params can't be sent in a flow_mod */
-    if (wc->masks.tunnel.ip_ttl
-        || wc->masks.tunnel.ip_tos || wc->masks.tunnel.flags) {
+    if (wc->masks.md.tunnel.ip_ttl
+        || wc->masks.md.tunnel.ip_tos || wc->masks.md.tunnel.flags) {
         return OFPUTIL_P_NONE;
     }
 
     /* skb_mark and skb_priority can't be sent in a flow_mod */
-    if (wc->masks.skb_mark || wc->masks.skb_priority) {
+    if (wc->masks.md.skb_mark || wc->masks.md.skb_priority) {
         return OFPUTIL_P_NONE;
     }
 
@@ -1074,7 +1074,7 @@ ofputil_usable_protocols(const struct match *match)
     }
 
     /* NXM, OXM, and OF1.1+ support matching metadata. */
-    if (wc->masks.metadata != htonll(0)) {
+    if (wc->masks.md.metadata != htonll(0)) {
         return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
             | OFPUTIL_P_OF13_OXM;
     }
@@ -1099,9 +1099,9 @@ ofputil_usable_protocols(const struct match *match)
     }
 
     /* NXM and OXM support matching tun_id, tun_src, and tun_dst. */
-    if (wc->masks.tunnel.tun_id != htonll(0)
-        || wc->masks.tunnel.ip_src != htonl(0)
-        || wc->masks.tunnel.ip_dst != htonl(0)) {
+    if (wc->masks.md.tunnel.tun_id != htonll(0)
+        || wc->masks.md.tunnel.ip_src != htonl(0)
+        || wc->masks.md.tunnel.ip_dst != htonl(0)) {
         return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
             | OFPUTIL_P_OF13_OXM;
     }
@@ -2441,12 +2441,12 @@ ofputil_decode_packet_in_finish(struct ofputil_packet_in *pin,
     pin->packet = b->data;
     pin->packet_len = b->size;
 
-    pin->fmd.in_port = match->flow.in_port;
-    pin->fmd.tunnel = match->flow.tunnel;
-    pin->fmd.metadata = match->flow.metadata;
-    memcpy(pin->fmd.regs, match->flow.regs, sizeof pin->fmd.regs);
-    pin->fmd.skb_priority = match->flow.skb_priority;
-    pin->fmd.skb_mark = match->flow.skb_mark;
+    pin->fmd.in_port = match->flow.md.in_port;
+    pin->fmd.tunnel = match->flow.md.tunnel;
+    pin->fmd.metadata = match->flow.md.metadata;
+    memcpy(pin->fmd.regs, match->flow.md.regs, sizeof pin->fmd.regs);
+    pin->fmd.skb_priority = match->flow.md.skb_priority;
+    pin->fmd.skb_mark = match->flow.md.skb_mark;
 }
 
 enum ofperr
diff --git a/ofproto/netflow.c b/ofproto/netflow.c
index aec3968..25194cc 100644
--- a/ofproto/netflow.c
+++ b/ofproto/netflow.c
@@ -85,10 +85,10 @@ gen_netflow_rec(struct netflow *nf, struct netflow_flow *nf_flow,
     nf_rec->nexthop = htonl(0);
     if (nf->add_id_to_iface) {
         uint16_t iface = (nf->engine_id & 0x7f) << 9;
-        nf_rec->input = htons(iface | (expired->flow.in_port & 0x1ff));
+        nf_rec->input = htons(iface | (expired->flow.md.in_port & 0x1ff));
         nf_rec->output = htons(iface | (nf_flow->output_iface & 0x1ff));
     } else {
-        nf_rec->input = htons(expired->flow.in_port);
+        nf_rec->input = htons(expired->flow.md.in_port);
         nf_rec->output = htons(nf_flow->output_iface);
     }
     nf_rec->packet_count = htonl(packet_count);
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 1da8ffb..5c37509 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -3533,7 +3533,7 @@ send_packet_in_miss(struct ofproto_dpif *ofproto, const struct ofpbuf *packet,
 
     pin.send_len = 0;           /* not used for flow table misses */
 
-    flow_get_metadata(flow, &pin.fmd);
+    pin.fmd = flow->md;
 
     connmgr_send_packet_in(ofproto->up.connmgr, &pin);
 }
@@ -3911,13 +3911,13 @@ ofproto_receive(const struct dpif_backer *backer, struct ofpbuf *packet,
     }
 
     if (odp_in_port) {
-        *odp_in_port = flow->in_port;
+        *odp_in_port = flow->md.in_port;
     }
 
     port = (tnl_port_should_receive(flow)
             ? ofport_dpif_cast(tnl_port_receive(flow))
-            : odp_port_to_ofport(backer, flow->in_port));
-    flow->in_port = port ? port->up.ofp_port : OFPP_NONE;
+            : odp_port_to_ofport(backer, flow->md.in_port));
+    flow->md.in_port = port ? port->up.ofp_port : OFPP_NONE;
     if (!port) {
         goto exit;
     }
@@ -4010,7 +4010,7 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls,
              * that future packets of the flow are inexpensively dropped
              * in the kernel. */
             VLOG_INFO_RL(&rl, "received packet on unassociated port %"PRIu32,
-                         flow.in_port);
+                         flow.md.in_port);
 
             drop_key = drop_key_lookup(backer, upcall->key, upcall->key_len);
             if (!drop_key) {
@@ -4030,8 +4030,8 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls,
         }
 
         ofproto->n_missed++;
-        flow_extract(upcall->packet, flow.skb_priority, flow.skb_mark,
-                     &flow.tunnel, flow.in_port, &miss->flow);
+        flow_extract(upcall->packet, flow.md.skb_priority, flow.md.skb_mark,
+                     &flow.md.tunnel, flow.md.in_port, &miss->flow);
 
         /* Add other packets to a to-do list. */
         hash = flow_hash(&miss->flow, 0);
@@ -4413,7 +4413,7 @@ update_stats(struct dpif_backer *backer)
         ofproto->total_subfacet_count += hmap_count(&ofproto->subfacets);
         ofproto->n_update_stats++;
 
-        ofport = get_ofp_port(ofproto, flow.in_port);
+        ofport = get_ofp_port(ofproto, flow.md.in_port);
         if (ofport && ofport->tnl_port) {
             netdev_vport_inc_rx(ofport->up.netdev, stats);
         }
@@ -4668,7 +4668,7 @@ execute_odp_actions(struct ofproto_dpif *ofproto, const struct flow *flow,
 
     ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
     odp_flow_key_from_flow(&key, flow,
-                           ofp_port_to_odp_port(ofproto, flow->in_port));
+                           ofp_port_to_odp_port(ofproto, flow->md.in_port));
 
     error = dpif_execute(ofproto->backer->dpif, key.data, key.size,
                          odp_actions, actions_len, packet);
@@ -5636,9 +5636,10 @@ rule_dpif_miss_rule(struct ofproto_dpif *ofproto, const struct flow *flow)
 {
     struct ofport_dpif *port;
 
-    port = get_ofp_port(ofproto, flow->in_port);
+    port = get_ofp_port(ofproto, flow->md.in_port);
     if (!port) {
-        VLOG_WARN_RL(&rl, "packet-in on unknown port %"PRIu16, flow->in_port);
+        VLOG_WARN_RL(&rl, "packet-in on unknown port %"PRIu16,
+                     flow->md.in_port);
         return ofproto->miss_rule;
     }
 
@@ -5902,7 +5903,7 @@ put_userspace_action(const struct ofproto_dpif *ofproto,
     uint32_t pid;
 
     pid = dpif_port_get_pid(ofproto->backer->dpif,
-                            ofp_port_to_odp_port(ofproto, flow->in_port));
+                            ofp_port_to_odp_port(ofproto, flow->md.in_port));
 
     return odp_put_userspace_action(pid, cookie, cookie_size, odp_actions);
 }
@@ -5977,7 +5978,7 @@ compose_sflow_action(const struct ofproto_dpif *ofproto,
     uint32_t probability;
     union user_action_cookie cookie;
 
-    if (!ofproto->sflow || flow->in_port == OFPP_NONE) {
+    if (!ofproto->sflow || flow->md.in_port == OFPP_NONE) {
         return 0;
     }
 
@@ -6016,7 +6017,7 @@ compose_ipfix_action(const struct ofproto_dpif *ofproto,
     uint32_t probability;
     union user_action_cookie cookie;
 
-    if (!ofproto->ipfix || flow->in_port == OFPP_NONE) {
+    if (!ofproto->ipfix || flow->md.in_port == OFPP_NONE) {
         return;
     }
 
@@ -6114,25 +6115,25 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
         }
 
         ctx->ofproto = ofproto_dpif_cast(peer->up.ofproto);
-        ctx->flow.in_port = peer->up.ofp_port;
-        ctx->flow.metadata = htonll(0);
-        memset(&ctx->flow.tunnel, 0, sizeof ctx->flow.tunnel);
-        memset(ctx->flow.regs, 0, sizeof ctx->flow.regs);
+        ctx->flow.md.in_port = peer->up.ofp_port;
+        ctx->flow.md.metadata = htonll(0);
+        memset(&ctx->flow.md.tunnel, 0, sizeof ctx->flow.md.tunnel);
+        memset(ctx->flow.md.regs, 0, sizeof ctx->flow.md.regs);
 
-        in_port = get_ofp_port(ctx->ofproto, ctx->flow.in_port);
+        in_port = get_ofp_port(ctx->ofproto, ctx->flow.md.in_port);
         special = process_special(ctx->ofproto, &ctx->flow, in_port,
                                   ctx->packet);
         if (special) {
             ctx->slow |= special;
         } else if (!in_port || may_receive(in_port, ctx)) {
             if (!in_port || stp_forward_in_state(in_port->stp_state)) {
-                xlate_table_action(ctx, ctx->flow.in_port, 0, true);
+                xlate_table_action(ctx, ctx->flow.md.in_port, 0, true);
             } else {
                 /* Forwarding is disabled by STP.  Let OFPP_NORMAL and the
                  * learning action look at the packet, then drop it. */
                 struct flow old_base_flow = ctx->base_flow;
                 size_t old_size = ctx->odp_actions->size;
-                xlate_table_action(ctx, ctx->flow.in_port, 0, true);
+                xlate_table_action(ctx, ctx->flow.md.in_port, 0, true);
                 ctx->base_flow = old_base_flow;
                 ctx->odp_actions->size = old_size;
             }
@@ -6150,10 +6151,10 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
     }
 
     flow_vlan_tci = ctx->flow.vlan_tci;
-    flow_skb_mark = ctx->flow.skb_mark;
+    flow_skb_mark = ctx->flow.md.skb_mark;
     flow_nw_tos = ctx->flow.nw_tos;
 
-    pdscp = get_priority(ofport, ctx->flow.skb_priority);
+    pdscp = get_priority(ofport, ctx->flow.md.skb_priority);
     if (pdscp) {
         ctx->flow.nw_tos &= ~IP_DSCP_MASK;
         ctx->flow.nw_tos |= pdscp->dscp;
@@ -6164,13 +6165,13 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
           * the Logical (tunnel) Port are not visible for any further
           * matches, while explicit set actions on tunnel metadata are.
           */
-        struct flow_tnl flow_tnl = ctx->flow.tunnel;
+        struct flow_tnl flow_tnl = ctx->flow.md.tunnel;
         odp_port = tnl_port_send(ofport->tnl_port, &ctx->flow);
         if (odp_port == OVSP_NONE) {
             xlate_report(ctx, "Tunneling decided against output");
             goto out; /* restore flow_nw_tos */
         }
-        if (ctx->flow.tunnel.ip_dst == ctx->orig_tunnel_ip_dst) {
+        if (ctx->flow.md.tunnel.ip_dst == ctx->orig_tunnel_ip_dst) {
             xlate_report(ctx, "Not tunneling to our own address");
             goto out; /* restore flow_nw_tos */
         }
@@ -6180,7 +6181,7 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
         out_port = odp_port;
         commit_odp_tunnel_action(&ctx->flow, &ctx->base_flow,
                                  ctx->odp_actions);
-        ctx->flow.tunnel = flow_tnl; /* Restore tunnel metadata */
+        ctx->flow.md.tunnel = flow_tnl; /* Restore tunnel metadata */
     } else {
         odp_port = ofport->odp_port;
         out_port = vsp_realdev_to_vlandev(ctx->ofproto, odp_port,
@@ -6188,7 +6189,7 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
         if (out_port != odp_port) {
             ctx->flow.vlan_tci = htons(0);
         }
-        ctx->flow.skb_mark &= ~IPSEC_MARK;
+        ctx->flow.md.skb_mark &= ~IPSEC_MARK;
     }
     commit_odp_actions(&ctx->flow, &ctx->base_flow, ctx->odp_actions);
     nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_OUTPUT, out_port);
@@ -6199,7 +6200,7 @@ compose_output_action__(struct action_xlate_ctx *ctx, uint16_t ofp_port,
 
     /* Restore flow */
     ctx->flow.vlan_tci = flow_vlan_tci;
-    ctx->flow.skb_mark = flow_skb_mark;
+    ctx->flow.md.skb_mark = flow_skb_mark;
  out:
     ctx->flow.nw_tos = flow_nw_tos;
 }
@@ -6258,20 +6259,20 @@ xlate_table_action(struct action_xlate_ctx *ctx,
 {
     if (ctx->recurse < MAX_RESUBMIT_RECURSION) {
         struct rule_dpif *rule;
-        uint16_t old_in_port = ctx->flow.in_port;
+        uint16_t old_in_port = ctx->flow.md.in_port;
         uint8_t old_table_id = ctx->table_id;
 
         ctx->table_id = table_id;
 
         /* Look up a flow with 'in_port' as the input port. */
-        ctx->flow.in_port = in_port;
+        ctx->flow.md.in_port = in_port;
         rule = rule_dpif_lookup__(ctx->ofproto, &ctx->flow, table_id);
 
         tag_the_flow(ctx, rule);
 
         /* Restore the original input port.  Otherwise OFPP_NORMAL and
          * OFPP_IN_PORT will have surprising behavior. */
-        ctx->flow.in_port = old_in_port;
+        ctx->flow.md.in_port = old_in_port;
 
         rule = ctx_rule_hooks(ctx, rule, may_packet_in);
 
@@ -6304,7 +6305,7 @@ xlate_ofpact_resubmit(struct action_xlate_ctx *ctx,
 
     in_port = resubmit->in_port;
     if (in_port == OFPP_IN_PORT) {
-        in_port = ctx->flow.in_port;
+        in_port = ctx->flow.md.in_port;
     }
 
     table_id = resubmit->table_id;
@@ -6323,7 +6324,7 @@ flood_packets(struct action_xlate_ctx *ctx, bool all)
     HMAP_FOR_EACH (ofport, up.hmap_node, &ctx->ofproto->up.ports) {
         uint16_t ofp_port = ofport->up.ofp_port;
 
-        if (ofp_port == ctx->flow.in_port) {
+        if (ofp_port == ctx->flow.md.in_port) {
             continue;
         }
 
@@ -6402,7 +6403,7 @@ execute_controller_action(struct action_xlate_ctx *ctx, int len,
     pin.cookie = ctx->rule ? ctx->rule->up.flow_cookie : 0;
 
     pin.send_len = len;
-    flow_get_metadata(&ctx->flow, &pin.fmd);
+    pin.fmd = ctx->flow.md;
 
     connmgr_send_packet_in(ctx->ofproto->up.connmgr, &pin);
     ofpbuf_delete(packet);
@@ -6514,10 +6515,10 @@ xlate_output_action(struct action_xlate_ctx *ctx,
 
     switch (port) {
     case OFPP_IN_PORT:
-        compose_output_action(ctx, ctx->flow.in_port);
+        compose_output_action(ctx, ctx->flow.md.in_port);
         break;
     case OFPP_TABLE:
-        xlate_table_action(ctx, ctx->flow.in_port, 0, may_packet_in);
+        xlate_table_action(ctx, ctx->flow.md.in_port, 0, may_packet_in);
         break;
     case OFPP_NORMAL:
         xlate_normal(ctx);
@@ -6535,7 +6536,7 @@ xlate_output_action(struct action_xlate_ctx *ctx,
         break;
     case OFPP_LOCAL:
     default:
-        if (port != ctx->flow.in_port) {
+        if (port != ctx->flow.md.in_port) {
             compose_output_action(ctx, port);
         } else {
             xlate_report(ctx, "skipping output to input port");
@@ -6583,16 +6584,16 @@ xlate_enqueue_action(struct action_xlate_ctx *ctx,
 
     /* Check output port. */
     if (ofp_port == OFPP_IN_PORT) {
-        ofp_port = ctx->flow.in_port;
-    } else if (ofp_port == ctx->flow.in_port) {
+        ofp_port = ctx->flow.md.in_port;
+    } else if (ofp_port == ctx->flow.md.in_port) {
         return;
     }
 
     /* Add datapath actions. */
-    flow_priority = ctx->flow.skb_priority;
-    ctx->flow.skb_priority = priority;
+    flow_priority = ctx->flow.md.skb_priority;
+    ctx->flow.md.skb_priority = priority;
     compose_output_action(ctx, ofp_port);
-    ctx->flow.skb_priority = flow_priority;
+    ctx->flow.md.skb_priority = flow_priority;
 
     /* Update NetFlow output port. */
     if (ctx->nf_output_iface == NF_OUT_DROP) {
@@ -6609,7 +6610,7 @@ xlate_set_queue_action(struct action_xlate_ctx *ctx, uint32_t queue_id)
 
     if (!dpif_queue_to_priority(ctx->ofproto->backer->dpif,
                                 queue_id, &skb_priority)) {
-        ctx->flow.skb_priority = skb_priority;
+        ctx->flow.md.skb_priority = skb_priority;
     } else {
         /* Couldn't translate queue to a priority.  Nothing to do.  A warning
          * has already been logged. */
@@ -6738,7 +6739,7 @@ static bool
 tunnel_ecn_ok(struct action_xlate_ctx *ctx)
 {
     if (is_ip_any(&ctx->base_flow)
-        && (ctx->flow.tunnel.ip_tos & IP_ECN_MASK) == IP_ECN_CE) {
+        && (ctx->flow.md.tunnel.ip_tos & IP_ECN_MASK) == IP_ECN_CE) {
         if ((ctx->base_flow.nw_tos & IP_ECN_MASK) == IP_ECN_NOT_ECT) {
             VLOG_WARN_RL(&rl, "dropping tunnel packet marked ECN CE"
                          " but is not ECN capable");
@@ -6860,7 +6861,8 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
             break;
 
         case OFPACT_SET_TUNNEL:
-            ctx->flow.tunnel.tun_id = htonll(ofpact_get_SET_TUNNEL(a)->tun_id);
+            ctx->flow.md.tunnel.tun_id
+                = htonll(ofpact_get_SET_TUNNEL(a)->tun_id);
             break;
 
         case OFPACT_SET_QUEUE:
@@ -6868,7 +6870,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
             break;
 
         case OFPACT_POP_QUEUE:
-            ctx->flow.skb_priority = ctx->orig_skb_priority;
+            ctx->flow.md.skb_priority = ctx->orig_skb_priority;
             break;
 
         case OFPACT_REG_MOVE:
@@ -6958,8 +6960,8 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
 
         case OFPACT_WRITE_METADATA:
             metadata = ofpact_get_WRITE_METADATA(a);
-            ctx->flow.metadata &= ~metadata->mask;
-            ctx->flow.metadata |= metadata->metadata & metadata->mask;
+            ctx->flow.md.metadata &= ~metadata->mask;
+            ctx->flow.md.metadata |= metadata->metadata & metadata->mask;
             break;
 
         case OFPACT_GOTO_TABLE: {
@@ -7037,8 +7039,8 @@ action_xlate_ctx_init(struct action_xlate_ctx *ctx,
     ctx->ofproto = ofproto;
     ctx->flow = *flow;
     ctx->base_flow = ctx->flow;
-    memset(&ctx->base_flow.tunnel, 0, sizeof ctx->base_flow.tunnel);
-    ctx->orig_tunnel_ip_dst = flow->tunnel.ip_dst;
+    memset(&ctx->base_flow.md.tunnel, 0, sizeof ctx->base_flow.md.tunnel);
+    ctx->orig_tunnel_ip_dst = flow->md.tunnel.ip_dst;
     ctx->rule = rule;
     ctx->packet = packet;
     ctx->may_learn = packet != NULL;
@@ -7083,7 +7085,7 @@ xlate_actions(struct action_xlate_ctx *ctx,
     ctx->mirrors = 0;
     ctx->recurse = 0;
     ctx->max_resubmit_trigger = false;
-    ctx->orig_skb_priority = ctx->flow.skb_priority;
+    ctx->orig_skb_priority = ctx->flow.md.skb_priority;
     ctx->table_id = 0;
     ctx->exit = false;
 
@@ -7118,7 +7120,7 @@ xlate_actions(struct action_xlate_ctx *ctx,
         }
     }
 
-    in_port = get_ofp_port(ctx->ofproto, ctx->flow.in_port);
+    in_port = get_ofp_port(ctx->ofproto, ctx->flow.md.in_port);
     special = process_special(ctx->ofproto, &ctx->flow, in_port, ctx->packet);
     if (special) {
         ctx->slow |= special;
@@ -7396,7 +7398,7 @@ add_mirror_actions(struct action_xlate_ctx *ctx, const struct flow *orig_flow)
     const struct nlattr *a;
     size_t left;
 
-    in_bundle = lookup_input_bundle(ctx->ofproto, orig_flow->in_port,
+    in_bundle = lookup_input_bundle(ctx->ofproto, orig_flow->md.in_port,
                                     ctx->packet != NULL, NULL);
     if (!in_bundle) {
         return;
@@ -7667,7 +7669,7 @@ xlate_normal(struct action_xlate_ctx *ctx)
 
     ctx->has_normal = true;
 
-    in_bundle = lookup_input_bundle(ctx->ofproto, ctx->flow.in_port,
+    in_bundle = lookup_input_bundle(ctx->ofproto, ctx->flow.md.in_port,
                                     ctx->packet != NULL, &in_port);
     if (!in_bundle) {
         xlate_report(ctx, "no input bundle, dropping");
@@ -7887,7 +7889,7 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf *packet,
 
     ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
     odp_flow_key_from_flow(&key, flow,
-                           ofp_port_to_odp_port(ofproto, flow->in_port));
+                           ofp_port_to_odp_port(ofproto, flow->md.in_port));
 
     dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
 
@@ -8083,7 +8085,7 @@ trace_format_regs(struct ds *result, int level, const char *title,
     ds_put_char_multiple(result, '\t', level);
     ds_put_format(result, "%s:", title);
     for (i = 0; i < FLOW_N_REGS; i++) {
-        ds_put_format(result, " reg%zu=0x%"PRIx32, i, trace->flow.regs[i]);
+        ds_put_format(result, " reg%zu=0x%"PRIx32, i, trace->flow.md.regs[i]);
     }
     ds_put_char(result, '\n');
 }
@@ -8226,7 +8228,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
         free(s);
 
         flow_extract(packet, priority, mark, NULL, in_port, &flow);
-        flow.tunnel.tun_id = tun_id;
+        flow.md.tunnel.tun_id = tun_id;
         initial_vals.vlan_tci = flow.vlan_tci;
     } else {
         unixctl_command_reply_error(conn, "Bad command syntax");
@@ -8811,14 +8813,14 @@ vsp_adjust_flow(const struct ofproto_dpif *ofproto, struct flow *flow)
     uint16_t realdev;
     int vid;
 
-    realdev = vsp_vlandev_to_realdev(ofproto, flow->in_port, &vid);
+    realdev = vsp_vlandev_to_realdev(ofproto, flow->md.in_port, &vid);
     if (!realdev) {
         return false;
     }
 
     /* Cause the flow to be processed as if it came in on the real device with
      * the VLAN device's VLAN ID. */
-    flow->in_port = realdev;
+    flow->md.in_port = realdev;
     flow->vlan_tci = htons((vid & VLAN_VID_MASK) | VLAN_CFI);
     return true;
 }
diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
index ffc4057..2535cb5 100644
--- a/ofproto/tunnel.c
+++ b/ofproto/tunnel.c
@@ -177,11 +177,11 @@ tnl_port_receive(const struct flow *flow)
     struct tnl_match match;
 
     memset(&match, 0, sizeof match);
-    match.odp_port = flow->in_port;
-    match.ip_src = flow->tunnel.ip_dst;
-    match.ip_dst = flow->tunnel.ip_src;
-    match.in_key = flow->tunnel.tun_id;
-    match.skb_mark = flow->skb_mark;
+    match.odp_port = flow->md.in_port;
+    match.ip_src = flow->md.tunnel.ip_dst;
+    match.ip_dst = flow->md.tunnel.ip_src;
+    match.in_key = flow->md.tunnel.tun_id;
+    match.skb_mark = flow->md.skb_mark;
 
     tnl_port = tnl_find(&match);
     if (!tnl_port) {
@@ -234,36 +234,36 @@ tnl_port_send(const struct tnl_port *tnl_port, struct flow *flow)
     }
 
     if (!cfg->ip_src_flow) {
-        flow->tunnel.ip_src = tnl_port->match.ip_src;
+        flow->md.tunnel.ip_src = tnl_port->match.ip_src;
     }
     if (!cfg->ip_dst_flow) {
-        flow->tunnel.ip_dst = tnl_port->match.ip_dst;
+        flow->md.tunnel.ip_dst = tnl_port->match.ip_dst;
     }
-    flow->skb_mark = tnl_port->match.skb_mark;
+    flow->md.skb_mark = tnl_port->match.skb_mark;
 
     if (!cfg->out_key_flow) {
-        flow->tunnel.tun_id = cfg->out_key;
+        flow->md.tunnel.tun_id = cfg->out_key;
     }
 
     if (cfg->ttl_inherit && is_ip_any(flow)) {
-        flow->tunnel.ip_ttl = flow->nw_ttl;
+        flow->md.tunnel.ip_ttl = flow->nw_ttl;
     } else {
-        flow->tunnel.ip_ttl = cfg->ttl;
+        flow->md.tunnel.ip_ttl = cfg->ttl;
     }
 
     if (cfg->tos_inherit && is_ip_any(flow)) {
-        flow->tunnel.ip_tos = flow->nw_tos & IP_DSCP_MASK;
+        flow->md.tunnel.ip_tos = flow->nw_tos & IP_DSCP_MASK;
     } else {
-        flow->tunnel.ip_tos = cfg->tos;
+        flow->md.tunnel.ip_tos = cfg->tos;
     }
 
     if ((flow->nw_tos & IP_ECN_MASK) == IP_ECN_CE) {
-        flow->tunnel.ip_tos |= IP_ECN_ECT_0;
+        flow->md.tunnel.ip_tos |= IP_ECN_ECT_0;
     } else {
-        flow->tunnel.ip_tos |= flow->nw_tos & IP_ECN_MASK;
+        flow->md.tunnel.ip_tos |= flow->nw_tos & IP_ECN_MASK;
     }
 
-    flow->tunnel.flags = (cfg->dont_fragment ? FLOW_TNL_F_DONT_FRAGMENT : 0)
+    flow->md.tunnel.flags = (cfg->dont_fragment ? FLOW_TNL_F_DONT_FRAGMENT : 0)
         | (cfg->csum ? FLOW_TNL_F_CSUM : 0)
         | (cfg->out_key_present ? FLOW_TNL_F_KEY : 0);
 
diff --git a/ofproto/tunnel.h b/ofproto/tunnel.h
index 34c1133..d2b8015 100644
--- a/ofproto/tunnel.h
+++ b/ofproto/tunnel.h
@@ -44,7 +44,7 @@ uint32_t tnl_port_send(const struct tnl_port *, struct flow *);
 static inline bool
 tnl_port_should_receive(const struct flow *flow)
 {
-    return flow->tunnel.ip_dst != 0;
+    return flow->md.tunnel.ip_dst != 0;
 }
 
 #endif /* tunnel.h */
diff --git a/tests/test-bundle.c b/tests/test-bundle.c
index f5b24b4..05afa93 100644
--- a/tests/test-bundle.c
+++ b/tests/test-bundle.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, 2012 Nicira, Inc.
+/* Copyright (c) 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -138,7 +138,7 @@ main(int argc, char *argv[])
         random_bytes(&flows[i], sizeof flows[i]);
         memset(flows[i].zeros, 0, sizeof flows[i].zeros);
         flows[i].mpls_depth = 0;
-        flows[i].regs[0] = OFPP_NONE;
+        flows[i].md.regs[0] = OFPP_NONE;
     }
 
     /* Cycles through each possible liveness permutation for the given
@@ -188,9 +188,9 @@ main(int argc, char *argv[])
             struct flow *flow = &flows[j];
             uint16_t old_slave_id, ofp_port;
 
-            old_slave_id = flow->regs[0];
+            old_slave_id = flow->md.regs[0];
             ofp_port = bundle_execute(bundle, flow, slave_enabled_cb, &sg);
-            flow->regs[0] = ofp_port;
+            flow->md.regs[0] = ofp_port;
 
             if (ofp_port != OFPP_NONE) {
                 slave_lookup(&sg, ofp_port)->flow_count++;
diff --git a/tests/test-classifier.c b/tests/test-classifier.c
index 18dee86..4bc2b4a 100644
--- a/tests/test-classifier.c
+++ b/tests/test-classifier.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -41,22 +41,22 @@
 
 /* Fields in a rule. */
 #define CLS_FIELDS                                                  \
-    /*        struct flow    all-caps */  \
-    /*        member name    name     */  \
-    /*        -----------    -------- */  \
-    CLS_FIELD(tunnel.tun_id, TUN_ID)      \
-    CLS_FIELD(metadata,      METADATA)    \
-    CLS_FIELD(nw_src,        NW_SRC)      \
-    CLS_FIELD(nw_dst,        NW_DST)      \
-    CLS_FIELD(in_port,       IN_PORT)     \
-    CLS_FIELD(vlan_tci,      VLAN_TCI)    \
-    CLS_FIELD(dl_type,       DL_TYPE)     \
-    CLS_FIELD(tp_src,        TP_SRC)      \
-    CLS_FIELD(tp_dst,        TP_DST)      \
-    CLS_FIELD(dl_src,        DL_SRC)      \
-    CLS_FIELD(dl_dst,        DL_DST)      \
-    CLS_FIELD(nw_proto,      NW_PROTO)    \
-    CLS_FIELD(nw_tos,        NW_DSCP)
+    /*        struct flow       all-caps */  \
+    /*        member name       name     */  \
+    /*        -----------       -------- */  \
+    CLS_FIELD(md.tunnel.tun_id, TUN_ID)      \
+    CLS_FIELD(md.metadata,      METADATA)    \
+    CLS_FIELD(nw_src,           NW_SRC)      \
+    CLS_FIELD(nw_dst,           NW_DST)      \
+    CLS_FIELD(md.in_port,       IN_PORT)     \
+    CLS_FIELD(vlan_tci,         VLAN_TCI)    \
+    CLS_FIELD(dl_type,          DL_TYPE)     \
+    CLS_FIELD(tp_src,           TP_SRC)      \
+    CLS_FIELD(tp_dst,           TP_DST)      \
+    CLS_FIELD(dl_src,           DL_SRC)      \
+    CLS_FIELD(dl_dst,           DL_DST)      \
+    CLS_FIELD(nw_proto,         NW_PROTO)    \
+    CLS_FIELD(nw_tos,           NW_DSCP)
 
 /* Field indexes.
  *
@@ -225,11 +225,11 @@ match(const struct cls_rule *wild_, const struct flow *fixed)
             eq = !((fixed->vlan_tci ^ wild.flow.vlan_tci)
                    & wild.wc.masks.vlan_tci);
         } else if (f_idx == CLS_F_IDX_TUN_ID) {
-            eq = !((fixed->tunnel.tun_id ^ wild.flow.tunnel.tun_id)
-                   & wild.wc.masks.tunnel.tun_id);
+            eq = !((fixed->md.tunnel.tun_id ^ wild.flow.md.tunnel.tun_id)
+                   & wild.wc.masks.md.tunnel.tun_id);
         } else if (f_idx == CLS_F_IDX_METADATA) {
-            eq = !((fixed->metadata ^ wild.flow.metadata)
-                   & wild.wc.masks.metadata);
+            eq = !((fixed->md.metadata ^ wild.flow.md.metadata)
+                   & wild.wc.masks.md.metadata);
         } else if (f_idx == CLS_F_IDX_NW_DSCP) {
             eq = !((fixed->nw_tos ^ wild.flow.nw_tos) &
                    (wild.wc.masks.nw_tos & IP_DSCP_MASK));
@@ -240,8 +240,8 @@ match(const struct cls_rule *wild_, const struct flow *fixed)
             eq = !((fixed->dl_type ^ wild.flow.dl_type)
                    & wild.wc.masks.dl_type);
         } else if (f_idx == CLS_F_IDX_IN_PORT) {
-            eq = !((fixed->in_port ^ wild.flow.in_port)
-                   & wild.wc.masks.in_port);
+            eq = !((fixed->md.in_port ^ wild.flow.md.in_port)
+                   & wild.wc.masks.md.in_port);
         } else {
             NOT_REACHED();
         }
@@ -408,9 +408,9 @@ compare_classifiers(struct classifier *cls, struct tcls *tcls)
         memset(&flow, 0, sizeof flow);
         flow.nw_src = nw_src_values[get_value(&x, N_NW_SRC_VALUES)];
         flow.nw_dst = nw_dst_values[get_value(&x, N_NW_DST_VALUES)];
-        flow.tunnel.tun_id = tun_id_values[get_value(&x, N_TUN_ID_VALUES)];
-        flow.metadata = metadata_values[get_value(&x, N_METADATA_VALUES)];
-        flow.in_port = in_port_values[get_value(&x, N_IN_PORT_VALUES)];
+        flow.md.tunnel.tun_id = tun_id_values[get_value(&x, N_TUN_ID_VALUES)];
+        flow.md.metadata = metadata_values[get_value(&x, N_METADATA_VALUES)];
+        flow.md.in_port = in_port_values[get_value(&x, N_IN_PORT_VALUES)];
         flow.vlan_tci = vlan_tci_values[get_value(&x, N_VLAN_TCI_VALUES)];
         flow.dl_type = dl_type_values[get_value(&x, N_DL_TYPE_VALUES)];
         flow.tp_src = tp_src_values[get_value(&x, N_TP_SRC_VALUES)];
@@ -536,9 +536,9 @@ make_rule(int wc_fields, unsigned int priority, int value_pat)
         } else if (f_idx == CLS_F_IDX_VLAN_TCI) {
             match.wc.masks.vlan_tci = htons(UINT16_MAX);
         } else if (f_idx == CLS_F_IDX_TUN_ID) {
-            match.wc.masks.tunnel.tun_id = htonll(UINT64_MAX);
+            match.wc.masks.md.tunnel.tun_id = htonll(UINT64_MAX);
         } else if (f_idx == CLS_F_IDX_METADATA) {
-            match.wc.masks.metadata = htonll(UINT64_MAX);
+            match.wc.masks.md.metadata = htonll(UINT64_MAX);
         } else if (f_idx == CLS_F_IDX_NW_DSCP) {
             match.wc.masks.nw_tos |= IP_DSCP_MASK;
         } else if (f_idx == CLS_F_IDX_NW_PROTO) {
@@ -546,7 +546,7 @@ make_rule(int wc_fields, unsigned int priority, int value_pat)
         } else if (f_idx == CLS_F_IDX_DL_TYPE) {
             match.wc.masks.dl_type = htons(UINT16_MAX);
         } else if (f_idx == CLS_F_IDX_IN_PORT) {
-            match.wc.masks.in_port = UINT16_MAX;
+            match.wc.masks.md.in_port = UINT16_MAX;
         } else {
             NOT_REACHED();
         }
diff --git a/tests/test-multipath.c b/tests/test-multipath.c
index 8442bc2..2d718a9 100644
--- a/tests/test-multipath.c
+++ b/tests/test-multipath.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2012 Nicira, Inc.
+ * Copyright (c) 2010, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -65,11 +65,11 @@ main(int argc, char *argv[])
 
             mp.max_link = n - 1;
             multipath_execute(&mp, &flow);
-            old_link = flow.regs[0];
+            old_link = flow.md.regs[0];
 
             mp.max_link = n;
             multipath_execute(&mp, &flow);
-            new_link = flow.regs[0];
+            new_link = flow.md.regs[0];
 
             assert(old_link >= 0 && old_link < n);
             assert(new_link >= 0 && new_link < n + 1);
diff --git a/tests/test-odp.c b/tests/test-odp.c
index 268a105..e08707a 100644
--- a/tests/test-odp.c
+++ b/tests/test-odp.c
@@ -70,7 +70,7 @@ parse_keys(void)
         /* Convert cls_rule back to odp_key. */
         ofpbuf_uninit(&odp_key);
         ofpbuf_init(&odp_key, 0);
-        odp_flow_key_from_flow(&odp_key, &flow, flow.in_port);
+        odp_flow_key_from_flow(&odp_key, &flow, flow.md.in_port);
 
         if (odp_key.size > ODPUTIL_FLOW_KEY_BYTES) {
             printf ("too long: %zu > %d\n",
-- 
1.7.10.4




More information about the dev mailing list