[ovs-dev] [PATCH V3] feature: Create specific types for ofp and odp port

Alex Wang alexw at nicira.com
Wed Jun 19 23:58:44 UTC 2013


Currently datapath ports and openflow ports are both represented by unsigned
integers of various sizes. With implicit casts, etc. it is easy to mix them
up and use one where the other is expected. This commit creates two typedefs
ofp_port_t and odp_port_t. Both of these two types are marked by
"__attribute__((bitwise))" so that Sparse can be used to detect any misuse.

Signed-off-by: Alex Wang <alexw at nicira.com>

---

v2 -> v3:
- Adds str_to_ofp, nl_msg_put_odp_port and nl_attr_get_odp_port functions
- Defines ODPP_LOCAL and ODPP_NONE macros
- Removes unnecessary utility functions in lib/flow.h
- Removes changes in lib/sflow* files
- Rebases to current master

v1 -> v2:
- Adds ofp_to_u16 / odp_to_u32 functions for conversion from ofp/odp_port_t
  to corresponding uint types
- Adds uint_to_ofp / uint_to_odp functions for conversion from uint variables
  to corresponding ofp_port_t, odp_port_t types
- Rebases to current master

SOME DESIGN IDEAS:

include/openvswitch/types.h :
- Typedefs ofp_port_t, odp_port_t and ofp11_port_t

include/openflow/openflow-1.0.h, openflow-1.1.h :
- Defines Openflow related macros e.g. OFPP_NONE, OFPP_MAX

lib/dpif-linux.c, dpif-netdev.c :
- Explicitly casts odp_port_t to uint32_t, since the odp_port variable is used
  as array index
- The MAX_PORT macro is not converted to odp_port_t, since it is compared with
  other UINT types and used as array size
- Note the choose_port() function is changed in lib/dpif-netdev.c

lib/flow.h, flow.c :
- Defines "union flow_in_port", which can be ofp_port_t, odp_port_t or
  ofp11_port_t. And each "struct flow" contains a "union flow_in_port in_port"
- Defines ofp/odp_port_t related utility functions, e.g. ofp_htons, odp_htonl
- The in_port argument of "flow_extract()" function is changed to of type
  "union flow_in_port *", since it is called with both odp/ofp port number

lib/odp-util.c, ofp-util.c :
- Nasty, a lot of conversions between Openflow protocol data structures and
  internal abstract data structures. Also a lot of explicity cast using
  OVS_FORCE macro

ofproto/ofproto.c ofproto-dpif.c, vswitch/bridge.c :
- A lot of changes in struct element and function headers. Convert from uint
  to corresponding ofp/odp_port_t type
- Note the alloc_ofp_port() function is changed in ofproto/ofproto.c
---
 include/openflow/openflow-1.0.h |   38 +++++------
 include/openflow/openflow-1.1.h |    4 +-
 include/openvswitch/types.h     |   12 ++++
 lib/bundle.c                    |   23 ++++---
 lib/bundle.h                    |    6 +-
 lib/dpif-linux.c                |   58 ++++++++--------
 lib/dpif-linux.h                |    4 +-
 lib/dpif-netdev.c               |   87 ++++++++++++------------
 lib/dpif-provider.h             |   10 +--
 lib/dpif.c                      |   22 +++---
 lib/dpif.h                      |   14 ++--
 lib/flow.c                      |    8 +--
 lib/flow.h                      |   58 ++++++++++++++--
 lib/learn.c                     |    4 +-
 lib/learning-switch.c           |   30 +++++----
 lib/mac-learning.h              |    2 +-
 lib/match.c                     |   10 +--
 lib/match.h                     |    2 +-
 lib/meta-flow.c                 |   35 +++++-----
 lib/netlink.c                   |   19 ++++++
 lib/netlink.h                   |    2 +
 lib/nx-match.c                  |    6 +-
 lib/odp-util.c                  |   15 +++--
 lib/odp-util.h                  |    5 +-
 lib/ofp-actions.c               |   34 +++++-----
 lib/ofp-actions.h               |   12 ++--
 lib/ofp-parse.c                 |   12 ++--
 lib/ofp-print.c                 |   14 ++--
 lib/ofp-util.c                  |  138 +++++++++++++++++++------------------
 lib/ofp-util.h                  |   36 +++++-----
 lib/util.c                      |   12 +++-
 lib/util.h                      |    3 +
 ofproto/connmgr.c               |    4 +-
 ofproto/connmgr.h               |    6 +-
 ofproto/in-band.c               |    4 +-
 ofproto/in-band.h               |    3 +-
 ofproto/netflow.c               |   12 ++--
 ofproto/netflow.h               |   10 ++-
 ofproto/ofproto-dpif-sflow.c    |   21 +++---
 ofproto/ofproto-dpif-sflow.h    |    9 +--
 ofproto/ofproto-dpif-xlate.c    |   96 +++++++++++++-------------
 ofproto/ofproto-dpif-xlate.h    |    2 +-
 ofproto/ofproto-dpif.c          |  142 +++++++++++++++++++++------------------
 ofproto/ofproto-dpif.h          |   17 ++---
 ofproto/ofproto-provider.h      |   18 ++---
 ofproto/ofproto.c               |  110 ++++++++++++++++--------------
 ofproto/ofproto.h               |   37 +++++-----
 ofproto/pinsched.c              |    9 +--
 ofproto/pinsched.h              |    3 +-
 ofproto/pktbuf.c                |   10 +--
 ofproto/pktbuf.h                |    4 +-
 ofproto/tunnel.c                |   16 ++---
 ofproto/tunnel.h                |    8 +--
 tests/test-bundle.c             |   16 ++---
 tests/test-classifier.c         |   12 ++--
 tests/test-flows.c              |    5 +-
 tests/test-odp.c                |    2 +-
 utilities/ovs-dpctl.c           |   14 ++--
 utilities/ovs-ofctl.c           |   22 +++---
 vswitchd/bridge.c               |   51 +++++++-------
 60 files changed, 773 insertions(+), 625 deletions(-)

diff --git a/include/openflow/openflow-1.0.h b/include/openflow/openflow-1.0.h
index c30fa92..f2b90db 100644
--- a/include/openflow/openflow-1.0.h
+++ b/include/openflow/openflow-1.0.h
@@ -28,28 +28,22 @@
  * 0xff00...0xfff7  "reserved" but not assigned a meaning by OpenFlow 1.0
  * 0xfff8...0xffff  "reserved" OFPP_* ports with assigned meanings
  */
-enum ofp_port {
-    /* Ranges. */
-    OFPP_MAX        = 0xff00,   /* Maximum number of physical switch ports. */
-    OFPP_FIRST_RESV = 0xfff8,   /* First assigned reserved port number. */
-    OFPP_LAST_RESV  = 0xffff,   /* Last assigned reserved port number. */
-
-    /* Reserved output "ports". */
-    OFPP_IN_PORT    = 0xfff8,  /* Send the packet out the input port.  This
-                                  virtual port must be explicitly used
-                                  in order to send back out of the input
-                                  port. */
-    OFPP_TABLE      = 0xfff9,  /* Perform actions in flow table.
-                                  NB: This can only be the destination
-                                  port for packet-out messages. */
-    OFPP_NORMAL     = 0xfffa,  /* Process with normal L2/L3 switching. */
-    OFPP_FLOOD      = 0xfffb,  /* All physical ports except input port and
-                                  those disabled by STP. */
-    OFPP_ALL        = 0xfffc,  /* All physical ports except input port. */
-    OFPP_CONTROLLER = 0xfffd,  /* Send to controller. */
-    OFPP_LOCAL      = 0xfffe,  /* Local openflow "port". */
-    OFPP_NONE       = 0xffff   /* Not associated with a physical port. */
-};
+
+/* Ranges. */
+#define OFPP_MAX        OFP_PORT_C(0xff00) /* Max # of switch ports. */
+#define OFPP_FIRST_RESV OFP_PORT_C(0xfff8) /* First assigned reserved port. */
+#define OFPP_LAST_RESV  OFP_PORT_C(0xffff) /* Last assigned reserved port. */
+
+/* Reserved output "ports". */
+#define OFPP_IN_PORT    OFP_PORT_C(0xfff8) /* Where the packet came in. */
+#define OFPP_TABLE      OFP_PORT_C(0xfff9) /* Perform actions in flow table. */
+#define OFPP_NORMAL     OFP_PORT_C(0xfffa) /* Process with normal L2/L3. */
+#define OFPP_FLOOD      OFP_PORT_C(0xfffb) /* All ports except input port and
+                                            * ports disabled by STP. */
+#define OFPP_ALL        OFP_PORT_C(0xfffc) /* All ports except input port. */
+#define OFPP_CONTROLLER OFP_PORT_C(0xfffd) /* Send to controller. */
+#define OFPP_LOCAL      OFP_PORT_C(0xfffe) /* Local openflow "port". */
+#define OFPP_NONE       OFP_PORT_C(0xffff) /* Not associated with any port. */
 
 /* OpenFlow 1.0 specific capabilities supported by the datapath (struct
  * ofp_switch_features, member capabilities). */
diff --git a/include/openflow/openflow-1.1.h b/include/openflow/openflow-1.1.h
index ec94cee..f7c2e78 100644
--- a/include/openflow/openflow-1.1.h
+++ b/include/openflow/openflow-1.1.h
@@ -67,8 +67,8 @@
  * an OpenFlow 1.0 reserved port number to or from, respectively, the
  * corresponding OpenFlow 1.1 reserved port number.
  */
-#define OFPP11_MAX    0xffffff00
-#define OFPP11_OFFSET (OFPP11_MAX - OFPP_MAX)
+#define OFPP11_MAX    OFP11_PORT_C(0xffffff00)
+#define OFPP11_OFFSET 0xffff0000    /* OFPP11_MAX - OFPP_MAX */
 
 /* Reserved wildcard port used only for flow mod (delete) and flow stats
  * requests. Selects all flows regardless of output port
diff --git a/include/openvswitch/types.h b/include/openvswitch/types.h
index 72caa5c..71cf468 100644
--- a/include/openvswitch/types.h
+++ b/include/openvswitch/types.h
@@ -60,4 +60,16 @@ typedef struct {
         ovs_be32 hi, lo;
 } ovs_32aligned_be64;
 
+/* ofp_port_t represents the port number of a OpenFlow switch.
+ * odp_port_t represents the port number on the datapath.
+ * ofp11_port_t represents the OpenFlow-1.1 port number. */
+typedef uint16_t OVS_BITWISE ofp_port_t;
+typedef uint32_t OVS_BITWISE odp_port_t;
+typedef uint32_t OVS_BITWISE ofp11_port_t;
+
+/* Macro functions that cast int types to ofp/odp/ofp11 types. */
+#define OFP_PORT_C(X) ((OVS_FORCE ofp_port_t) X)
+#define ODP_PORT_C(X) ((OVS_FORCE odp_port_t) X)
+#define OFP11_PORT_C(X) ((OVS_FORCE ofp11_port_t) X)
+
 #endif /* openvswitch/types.h */
diff --git a/lib/bundle.c b/lib/bundle.c
index b3821e8..d1834d0 100644
--- a/lib/bundle.c
+++ b/lib/bundle.c
@@ -35,14 +35,14 @@
 
 VLOG_DEFINE_THIS_MODULE(bundle);
 
-static uint16_t
+static ofp_port_t
 execute_ab(const struct ofpact_bundle *bundle,
-           bool (*slave_enabled)(uint16_t ofp_port, void *aux), void *aux)
+           bool (*slave_enabled)(ofp_port_t ofp_port, void *aux), void *aux)
 {
     size_t i;
 
     for (i = 0; i < bundle->n_slaves; i++) {
-        uint16_t slave = bundle->slaves[i];
+        ofp_port_t slave = bundle->slaves[i];
         if (slave_enabled(slave, aux)) {
             return slave;
         }
@@ -51,10 +51,10 @@ execute_ab(const struct ofpact_bundle *bundle,
     return OFPP_NONE;
 }
 
-static uint16_t
+static ofp_port_t
 execute_hrw(const struct ofpact_bundle *bundle,
             const struct flow *flow, struct flow_wildcards *wc,
-            bool (*slave_enabled)(uint16_t ofp_port, void *aux), void *aux)
+            bool (*slave_enabled)(ofp_port_t ofp_port, void *aux), void *aux)
 {
     uint32_t flow_hash, best_hash;
     int best, i;
@@ -85,10 +85,11 @@ execute_hrw(const struct ofpact_bundle *bundle,
  * calculate the result.  Uses 'slave_enabled' to determine if the slave
  * designated by 'ofp_port' is up.  Returns the chosen slave, or
  * OFPP_NONE if none of the slaves are acceptable. */
-uint16_t
+ofp_port_t
 bundle_execute(const struct ofpact_bundle *bundle,
                const struct flow *flow, struct flow_wildcards *wc,
-               bool (*slave_enabled)(uint16_t ofp_port, void *aux), void *aux)
+               bool (*slave_enabled)(ofp_port_t ofp_port, void *aux),
+               void *aux)
 {
     switch (bundle->algorithm) {
     case NX_BD_ALG_HRW:
@@ -186,7 +187,7 @@ bundle_from_openflow(const struct nx_action_bundle *nab,
 }
 
 enum ofperr
-bundle_check(const struct ofpact_bundle *bundle, int max_ports,
+bundle_check(const struct ofpact_bundle *bundle, ofp_port_t max_ports,
              const struct flow *flow)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
@@ -200,7 +201,7 @@ bundle_check(const struct ofpact_bundle *bundle, int max_ports,
     }
 
     for (i = 0; i < bundle->n_slaves; i++) {
-        uint16_t ofp_port = bundle->slaves[i];
+        ofp_port_t ofp_port = bundle->slaves[i];
         enum ofperr error;
 
         error = ofputil_check_output_port(ofp_port, max_ports);
@@ -246,7 +247,7 @@ bundle_to_nxast(const struct ofpact_bundle *bundle, struct ofpbuf *openflow)
 
     slaves = ofpbuf_put_zeros(openflow, slaves_len);
     for (i = 0; i < bundle->n_slaves; i++) {
-        slaves[i] = htons(bundle->slaves[i]);
+        slaves[i] = htons(ofp_to_u16(bundle->slaves[i]));
     }
 }
 
@@ -271,7 +272,7 @@ bundle_parse__(const char *s, char **save_ptr,
     bundle = ofpact_put_BUNDLE(ofpacts);
 
     for (;;) {
-        uint16_t slave_port;
+        ofp_port_t slave_port;
         char *slave;
 
         slave = strtok_r(NULL, ", []", save_ptr);
diff --git a/lib/bundle.h b/lib/bundle.h
index 2619aeb..3e92374 100644
--- a/lib/bundle.h
+++ b/lib/bundle.h
@@ -35,13 +35,13 @@ struct ofpbuf;
  *
  * See include/openflow/nicira-ext.h for NXAST_BUNDLE specification. */
 
-uint16_t bundle_execute(const struct ofpact_bundle *, const struct flow *,
+ofp_port_t bundle_execute(const struct ofpact_bundle *, const struct flow *,
                         struct flow_wildcards *wc,
-                        bool (*slave_enabled)(uint16_t ofp_port, void *aux),
+                        bool (*slave_enabled)(ofp_port_t ofp_port, void *aux),
                         void *aux);
 enum ofperr bundle_from_openflow(const struct nx_action_bundle *,
                                  struct ofpbuf *ofpact);
-enum ofperr bundle_check(const struct ofpact_bundle *, int max_ports,
+enum ofperr bundle_check(const struct ofpact_bundle *, ofp_port_t max_ports,
                          const struct flow *);
 void bundle_to_nxast(const struct ofpact_bundle *, struct ofpbuf *of10);
 void bundle_parse(const char *, struct ofpbuf *ofpacts);
diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c
index 1383b58..b8386e3 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -167,7 +167,8 @@ static int dpif_linux_init(void);
 static void open_dpif(const struct dpif_linux_dp *, struct dpif **);
 static bool dpif_linux_nln_parse(struct ofpbuf *, void *);
 static void dpif_linux_port_changed(const void *vport, void *dpif);
-static uint32_t dpif_linux_port_get_pid(const struct dpif *, uint32_t port_no);
+static uint32_t dpif_linux_port_get_pid(const struct dpif *,
+                                        odp_port_t port_no);
 
 static void dpif_linux_vport_to_ofpbuf(const struct dpif_linux_vport *,
                                        struct ofpbuf *);
@@ -259,7 +260,7 @@ open_dpif(const struct dpif_linux_dp *dp, struct dpif **dpifp)
 static void
 destroy_channels(struct dpif_linux *dpif)
 {
-    int i;
+    unsigned int i;
 
     if (dpif->epoll_fd < 0) {
         return;
@@ -278,7 +279,7 @@ destroy_channels(struct dpif_linux *dpif)
         dpif_linux_vport_init(&vport_request);
         vport_request.cmd = OVS_VPORT_CMD_SET;
         vport_request.dp_ifindex = dpif->dp_ifindex;
-        vport_request.port_no = i;
+        vport_request.port_no = u32_to_odp(i);
         vport_request.upcall_pid = &upcall_pid;
         dpif_linux_vport_transact(&vport_request, NULL, NULL);
 
@@ -298,9 +299,10 @@ destroy_channels(struct dpif_linux *dpif)
 }
 
 static int
-add_channel(struct dpif_linux *dpif, uint32_t port_no, struct nl_sock *sock)
+add_channel(struct dpif_linux *dpif, odp_port_t port_no, struct nl_sock *sock)
 {
     struct epoll_event event;
+    uint32_t port_idx = odp_to_u32(port_no);
 
     if (dpif->epoll_fd < 0) {
         return 0;
@@ -308,9 +310,9 @@ add_channel(struct dpif_linux *dpif, uint32_t port_no, struct nl_sock *sock)
 
     /* We assume that the datapath densely chooses port numbers, which
      * can therefore be used as an index into an array of channels. */
-    if (port_no >= dpif->uc_array_size) {
-        int new_size = port_no + 1;
-        int i;
+    if (port_idx >= dpif->uc_array_size) {
+        uint32_t new_size = port_idx + 1;
+        uint32_t i;
 
         if (new_size > MAX_PORTS) {
             VLOG_WARN_RL(&error_rl, "%s: datapath port %"PRIu32" too big",
@@ -331,29 +333,30 @@ add_channel(struct dpif_linux *dpif, uint32_t port_no, struct nl_sock *sock)
 
     memset(&event, 0, sizeof event);
     event.events = EPOLLIN;
-    event.data.u32 = port_no;
+    event.data.u32 = port_idx;
     if (epoll_ctl(dpif->epoll_fd, EPOLL_CTL_ADD, nl_sock_fd(sock),
                   &event) < 0) {
         return errno;
     }
 
-    nl_sock_destroy(dpif->channels[port_no].sock);
-    dpif->channels[port_no].sock = sock;
-    dpif->channels[port_no].last_poll = LLONG_MIN;
+    nl_sock_destroy(dpif->channels[port_idx].sock);
+    dpif->channels[port_idx].sock = sock;
+    dpif->channels[port_idx].last_poll = LLONG_MIN;
 
     return 0;
 }
 
 static void
-del_channel(struct dpif_linux *dpif, uint32_t port_no)
+del_channel(struct dpif_linux *dpif, odp_port_t port_no)
 {
     struct dpif_channel *ch;
+    uint32_t port_idx = odp_to_u32(port_no);
 
-    if (dpif->epoll_fd < 0 || port_no >= dpif->uc_array_size) {
+    if (dpif->epoll_fd < 0 || port_idx >= dpif->uc_array_size) {
         return;
     }
 
-    ch = &dpif->channels[port_no];
+    ch = &dpif->channels[port_idx];
     if (!ch->sock) {
         return;
     }
@@ -480,7 +483,7 @@ netdev_to_ovs_vport_type(const struct netdev *netdev)
 
 static int
 dpif_linux_port_add(struct dpif *dpif_, struct netdev *netdev,
-                    uint32_t *port_nop)
+                    odp_port_t *port_nop)
 {
     struct dpif_linux *dpif = dpif_linux_cast(dpif_);
     const struct netdev_tunnel_config *tnl_cfg;
@@ -539,7 +542,7 @@ dpif_linux_port_add(struct dpif *dpif_, struct netdev *netdev,
         VLOG_DBG("%s: assigning port %"PRIu32" to netlink pid %"PRIu32,
                  dpif_name(dpif_), reply.port_no, upcall_pid);
     } else {
-        if (error == EBUSY && *port_nop != UINT32_MAX) {
+        if (error == EBUSY && *port_nop != ODPP_NONE) {
             VLOG_INFO("%s: requested port %"PRIu32" is in use",
                       dpif_name(dpif_), *port_nop);
         }
@@ -571,7 +574,7 @@ dpif_linux_port_add(struct dpif *dpif_, struct netdev *netdev,
 }
 
 static int
-dpif_linux_port_del(struct dpif *dpif_, uint32_t port_no)
+dpif_linux_port_del(struct dpif *dpif_, odp_port_t port_no)
 {
     struct dpif_linux *dpif = dpif_linux_cast(dpif_);
     struct dpif_linux_vport vport;
@@ -589,7 +592,7 @@ dpif_linux_port_del(struct dpif *dpif_, uint32_t port_no)
 }
 
 static int
-dpif_linux_port_query__(const struct dpif *dpif, uint32_t port_no,
+dpif_linux_port_query__(const struct dpif *dpif, odp_port_t port_no,
                         const char *port_name, struct dpif_port *dpif_port)
 {
     struct dpif_linux_vport request;
@@ -620,7 +623,7 @@ dpif_linux_port_query__(const struct dpif *dpif, uint32_t port_no,
 }
 
 static int
-dpif_linux_port_query_by_number(const struct dpif *dpif, uint32_t port_no,
+dpif_linux_port_query_by_number(const struct dpif *dpif, odp_port_t port_no,
                                 struct dpif_port *dpif_port)
 {
     return dpif_linux_port_query__(dpif, port_no, NULL, dpif_port);
@@ -633,23 +636,24 @@ dpif_linux_port_query_by_name(const struct dpif *dpif, const char *devname,
     return dpif_linux_port_query__(dpif, 0, devname, dpif_port);
 }
 
-static int
+static odp_port_t
 dpif_linux_get_max_ports(const struct dpif *dpif OVS_UNUSED)
 {
-    return MAX_PORTS;
+    return u32_to_odp(MAX_PORTS);
 }
 
 static uint32_t
-dpif_linux_port_get_pid(const struct dpif *dpif_, uint32_t port_no)
+dpif_linux_port_get_pid(const struct dpif *dpif_, odp_port_t port_no)
 {
     struct dpif_linux *dpif = dpif_linux_cast(dpif_);
+    uint32_t port_idx = odp_to_u32(port_no);
 
     if (dpif->epoll_fd < 0) {
         return 0;
     } else {
         /* The UINT32_MAX "reserved" port number uses the "ovs-system"'s
          * channel, since it is not heavily loaded. */
-        int idx = (port_no >= dpif->uc_array_size) ? 0 : port_no;
+        uint32_t idx = port_idx >= dpif->uc_array_size ? 0 : port_idx;
         return nl_sock_pid(dpif->channels[idx].sock);
     }
 }
@@ -1553,7 +1557,7 @@ dpif_linux_vport_from_ofpbuf(struct dpif_linux_vport *vport,
 
     vport->cmd = genl->cmd;
     vport->dp_ifindex = ovs_header->dp_ifindex;
-    vport->port_no = nl_attr_get_u32(a[OVS_VPORT_ATTR_PORT_NO]);
+    vport->port_no = nl_attr_get_odp_port(a[OVS_VPORT_ATTR_PORT_NO]);
     vport->type = nl_attr_get_u32(a[OVS_VPORT_ATTR_TYPE]);
     vport->name = nl_attr_get_string(a[OVS_VPORT_ATTR_NAME]);
     if (a[OVS_VPORT_ATTR_UPCALL_PID]) {
@@ -1583,8 +1587,8 @@ dpif_linux_vport_to_ofpbuf(const struct dpif_linux_vport *vport,
     ovs_header = ofpbuf_put_uninit(buf, sizeof *ovs_header);
     ovs_header->dp_ifindex = vport->dp_ifindex;
 
-    if (vport->port_no != UINT32_MAX) {
-        nl_msg_put_u32(buf, OVS_VPORT_ATTR_PORT_NO, vport->port_no);
+    if (vport->port_no != ODPP_NONE) {
+        nl_msg_put_odp_port(buf, OVS_VPORT_ATTR_PORT_NO, vport->port_no);
     }
 
     if (vport->type != OVS_VPORT_TYPE_UNSPEC) {
@@ -1615,7 +1619,7 @@ void
 dpif_linux_vport_init(struct dpif_linux_vport *vport)
 {
     memset(vport, 0, sizeof *vport);
-    vport->port_no = UINT32_MAX;
+    vport->port_no = ODPP_NONE;
 }
 
 /* Executes 'request' in the kernel datapath.  If the command fails, returns a
diff --git a/lib/dpif-linux.h b/lib/dpif-linux.h
index 81062aa..ec94ccf 100644
--- a/lib/dpif-linux.h
+++ b/lib/dpif-linux.h
@@ -22,6 +22,8 @@
 #include <stdint.h>
 #include <linux/openvswitch.h>
 
+#include "flow.h"
+
 struct ofpbuf;
 
 struct dpif_linux_vport {
@@ -30,7 +32,7 @@ struct dpif_linux_vport {
 
     /* ovs_vport header. */
     int dp_ifindex;
-    uint32_t port_no;                      /* UINT32_MAX if unknown. */
+    odp_port_t port_no;                    /* ODPP_NONE if unknown. */
     enum ovs_vport_type type;
 
     /* Attributes.
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 52aedb6..867af91 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -104,7 +104,7 @@ struct dp_netdev {
 
 /* A port in a netdev-based datapath. */
 struct dp_netdev_port {
-    int port_no;                /* Index into dp_netdev's 'ports'. */
+    odp_port_t port_no;         /* Index into dp_netdev's 'ports'. */
     struct list node;           /* Element in dp_netdev's 'port_list'. */
     struct netdev *netdev;
     struct netdev_saved_flags *sf;
@@ -141,15 +141,15 @@ static struct shash dp_netdevs = SHASH_INITIALIZER(&dp_netdevs);
 /* Maximum port MTU seen so far. */
 static int max_mtu = ETH_PAYLOAD_MAX;
 
-static int get_port_by_number(struct dp_netdev *, uint32_t port_no,
+static int get_port_by_number(struct dp_netdev *, odp_port_t port_no,
                               struct dp_netdev_port **portp);
 static int get_port_by_name(struct dp_netdev *, const char *devname,
                             struct dp_netdev_port **portp);
 static void dp_netdev_free(struct dp_netdev *);
 static void dp_netdev_flow_flush(struct dp_netdev *);
 static int do_add_port(struct dp_netdev *, const char *devname,
-                       const char *type, uint32_t port_no);
-static int do_del_port(struct dp_netdev *, uint32_t port_no);
+                       const char *type, odp_port_t port_no);
+static int do_del_port(struct dp_netdev *, odp_port_t port_no);
 static int dpif_netdev_open(const struct dpif_class *, const char *name,
                             bool create, struct dpif **);
 static int dp_netdev_output_userspace(struct dp_netdev *, const struct ofpbuf *,
@@ -218,10 +218,12 @@ create_dpif_netdev(struct dp_netdev *dp)
     return &dpif->dpif;
 }
 
-static int
+/* Choose an unused, non-zero port number and return it on success.
+ * Return 0 on failure. */
+static uint32_t
 choose_port(struct dp_netdev *dp, const char *name)
 {
-    int port_no;
+    uint32_t port_no;
 
     if (dp->class != &dpif_netdev_class) {
         const char *p;
@@ -254,7 +256,7 @@ choose_port(struct dp_netdev *dp, const char *name)
         }
     }
 
-    return -1;
+    return 0;
 }
 
 static int
@@ -275,7 +277,7 @@ create_dp_netdev(const char *name, const struct dpif_class *class,
     hmap_init(&dp->flow_table);
     list_init(&dp->port_list);
 
-    error = do_add_port(dp, name, "internal", OVSP_LOCAL);
+    error = do_add_port(dp, name, "internal", ODPP_LOCAL);
     if (error) {
         dp_netdev_free(dp);
         return error;
@@ -379,7 +381,7 @@ dpif_netdev_get_stats(const struct dpif *dpif, struct dpif_dp_stats *stats)
 
 static int
 do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
-            uint32_t port_no)
+            odp_port_t port_no)
 {
     struct netdev_saved_flags *sf;
     struct dp_netdev_port *port;
@@ -429,7 +431,7 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
     }
 
     list_push_back(&dp->port_list, &port->node);
-    dp->ports[port_no] = port;
+    dp->ports[odp_to_u32(port_no)] = port;
     dp->serial++;
 
     return 0;
@@ -437,53 +439,53 @@ do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
 
 static int
 dpif_netdev_port_add(struct dpif *dpif, struct netdev *netdev,
-                     uint32_t *port_nop)
+                     odp_port_t *port_nop)
 {
     struct dp_netdev *dp = get_dp_netdev(dpif);
     char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
     const char *dpif_port;
-    int port_no;
+    uint32_t port_no = odp_to_u32(*port_nop);
 
     dpif_port = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
-    if (*port_nop != UINT32_MAX) {
-        if (*port_nop >= MAX_PORTS) {
+    if (port_no != UINT32_MAX) {
+        if (port_no >= MAX_PORTS) {
             return EFBIG;
-        } else if (dp->ports[*port_nop]) {
+        } else if (dp->ports[port_no]) {
             return EBUSY;
         }
-        port_no = *port_nop;
     } else {
         port_no = choose_port(dp, dpif_port);
     }
-    if (port_no >= 0) {
-        *port_nop = port_no;
-        return do_add_port(dp, dpif_port, netdev_get_type(netdev), port_no);
+    if (port_no > 0) {
+        *port_nop = u32_to_odp(port_no);
+        return do_add_port(dp, dpif_port, netdev_get_type(netdev), *port_nop);
     }
     return EFBIG;
 }
 
 static int
-dpif_netdev_port_del(struct dpif *dpif, uint32_t port_no)
+dpif_netdev_port_del(struct dpif *dpif, odp_port_t port_no)
 {
     struct dp_netdev *dp = get_dp_netdev(dpif);
-    return port_no == OVSP_LOCAL ? EINVAL : do_del_port(dp, port_no);
+    return (port_no == ODPP_LOCAL ?
+                           EINVAL : do_del_port(dp, port_no));
 }
 
 static bool
-is_valid_port_number(uint32_t port_no)
+is_valid_port_number(odp_port_t port_no)
 {
-    return port_no < MAX_PORTS;
+    return odp_to_u32(port_no) < MAX_PORTS;
 }
 
 static int
 get_port_by_number(struct dp_netdev *dp,
-                   uint32_t port_no, struct dp_netdev_port **portp)
+                   odp_port_t port_no, struct dp_netdev_port **portp)
 {
     if (!is_valid_port_number(port_no)) {
         *portp = NULL;
         return EINVAL;
     } else {
-        *portp = dp->ports[port_no];
+        *portp = dp->ports[odp_to_u32(port_no)];
         return *portp ? 0 : ENOENT;
     }
 }
@@ -504,7 +506,7 @@ get_port_by_name(struct dp_netdev *dp,
 }
 
 static int
-do_del_port(struct dp_netdev *dp, uint32_t port_no)
+do_del_port(struct dp_netdev *dp, odp_port_t port_no)
 {
     struct dp_netdev_port *port;
     int error;
@@ -515,7 +517,7 @@ do_del_port(struct dp_netdev *dp, uint32_t port_no)
     }
 
     list_remove(&port->node);
-    dp->ports[port->port_no] = NULL;
+    dp->ports[odp_to_u32(port_no)] = NULL;
     dp->serial++;
 
     netdev_close(port->netdev);
@@ -537,7 +539,7 @@ answer_port_query(const struct dp_netdev_port *port,
 }
 
 static int
-dpif_netdev_port_query_by_number(const struct dpif *dpif, uint32_t port_no,
+dpif_netdev_port_query_by_number(const struct dpif *dpif, odp_port_t port_no,
                                  struct dpif_port *dpif_port)
 {
     struct dp_netdev *dp = get_dp_netdev(dpif);
@@ -566,10 +568,10 @@ dpif_netdev_port_query_by_name(const struct dpif *dpif, const char *devname,
     return error;
 }
 
-static int
+static odp_port_t
 dpif_netdev_get_max_ports(const struct dpif *dpif OVS_UNUSED)
 {
-    return MAX_PORTS;
+    return u32_to_odp(MAX_PORTS);
 }
 
 static void
@@ -599,7 +601,7 @@ dpif_netdev_flow_flush(struct dpif *dpif)
 }
 
 struct dp_netdev_port_state {
-    uint32_t port_no;
+    odp_port_t port_no;
     char *name;
 };
 
@@ -616,17 +618,18 @@ dpif_netdev_port_dump_next(const struct dpif *dpif, void *state_,
 {
     struct dp_netdev_port_state *state = state_;
     struct dp_netdev *dp = get_dp_netdev(dpif);
-    uint32_t port_no;
+    uint32_t port_idx;
 
-    for (port_no = state->port_no; port_no < MAX_PORTS; port_no++) {
-        struct dp_netdev_port *port = dp->ports[port_no];
+    for (port_idx = odp_to_u32(state->port_no);
+         port_idx < MAX_PORTS; port_idx++) {
+        struct dp_netdev_port *port = dp->ports[port_idx];
         if (port) {
             free(state->name);
             state->name = xstrdup(netdev_get_name(port->netdev));
             dpif_port->name = state->name;
             dpif_port->type = port->type;
             dpif_port->port_no = port->port_no;
-            state->port_no = port_no + 1;
+            state->port_no = u32_to_odp(port_idx + 1);
             return 0;
         }
     }
@@ -708,9 +711,7 @@ 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 (odp_to_u32(flow->in_port.odp_port) >= MAX_PORTS) {
         return EINVAL;
     }
 
@@ -898,7 +899,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.in_port.odp_port);
 
         *key = buf.data;
         *key_len = buf.size;
@@ -948,7 +949,7 @@ dpif_netdev_execute(struct dpif *dpif, const struct dpif_execute *execute)
     ofpbuf_reserve(&copy, DP_NETDEV_HEADROOM);
     ofpbuf_put(&copy, execute->packet->data, execute->packet->size);
 
-    flow_extract(&copy, 0, 0, NULL, -1, &key);
+    flow_extract(&copy, 0, 0, NULL, NULL, &key);
     error = dpif_netdev_flow_from_nlattrs(execute->key, execute->key_len,
                                           &key);
     if (!error) {
@@ -1043,11 +1044,13 @@ dp_netdev_port_input(struct dp_netdev *dp, struct dp_netdev_port *port,
 {
     struct dp_netdev_flow *flow;
     struct flow key;
+    union flow_in_port in_port_;
 
     if (packet->size < ETH_HEADER_LEN) {
         return;
     }
-    flow_extract(packet, skb_priority, skb_mark, tnl, port->port_no, &key);
+    in_port_.odp_port = port->port_no;
+    flow_extract(packet, skb_priority, skb_mark, tnl, &in_port_, &key);
     flow = dp_netdev_lookup_flow(dp, &key);
     if (flow) {
         dp_netdev_flow_used(flow, packet);
@@ -1134,7 +1137,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->in_port.odp_port);
         upcall->key = buf->data;
         upcall->key_len = buf->size;
 
diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
index bea822f..6af6733 100644
--- a/lib/dpif-provider.h
+++ b/lib/dpif-provider.h
@@ -127,10 +127,10 @@ struct dpif_class {
      * port number.  Returns EBUSY if caller attempted to choose a port
      * number, and it was in use. */
     int (*port_add)(struct dpif *dpif, struct netdev *netdev,
-                    uint32_t *port_no);
+                    odp_port_t *port_no);
 
     /* Removes port numbered 'port_no' from 'dpif'. */
-    int (*port_del)(struct dpif *dpif, uint32_t port_no);
+    int (*port_del)(struct dpif *dpif, odp_port_t port_no);
 
     /* Queries 'dpif' for a port with the given 'port_no' or 'devname'.
      * If 'port' is not null, stores information about the port into
@@ -139,14 +139,14 @@ struct dpif_class {
      * If 'port' is not null, the caller takes ownership of data in
      * 'port' and must free it with dpif_port_destroy() when it is no
      * longer needed. */
-    int (*port_query_by_number)(const struct dpif *dpif, uint32_t port_no,
+    int (*port_query_by_number)(const struct dpif *dpif, odp_port_t port_no,
                                 struct dpif_port *port);
     int (*port_query_by_name)(const struct dpif *dpif, const char *devname,
                               struct dpif_port *port);
 
     /* Returns one greater than the largest port number accepted in flow
      * actions. */
-    int (*get_max_ports)(const struct dpif *dpif);
+    odp_port_t (*get_max_ports)(const struct dpif *dpif);
 
     /* Returns the Netlink PID value to supply in OVS_ACTION_ATTR_USERSPACE
      * actions as the OVS_USERSPACE_ATTR_PID attribute's value, for use in
@@ -162,7 +162,7 @@ struct dpif_class {
      *
      * A dpif provider that doesn't have meaningful Netlink PIDs can use NULL
      * for this function.  This is equivalent to always returning 0. */
-    uint32_t (*port_get_pid)(const struct dpif *dpif, uint32_t port_no);
+    uint32_t (*port_get_pid)(const struct dpif *dpif, odp_port_t port_no);
 
     /* Attempts to begin dumping the ports in a dpif.  On success, returns 0
      * and initializes '*statep' with any data needed for iteration.  On
diff --git a/lib/dpif.c b/lib/dpif.c
index 6aa52d5..1b5e47b 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -434,18 +434,18 @@ dpif_port_open_type(const char *datapath_type, const char *port_type)
 }
 
 /* Attempts to add 'netdev' as a port on 'dpif'.  If 'port_nop' is
- * non-null and its value is not UINT32_MAX, then attempts to use the
+ * non-null and its value is not ODPP_NONE, then attempts to use the
  * value as the port number.
  *
  * If successful, returns 0 and sets '*port_nop' to the new port's port
  * number (if 'port_nop' is non-null).  On failure, returns a positive
- * errno value and sets '*port_nop' to UINT32_MAX (if 'port_nop' is
+ * errno value and sets '*port_nop' to ODPP_NONE (if 'port_nop' is
  * non-null). */
 int
-dpif_port_add(struct dpif *dpif, struct netdev *netdev, uint32_t *port_nop)
+dpif_port_add(struct dpif *dpif, struct netdev *netdev, odp_port_t *port_nop)
 {
     const char *netdev_name = netdev_get_name(netdev);
-    uint32_t port_no = UINT32_MAX;
+    odp_port_t port_no = ODPP_NONE;
     int error;
 
     COVERAGE_INC(dpif_port_add);
@@ -461,7 +461,7 @@ dpif_port_add(struct dpif *dpif, struct netdev *netdev, uint32_t *port_nop)
     } else {
         VLOG_WARN_RL(&error_rl, "%s: failed to add %s as port: %s",
                      dpif_name(dpif), netdev_name, strerror(error));
-        port_no = UINT32_MAX;
+        port_no = ODPP_NONE;
     }
     if (port_nop) {
         *port_nop = port_no;
@@ -472,7 +472,7 @@ dpif_port_add(struct dpif *dpif, struct netdev *netdev, uint32_t *port_nop)
 /* Attempts to remove 'dpif''s port number 'port_no'.  Returns 0 if successful,
  * otherwise a positive errno value. */
 int
-dpif_port_del(struct dpif *dpif, uint32_t port_no)
+dpif_port_del(struct dpif *dpif, odp_port_t port_no)
 {
     int error;
 
@@ -530,7 +530,7 @@ dpif_port_exists(const struct dpif *dpif, const char *devname)
  * The caller owns the data in 'port' and must free it with
  * dpif_port_destroy() when it is no longer needed. */
 int
-dpif_port_query_by_number(const struct dpif *dpif, uint32_t port_no,
+dpif_port_query_by_number(const struct dpif *dpif, odp_port_t port_no,
                           struct dpif_port *port)
 {
     int error = dpif->dpif_class->port_query_by_number(dpif, port_no, port);
@@ -576,7 +576,7 @@ dpif_port_query_by_name(const struct dpif *dpif, const char *devname,
 
 /* Returns one greater than the maximum port number accepted in flow
  * actions. */
-int
+odp_port_t
 dpif_get_max_ports(const struct dpif *dpif)
 {
     return dpif->dpif_class->get_max_ports(dpif);
@@ -586,7 +586,7 @@ dpif_get_max_ports(const struct dpif *dpif)
  * as the OVS_USERSPACE_ATTR_PID attribute's value, for use in flows whose
  * packets arrived on port 'port_no'.
  *
- * A 'port_no' of UINT32_MAX is a special case: it returns a reserved PID, not
+ * A 'port_no' of ODPP_NONE is a special case: it returns a reserved PID, not
  * allocated to any port, that the client may use for special purposes.
  *
  * The return value is only meaningful when DPIF_UC_ACTION has been enabled in
@@ -595,7 +595,7 @@ dpif_get_max_ports(const struct dpif *dpif)
  * update all of the flows that it installed that contain
  * OVS_ACTION_ATTR_USERSPACE actions. */
 uint32_t
-dpif_port_get_pid(const struct dpif *dpif, uint32_t port_no)
+dpif_port_get_pid(const struct dpif *dpif, odp_port_t port_no)
 {
     return (dpif->dpif_class->port_get_pid
             ? (dpif->dpif_class->port_get_pid)(dpif, port_no)
@@ -607,7 +607,7 @@ dpif_port_get_pid(const struct dpif *dpif, uint32_t port_no)
  * result is null-terminated.  On failure, returns a positive errno value and
  * makes 'name' the empty string. */
 int
-dpif_port_get_name(struct dpif *dpif, uint32_t port_no,
+dpif_port_get_name(struct dpif *dpif, odp_port_t port_no,
                    char *name, size_t name_size)
 {
     struct dpif_port port;
diff --git a/lib/dpif.h b/lib/dpif.h
index fd05b2f..12e5ad0 100644
--- a/lib/dpif.h
+++ b/lib/dpif.h
@@ -377,8 +377,8 @@ int dpif_get_dp_stats(const struct dpif *, struct dpif_dp_stats *);
 
 const char *dpif_port_open_type(const char *datapath_type,
                                 const char *port_type);
-int dpif_port_add(struct dpif *, struct netdev *, uint32_t *port_nop);
-int dpif_port_del(struct dpif *, uint32_t port_no);
+int dpif_port_add(struct dpif *, struct netdev *, odp_port_t *port_nop);
+int dpif_port_del(struct dpif *, odp_port_t port_no);
 
 /* A port within a datapath.
  *
@@ -386,19 +386,19 @@ int dpif_port_del(struct dpif *, uint32_t port_no);
 struct dpif_port {
     char *name;                 /* Network device name, e.g. "eth0". */
     char *type;                 /* Network device type, e.g. "system". */
-    uint32_t port_no;           /* Port number within datapath. */
+    odp_port_t port_no;         /* Port number within datapath. */
 };
 void dpif_port_clone(struct dpif_port *, const struct dpif_port *);
 void dpif_port_destroy(struct dpif_port *);
 bool dpif_port_exists(const struct dpif *dpif, const char *devname);
-int dpif_port_query_by_number(const struct dpif *, uint32_t port_no,
+int dpif_port_query_by_number(const struct dpif *, odp_port_t port_no,
                               struct dpif_port *);
 int dpif_port_query_by_name(const struct dpif *, const char *devname,
                             struct dpif_port *);
-int dpif_port_get_name(struct dpif *, uint32_t port_no,
+int dpif_port_get_name(struct dpif *, odp_port_t port_no,
                        char *name, size_t name_size);
-int dpif_get_max_ports(const struct dpif *);
-uint32_t dpif_port_get_pid(const struct dpif *, uint32_t port_no);
+odp_port_t dpif_get_max_ports(const struct dpif *);
+uint32_t dpif_port_get_pid(const struct dpif *, odp_port_t port_no);
 
 struct dpif_port_dump {
     const struct dpif *dpif;
diff --git a/lib/flow.c b/lib/flow.c
index d38e3ab..cbb32c2 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -337,7 +337,7 @@ invalid:
 }
 
 /* Initializes 'flow' members from 'packet', 'skb_priority', 'tnl', and
- * 'ofp_in_port'.
+ * 'in_port'.
  *
  * Initializes 'packet' header pointers as follows:
  *
@@ -357,7 +357,7 @@ invalid:
  */
 void
 flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t skb_mark,
-             const struct flow_tnl *tnl, uint16_t ofp_in_port,
+             const struct flow_tnl *tnl, const union flow_in_port *in_port,
              struct flow *flow)
 {
     struct ofpbuf b = *packet;
@@ -371,7 +371,7 @@ flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t skb_mark,
         ovs_assert(tnl != &flow->tunnel);
         flow->tunnel = *tnl;
     }
-    flow->in_port = ofp_in_port;
+    flow->in_port = in_port ? *in_port : flow->in_port;
     flow->skb_priority = skb_priority;
     flow->skb_mark = skb_mark;
 
@@ -498,7 +498,7 @@ flow_get_metadata(const struct flow *flow, struct flow_metadata *fmd)
     fmd->tun_dst = flow->tunnel.ip_dst;
     fmd->metadata = flow->metadata;
     memcpy(fmd->regs, flow->regs, sizeof fmd->regs);
-    fmd->in_port = flow->in_port;
+    fmd->in_port = flow->in_port.ofp_port;
 }
 
 char *
diff --git a/lib/flow.h b/lib/flow.h
index b07b9ed..a5790a6 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -68,6 +68,11 @@ struct flow_tnl {
     uint8_t ip_ttl;
 };
 
+union flow_in_port {           /* Input port union. The port can be either */
+    ofp_port_t   ofp_port;     /* OpenFlow port number or the datapath port */
+    odp_port_t   odp_port;     /* number. */
+};
+
 /*
 * A flow in the network.
 *
@@ -82,14 +87,12 @@ struct flow {
     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. */
+    union flow_in_port in_port; /* Input port union.*/
     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. */
@@ -122,11 +125,12 @@ struct flow_metadata {
     ovs_be32 tun_dst;                /* Tunnel outer IPv4 dst addr */
     ovs_be64 metadata;               /* OpenFlow 1.1+ metadata field. */
     uint32_t regs[FLOW_N_REGS];      /* Registers. */
-    uint16_t in_port;                /* OpenFlow port or zero. */
+    ofp_port_t in_port;              /* OpenFlow port or zero. */
 };
 
 void flow_extract(struct ofpbuf *, uint32_t priority, uint32_t mark,
-                  const struct flow_tnl *, uint16_t in_port, struct flow *);
+                  const struct flow_tnl *, const union flow_in_port *in_port,
+                  struct flow *);
 
 void flow_zero_wildcards(struct flow *, const struct flow_wildcards *);
 void flow_get_metadata(const struct flow *, struct flow_metadata *);
@@ -170,6 +174,50 @@ flow_hash(const struct flow *flow, uint32_t basis)
     return hash_words((const uint32_t *) flow, sizeof *flow / 4, basis);
 }
 
+/* ofp/odp/ofp11 port cast functions. */
+static inline uint16_t ofp_to_u16(const ofp_port_t ofp_port);
+static inline uint32_t odp_to_u32(const odp_port_t odp_port);
+static inline uint32_t ofp11_to_u32(const ofp11_port_t ofp11_port);
+static inline ofp_port_t u16_to_ofp(const uint16_t port);
+static inline odp_port_t u32_to_odp(const uint32_t port);
+static inline ofp11_port_t u32_to_ofp11(const uint32_t port);
+
+static inline uint16_t
+ofp_to_u16(ofp_port_t ofp_port)
+{
+    return (OVS_FORCE uint16_t) ofp_port;
+}
+
+static inline uint32_t
+odp_to_u32(odp_port_t odp_port)
+{
+    return (OVS_FORCE uint32_t) odp_port;
+}
+
+static inline uint32_t
+ofp11_to_u32(ofp11_port_t ofp11_port)
+{
+    return (OVS_FORCE uint32_t) ofp11_port;
+}
+
+static inline ofp_port_t
+u16_to_ofp(uint16_t port)
+{
+    return OFP_PORT_C(port);
+}
+
+static inline odp_port_t
+u32_to_odp(uint32_t port)
+{
+    return ODP_PORT_C(port);
+}
+
+static inline ofp11_port_t
+u32_to_ofp11(uint32_t port)
+{
+    return OFP11_PORT_C(port);
+}
+
 uint32_t flow_hash_in_minimask(const struct flow *, const struct minimask *,
                                uint32_t basis);
 
diff --git a/lib/learn.c b/lib/learn.c
index 606ea9e..0cc562d 100644
--- a/lib/learn.c
+++ b/lib/learn.c
@@ -355,9 +355,9 @@ learn_execute(const struct ofpact_learn *learn, const struct flow *flow,
         case NX_LEARN_DST_OUTPUT:
             if (spec->n_bits <= 16
                 || is_all_zeros(value.u8, sizeof value - 2)) {
-                uint16_t port = ntohs(value.be16[7]);
+                ofp_port_t port = u16_to_ofp(ntohs(value.be16[7]));
 
-                if (port < OFPP_MAX
+                if (ofp_to_u16(port) < ofp_to_u16(OFPP_MAX)
                     || port == OFPP_IN_PORT
                     || port == OFPP_FLOOD
                     || port == OFPP_LOCAL
diff --git a/lib/learning-switch.c b/lib/learning-switch.c
index ab37dcc..c430f31 100644
--- a/lib/learning-switch.c
+++ b/lib/learning-switch.c
@@ -48,7 +48,7 @@ VLOG_DEFINE_THIS_MODULE(learning_switch);
 
 struct lswitch_port {
     struct hmap_node hmap_node; /* Hash node for port number. */
-    uint16_t port_no;           /* OpenFlow port number, in host byte order. */
+    ofp_port_t port_no;         /* OpenFlow port number, in host byte order. */
     uint32_t queue_id;          /* OpenFlow queue number. */
 };
 
@@ -460,26 +460,27 @@ process_switch_features(struct lswitch *sw, struct ofp_header *oh)
         if (lp && hmap_node_is_null(&lp->hmap_node)) {
             lp->port_no = port.port_no;
             hmap_insert(&sw->queue_numbers, &lp->hmap_node,
-                        hash_int(lp->port_no, 0));
+                        hash_int(ofp_to_u16(lp->port_no), 0));
         }
     }
     return 0;
 }
 
-static uint16_t
+static ofp_port_t
 lswitch_choose_destination(struct lswitch *sw, const struct flow *flow)
 {
-    uint16_t out_port;
+    ofp_port_t out_port;
 
     /* 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.ofp_port != flow->in_port) {
+        if (mac_entry_is_new(mac)
+            || mac->port.ofp_port != flow->in_port.ofp_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->in_port.ofp_port);
 
-            mac->port.ofp_port = flow->in_port;
+            mac->port.ofp_port = flow->in_port.ofp_port;
             mac_learning_changed(sw->ml, mac);
         }
     }
@@ -496,7 +497,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.ofp_port;
-            if (out_port == flow->in_port) {
+            if (out_port == flow->in_port.ofp_port) {
                 /* Don't send a packet back out its input port. */
                 return OFPP_NONE;
             }
@@ -512,11 +513,11 @@ lswitch_choose_destination(struct lswitch *sw, const struct flow *flow)
 }
 
 static uint32_t
-get_queue_id(const struct lswitch *sw, uint16_t in_port)
+get_queue_id(const struct lswitch *sw, ofp_port_t in_port)
 {
     const struct lswitch_port *port;
 
-    HMAP_FOR_EACH_WITH_HASH (port, hmap_node, hash_int(in_port, 0),
+    HMAP_FOR_EACH_WITH_HASH (port, hmap_node, hash_int(ofp_to_u16(in_port), 0),
                              &sw->queue_numbers) {
         if (port->port_no == in_port) {
             return port->queue_id;
@@ -531,7 +532,7 @@ process_packet_in(struct lswitch *sw, const struct ofp_header *oh)
 {
     struct ofputil_packet_in pi;
     uint32_t queue_id;
-    uint16_t out_port;
+    ofp_port_t out_port;
 
     uint64_t ofpacts_stub[64 / 8];
     struct ofpbuf ofpacts;
@@ -541,6 +542,7 @@ process_packet_in(struct lswitch *sw, const struct ofp_header *oh)
 
     struct ofpbuf pkt;
     struct flow flow;
+    union flow_in_port in_port_;
 
     error = ofputil_decode_packet_in(&pi, oh);
     if (error) {
@@ -558,7 +560,8 @@ 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);
+    in_port_.ofp_port = pi.fmd.in_port;
+    flow_extract(&pkt, 0, 0, NULL, &in_port_, &flow);
     flow.tunnel.tun_id = pi.fmd.tun_id;
 
     /* Choose output port. */
@@ -569,7 +572,8 @@ process_packet_in(struct lswitch *sw, const struct ofp_header *oh)
     ofpbuf_use_stack(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
     if (out_port == OFPP_NONE) {
         /* No actions. */
-    } else if (queue_id == UINT32_MAX || out_port >= OFPP_MAX) {
+    } else if (queue_id == UINT32_MAX
+               || ofp_to_u16(out_port) >= ofp_to_u16(OFPP_MAX)) {
         ofpact_put_OUTPUT(&ofpacts)->port = out_port;
     } else {
         struct ofpact_enqueue *enqueue = ofpact_put_ENQUEUE(&ofpacts);
diff --git a/lib/mac-learning.h b/lib/mac-learning.h
index 1cbacfe..9feca00 100644
--- a/lib/mac-learning.h
+++ b/lib/mac-learning.h
@@ -49,7 +49,7 @@ struct mac_entry {
     /* Learned port. */
     union {
         void *p;
-        uint16_t ofp_port;
+        ofp_port_t ofp_port;
     } port;
 };
 
diff --git a/lib/match.c b/lib/match.c
index 512253e..4ee8ed6 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -271,10 +271,10 @@ match_set_tun_flags_masked(struct match *match, uint16_t flags, uint16_t mask)
 }
 
 void
-match_set_in_port(struct match *match, uint16_t ofp_port)
+match_set_in_port(struct match *match, ofp_port_t ofp_port)
 {
-    match->wc.masks.in_port = UINT16_MAX;
-    match->flow.in_port = ofp_port;
+    match->wc.masks.in_port.ofp_port = OFPP_NONE;
+    match->flow.in_port.ofp_port = ofp_port;
 }
 
 void
@@ -916,9 +916,9 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
                       ntohll(f->metadata), ntohll(wc->masks.metadata));
         break;
     }
-    if (wc->masks.in_port) {
+    if (wc->masks.in_port.ofp_port) {
         ds_put_cstr(s, "in_port=");
-        ofputil_format_port(f->in_port, s);
+        ofputil_format_port(f->in_port.ofp_port, s);
         ds_put_char(s, ',');
     }
     if (wc->masks.vlan_tci) {
diff --git a/lib/match.h b/lib/match.h
index d435aa4..0ea1f2d 100644
--- a/lib/match.h
+++ b/lib/match.h
@@ -60,7 +60,7 @@ void 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);
 void 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);
-void match_set_in_port(struct match *, uint16_t ofp_port);
+void match_set_in_port(struct match *, ofp_port_t ofp_port);
 void match_set_skb_mark(struct match *, uint32_t skb_mark);
 void match_set_skb_priority(struct match *, uint32_t skb_priority);
 void match_set_dl_type(struct match *, ovs_be16);
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index f9e044d..0677202 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -698,7 +698,7 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
         return !wc->masks.metadata;
     case MFF_IN_PORT:
     case MFF_IN_PORT_OXM:
-        return !wc->masks.in_port;
+        return !wc->masks.in_port.ofp_port;
     case MFF_SKB_PRIORITY:
         return !wc->masks.skb_priority;
     case MFF_SKB_MARK:
@@ -937,7 +937,7 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
         return true;
 
     case MFF_IN_PORT_OXM: {
-        uint16_t port;
+        ofp_port_t port;
         return !ofputil_port_from_ofp11(value->be32, &port);
     }
 
@@ -1011,11 +1011,10 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
         break;
 
     case MFF_IN_PORT:
-        value->be16 = htons(flow->in_port);
+        value->be16 = htons(ofp_to_u16(flow->in_port.ofp_port));
         break;
-
     case MFF_IN_PORT_OXM:
-        value->be32 = ofputil_port_to_ofp11(flow->in_port);
+        value->be32 = ofputil_port_to_ofp11(flow->in_port.ofp_port);
         break;
 
     case MFF_SKB_PRIORITY:
@@ -1198,11 +1197,11 @@ mf_set_value(const struct mf_field *mf,
         break;
 
     case MFF_IN_PORT:
-        match_set_in_port(match, ntohs(value->be16));
+        match_set_in_port(match, u16_to_ofp(ntohs(value->be16)));
         break;
 
     case MFF_IN_PORT_OXM: {
-        uint16_t port;
+        ofp_port_t port;
         ofputil_port_from_ofp11(value->be32, &port);
         match_set_in_port(match, port);
         break;
@@ -1387,13 +1386,13 @@ mf_set_flow_value(const struct mf_field *mf,
         break;
 
     case MFF_IN_PORT:
-        flow->in_port = ntohs(value->be16);
+        flow->in_port.ofp_port = u16_to_ofp(ntohs(value->be16));
         break;
 
     case MFF_IN_PORT_OXM: {
-        uint16_t port;
+        ofp_port_t port;
         ofputil_port_from_ofp11(value->be32, &port);
-        flow->in_port = port;
+        flow->in_port.ofp_port = port;
         break;
     }
 
@@ -1594,8 +1593,8 @@ mf_set_wild(const struct mf_field *mf, struct match *match)
 
     case MFF_IN_PORT:
     case MFF_IN_PORT_OXM:
-        match->flow.in_port = 0;
-        match->wc.masks.in_port = 0;
+        match->flow.in_port.ofp_port = 0;
+        match->wc.masks.in_port.ofp_port = 0;
         break;
 
     case MFF_SKB_PRIORITY:
@@ -2012,7 +2011,7 @@ mf_random_value(const struct mf_field *mf, union mf_value *value)
         break;
 
     case MFF_IN_PORT_OXM:
-        value->be32 = ofputil_port_to_ofp11(ntohs(value->be16));
+        value->be32 = ofputil_port_to_ofp11(u16_to_ofp(ntohs(value->be16)));
         break;
 
     case MFF_IPV6_LABEL:
@@ -2203,12 +2202,12 @@ static char *
 mf_from_ofp_port_string(const struct mf_field *mf, const char *s,
                         ovs_be16 *valuep, ovs_be16 *maskp)
 {
-    uint16_t port;
+    ofp_port_t port;
 
     ovs_assert(mf->n_bytes == sizeof(ovs_be16));
 
     if (ofputil_port_from_string(s, &port)) {
-        *valuep = htons(port);
+        *valuep = htons(ofp_to_u16(port));
         *maskp = htons(UINT16_MAX);
         return NULL;
     }
@@ -2219,7 +2218,7 @@ static char *
 mf_from_ofp_port_string32(const struct mf_field *mf, const char *s,
                           ovs_be32 *valuep, ovs_be32 *maskp)
 {
-    uint16_t port;
+    ofp_port_t port;
 
     ovs_assert(mf->n_bytes == sizeof(ovs_be32));
     if (ofputil_port_from_string(s, &port)) {
@@ -2475,7 +2474,7 @@ mf_format(const struct mf_field *mf,
     switch (mf->string) {
     case MFS_OFP_PORT_OXM:
         if (!mask) {
-            uint16_t port;
+            ofp_port_t port;
             ofputil_port_from_ofp11(value->be32, &port);
             ofputil_format_port(port, s);
             break;
@@ -2483,7 +2482,7 @@ mf_format(const struct mf_field *mf,
         /* fall through */
     case MFS_OFP_PORT:
         if (!mask) {
-            ofputil_format_port(ntohs(value->be16), s);
+            ofputil_format_port(u16_to_ofp(ntohs(value->be16)), s);
             break;
         }
         /* fall through */
diff --git a/lib/netlink.c b/lib/netlink.c
index c8e5905..8353f83 100644
--- a/lib/netlink.c
+++ b/lib/netlink.c
@@ -295,6 +295,16 @@ nl_msg_put_be64(struct ofpbuf *msg, uint16_t type, ovs_be64 value)
     nl_msg_put_unspec(msg, type, &value, sizeof value);
 }
 
+/* Appends a Netlink attribute of the given 'type' and the given odp_port_t
+ * 'value' to 'msg'. */
+void
+nl_msg_put_odp_port(struct ofpbuf *msg, uint16_t type, odp_port_t value)
+{
+    uint32_t value_ = (OVS_FORCE uint32_t) value;
+    nl_msg_put_unspec(msg, type, &value_, sizeof value);
+}
+
+
 /* Appends a Netlink attribute of the given 'type' and the given
  * null-terminated string 'value' to 'msg'. */
 void
@@ -570,6 +580,15 @@ nl_attr_get_be64(const struct nlattr *nla)
     return get_32aligned_be64(x);
 }
 
+/* Returns the 32-bit odp_port_t value in 'nla''s payload.
+ *
+ * Asserts that 'nla''s payload is at least 4 bytes long. */
+odp_port_t
+nl_attr_get_odp_port(const struct nlattr *nla)
+{
+    return ODP_PORT_C(NL_ATTR_GET_AS(nla, uint32_t));
+}
+
 /* Returns the null-terminated string value in 'nla''s payload.
  *
  * Asserts that 'nla''s payload contains a null-terminated string. */
diff --git a/lib/netlink.h b/lib/netlink.h
index a5c129a..afe2277 100644
--- a/lib/netlink.h
+++ b/lib/netlink.h
@@ -68,6 +68,7 @@ void nl_msg_put_u64(struct ofpbuf *, uint16_t type, uint64_t value);
 void nl_msg_put_be16(struct ofpbuf *, uint16_t type, ovs_be16 value);
 void nl_msg_put_be32(struct ofpbuf *, uint16_t type, ovs_be32 value);
 void nl_msg_put_be64(struct ofpbuf *, uint16_t type, ovs_be64 value);
+void nl_msg_put_odp_port(struct ofpbuf *, uint16_t type, odp_port_t value);
 void nl_msg_put_string(struct ofpbuf *, uint16_t type, const char *value);
 
 size_t nl_msg_start_nested(struct ofpbuf *, uint16_t type);
@@ -170,6 +171,7 @@ uint64_t nl_attr_get_u64(const struct nlattr *);
 ovs_be16 nl_attr_get_be16(const struct nlattr *);
 ovs_be32 nl_attr_get_be32(const struct nlattr *);
 ovs_be64 nl_attr_get_be64(const struct nlattr *);
+odp_port_t nl_attr_get_odp_port(const struct nlattr *);
 const char *nl_attr_get_string(const struct nlattr *);
 void nl_attr_get_nested(const struct nlattr *, struct ofpbuf *);
 
diff --git a/lib/nx-match.c b/lib/nx-match.c
index ecdaa65..8bdd8ec 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -568,12 +568,12 @@ 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.in_port.ofp_port) {
+        ofp_port_t in_port = flow->in_port.ofp_port;
         if (oxm) {
             nxm_put_32(b, OXM_OF_IN_PORT, ofputil_port_to_ofp11(in_port));
         } else {
-            nxm_put_16(b, NXM_OF_IN_PORT, htons(in_port));
+            nxm_put_16(b, NXM_OF_IN_PORT, htons(ofp_to_u16(in_port)));
         }
     }
 
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 588b3b6..6086fdb 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -1072,7 +1072,7 @@ odp_flow_key_format(const struct nlattr *key, size_t key_len, struct ds *ds)
         }
         if (left) {
             int i;
-            
+
             if (left == key_len) {
                 ds_put_cstr(ds, "<empty>");
             }
@@ -1553,14 +1553,14 @@ ovs_to_odp_frag(uint8_t nw_frag)
 /* Appends a representation of 'flow' as OVS_KEY_ATTR_* attributes to 'buf'.
  * 'flow->in_port' is ignored (since it is likely to be an OpenFlow port
  * number rather than a datapath port number).  Instead, if 'odp_in_port'
- * is anything other than OVSP_NONE, it is included in 'buf' as the input
+ * is anything other than ODPP_NONE, it is included in 'buf' as the input
  * port.
  *
  * 'buf' must have at least ODPUTIL_FLOW_KEY_BYTES bytes of space, or be
  * capable of being expanded to allow for that much space. */
 void
 odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow,
-                       uint32_t odp_in_port)
+                       odp_port_t odp_in_port)
 {
     struct ovs_key_ethernet *eth_key;
     size_t encap;
@@ -1577,8 +1577,8 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow,
         nl_msg_put_u32(buf, OVS_KEY_ATTR_SKB_MARK, flow->skb_mark);
     }
 
-    if (odp_in_port != OVSP_NONE) {
-        nl_msg_put_u32(buf, OVS_KEY_ATTR_IN_PORT, odp_in_port);
+    if (odp_in_port != ODPP_NONE) {
+        nl_msg_put_odp_port(buf, OVS_KEY_ATTR_IN_PORT, odp_in_port);
     }
 
     eth_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ETHERNET,
@@ -2109,10 +2109,11 @@ 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->in_port.odp_port
+            = nl_attr_get_odp_port(attrs[OVS_KEY_ATTR_IN_PORT]);
         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IN_PORT;
     } else {
-        flow->in_port = OVSP_NONE;
+        flow->in_port.odp_port = ODPP_NONE;
     }
 
     /* Ethernet header. */
diff --git a/lib/odp-util.h b/lib/odp-util.h
index 6213418..7844475 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -33,7 +33,8 @@ struct nlattr;
 struct ofpbuf;
 struct simap;
 
-#define OVSP_NONE UINT32_MAX
+#define ODPP_LOCAL ODP_PORT_C(OVSP_LOCAL)
+#define ODPP_NONE  ODP_PORT_C(UINT_MAX)
 
 void format_odp_actions(struct ds *, const struct nlattr *odp_actions,
                         size_t actions_len);
@@ -95,7 +96,7 @@ int odp_flow_key_from_string(const char *s, const struct simap *port_names,
                              struct ofpbuf *);
 
 void odp_flow_key_from_flow(struct ofpbuf *, const struct flow *,
-                            uint32_t odp_in_port);
+                            odp_port_t odp_in_port);
 
 uint32_t odp_flow_key_hash(const struct nlattr *, size_t);
 
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index c9e000f..45d8601 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -42,7 +42,7 @@ output_from_openflow10(const struct ofp10_action_output *oao,
     struct ofpact_output *output;
 
     output = ofpact_put_OUTPUT(out);
-    output->port = ntohs(oao->port);
+    output->port = u16_to_ofp(ntohs(oao->port));
     output->max_len = ntohs(oao->max_len);
 
     return ofputil_check_output_port(output->port, OFPP_MAX);
@@ -55,9 +55,10 @@ enqueue_from_openflow10(const struct ofp10_action_enqueue *oae,
     struct ofpact_enqueue *enqueue;
 
     enqueue = ofpact_put_ENQUEUE(out);
-    enqueue->port = ntohs(oae->port);
+    enqueue->port = u16_to_ofp(ntohs(oae->port));
     enqueue->queue = ntohl(oae->queue_id);
-    if (enqueue->port >= OFPP_MAX && enqueue->port != OFPP_IN_PORT
+    if (ofp_to_u16(enqueue->port) >= ofp_to_u16(OFPP_MAX)
+        && enqueue->port != OFPP_IN_PORT
         && enqueue->port != OFPP_LOCAL) {
         return OFPERR_OFPBAC_BAD_OUT_PORT;
     }
@@ -72,7 +73,7 @@ resubmit_from_openflow(const struct nx_action_resubmit *nar,
 
     resubmit = ofpact_put_RESUBMIT(out);
     resubmit->ofpact.compat = OFPUTIL_NXAST_RESUBMIT;
-    resubmit->in_port = ntohs(nar->in_port);
+    resubmit->in_port = u16_to_ofp(ntohs(nar->in_port));
     resubmit->table_id = 0xff;
 }
 
@@ -88,7 +89,7 @@ resubmit_table_from_openflow(const struct nx_action_resubmit *nar,
 
     resubmit = ofpact_put_RESUBMIT(out);
     resubmit->ofpact.compat = OFPUTIL_NXAST_RESUBMIT_TABLE;
-    resubmit->in_port = ntohs(nar->in_port);
+    resubmit->in_port = u16_to_ofp(ntohs(nar->in_port));
     resubmit->table_id = nar->table;
     return 0;
 }
@@ -1142,8 +1143,8 @@ exit:
 }
 
 static enum ofperr
-ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports,
-               ovs_be16 *dl_type)
+ofpact_check__(const struct ofpact *a, const struct flow *flow,
+               ofp_port_t max_ports, ovs_be16 *dl_type)
 {
     const struct ofpact_enqueue *enqueue;
 
@@ -1157,7 +1158,8 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports,
 
     case OFPACT_ENQUEUE:
         enqueue = ofpact_get_ENQUEUE(a);
-        if (enqueue->port >= max_ports && enqueue->port != OFPP_IN_PORT
+        if (ofp_to_u16(enqueue->port) >= ofp_to_u16(max_ports)
+            && enqueue->port != OFPP_IN_PORT
             && enqueue->port != OFPP_LOCAL) {
             return OFPERR_OFPBAC_BAD_OUT_PORT;
         }
@@ -1240,7 +1242,7 @@ ofpact_check__(const struct ofpact *a, const struct flow *flow, int max_ports,
  * switch with no more than 'max_ports' ports. */
 enum ofperr
 ofpacts_check(const struct ofpact ofpacts[], size_t ofpacts_len,
-              const struct flow *flow, int max_ports)
+              const struct flow *flow, ofp_port_t max_ports)
 {
     const struct ofpact *a;
     ovs_be16 dl_type = flow->dl_type;
@@ -1339,7 +1341,7 @@ ofpact_resubmit_to_nxast(const struct ofpact_resubmit *resubmit,
         nar = ofputil_put_NXAST_RESUBMIT_TABLE(out);
         nar->table = resubmit->table_id;
     }
-    nar->in_port = htons(resubmit->in_port);
+    nar->in_port = htons(ofp_to_u16(resubmit->in_port));
 }
 
 static void
@@ -1574,7 +1576,7 @@ ofpact_output_to_openflow10(const struct ofpact_output *output,
     struct ofp10_action_output *oao;
 
     oao = ofputil_put_OFPAT10_OUTPUT(out);
-    oao->port = htons(output->port);
+    oao->port = htons(ofp_to_u16(output->port));
     oao->max_len = htons(output->max_len);
 }
 
@@ -1585,7 +1587,7 @@ ofpact_enqueue_to_openflow10(const struct ofpact_enqueue *enqueue,
     struct ofp10_action_enqueue *oae;
 
     oae = ofputil_put_OFPAT10_ENQUEUE(out);
-    oae->port = htons(enqueue->port);
+    oae->port = htons(ofp_to_u16(enqueue->port));
     oae->queue_id = htonl(enqueue->queue);
 }
 
@@ -1929,7 +1931,7 @@ ofpacts_put_openflow11_instructions(const struct ofpact ofpacts[],
 
 /* Returns true if 'action' outputs to 'port', false otherwise. */
 static bool
-ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port)
+ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port)
 {
     switch (ofpact->type) {
     case OFPACT_OUTPUT:
@@ -1983,7 +1985,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, uint16_t port)
  * to 'port', false otherwise. */
 bool
 ofpacts_output_to_port(const struct ofpact *ofpacts, size_t ofpacts_len,
-                       uint16_t port)
+                       ofp_port_t port)
 {
     const struct ofpact *a;
 
@@ -2064,12 +2066,12 @@ ofpact_format(const struct ofpact *a, struct ds *s)
     const struct ofpact_metadata *metadata;
     const struct ofpact_tunnel *tunnel;
     const struct ofpact_sample *sample;
-    uint16_t port;
+    ofp_port_t port;
 
     switch (a->type) {
     case OFPACT_OUTPUT:
         port = ofpact_get_OUTPUT(a)->port;
-        if (port < OFPP_MAX) {
+        if (ofp_to_u16(port) < ofp_to_u16(OFPP_MAX)) {
             ds_put_format(s, "output:%"PRIu16, port);
         } else {
             ofputil_format_port(port, s);
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index 4e7fb5c..4fc40b3 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -198,7 +198,7 @@ struct ofpact_null {
  * Used for OFPAT10_OUTPUT. */
 struct ofpact_output {
     struct ofpact ofpact;
-    uint16_t port;              /* Output port. */
+    ofp_port_t port;            /* Output port. */
     uint16_t max_len;           /* Max send len, for port OFPP_CONTROLLER. */
 };
 
@@ -217,7 +217,7 @@ struct ofpact_controller {
  * Used for OFPAT10_ENQUEUE. */
 struct ofpact_enqueue {
     struct ofpact ofpact;
-    uint16_t port;
+    ofp_port_t port;
     uint32_t queue;
 };
 
@@ -247,7 +247,7 @@ struct ofpact_bundle {
 
     /* Slaves for output. */
     unsigned int n_slaves;
-    uint16_t slaves[];
+    ofp_port_t slaves[];
 };
 
 /* OFPACT_SET_VLAN_VID.
@@ -379,7 +379,7 @@ struct ofpact_metadata {
  * Used for NXAST_RESUBMIT, NXAST_RESUBMIT_TABLE. */
 struct ofpact_resubmit {
     struct ofpact ofpact;
-    uint16_t in_port;
+    ofp_port_t in_port;
     uint8_t table_id;
 };
 
@@ -493,7 +493,7 @@ enum ofperr ofpacts_pull_openflow11_instructions(struct ofpbuf *openflow,
                                                  uint8_t table_id,
                                                  struct ofpbuf *ofpacts);
 enum ofperr ofpacts_check(const struct ofpact[], size_t ofpacts_len,
-                          const struct flow *, int max_ports);
+                          const struct flow *, ofp_port_t max_ports);
 enum ofperr ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len);
 
 /* Converting ofpacts to OpenFlow. */
@@ -507,7 +507,7 @@ void ofpacts_put_openflow11_instructions(const struct ofpact[],
 
 /* Working with ofpacts. */
 bool ofpacts_output_to_port(const struct ofpact[], size_t ofpacts_len,
-                            uint16_t port);
+                            ofp_port_t port);
 bool ofpacts_equal(const struct ofpact a[], size_t a_len,
                    const struct ofpact b[], size_t b_len);
 
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 1c5c761..1890050 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -135,7 +135,7 @@ parse_enqueue(char *arg, struct ofpbuf *ofpacts)
     }
 
     enqueue = ofpact_put_ENQUEUE(ofpacts);
-    enqueue->port = str_to_u32(port);
+    enqueue->port = u16_to_ofp(str_to_u32(port));
     enqueue->queue = str_to_u32(queue);
 }
 
@@ -152,7 +152,7 @@ parse_output(char *arg, struct ofpbuf *ofpacts)
         struct ofpact_output *output;
 
         output = ofpact_put_OUTPUT(ofpacts);
-        output->port = str_to_u32(arg);
+        output->port = u16_to_ofp(str_to_u32(arg));
         output->max_len = output->port == OFPP_CONTROLLER ? UINT16_MAX : 0;
     }
 }
@@ -650,7 +650,7 @@ str_to_ofpact__(char *pos, char *act, char *arg,
         }
         return false;
     } else {
-        uint16_t port;
+        ofp_port_t port;
         if (ofputil_port_from_string(act, &port)) {
             ofpact_put_OUTPUT(ofpacts)->port = port;
         } else {
@@ -1076,7 +1076,7 @@ parse_flow_monitor_request(struct ofputil_flow_monitor_request *fmr,
             if (!strcmp(name, "table")) {
                 fmr->table_id = str_to_table_id(value);
             } else if (!strcmp(name, "out_port")) {
-                fmr->out_port = atoi(value);
+                fmr->out_port = u16_to_ofp(atoi(value));
             } else if (mf_from_name(name)) {
                 parse_field(mf_from_name(name), value, &fmr->match);
             } else {
@@ -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->in_port.ofp_port) {
+        flow->in_port.ofp_port = OFPP_NONE;
     }
 
 exit:
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index 549616c..42fd9a6 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -62,7 +62,7 @@ ofp_packet_to_string(const void *data, size_t len)
     struct flow flow;
 
     ofpbuf_use_const(&buf, data, len);
-    flow_extract(&buf, 0, 0, NULL, 0, &flow);
+    flow_extract(&buf, 0, 0, NULL, NULL, &flow);
     flow_format(&ds, &flow);
 
     if (buf.l7) {
@@ -204,8 +204,8 @@ compare_ports(const void *a_, const void *b_)
 {
     const struct ofputil_phy_port *a = a_;
     const struct ofputil_phy_port *b = b_;
-    uint16_t ap = a->port_no;
-    uint16_t bp = b->port_no;
+    uint16_t ap = ofp_to_u16(a->port_no);
+    uint16_t bp = ofp_to_u16(b->port_no);
 
     return ap < bp ? -1 : ap > bp;
 }
@@ -585,7 +585,7 @@ static void print_wild(struct ds *string, const char *leader, int is_wild,
 
 static void
 print_wild_port(struct ds *string, const char *leader, int is_wild,
-                int verbosity, uint16_t port)
+                int verbosity, ofp_port_t port)
 {
     if (is_wild && verbosity < 2) {
         return;
@@ -665,7 +665,7 @@ ofp10_match_to_string(const struct ofp10_match *om, int verbosity)
         }
     }
     print_wild_port(&f, "in_port=", w & OFPFW10_IN_PORT, verbosity,
-                    ntohs(om->in_port));
+                    u16_to_ofp(ntohs(om->in_port)));
     print_wild(&f, "dl_vlan=", w & OFPFW10_DL_VLAN, verbosity,
                "%d", ntohs(om->dl_vlan));
     print_wild(&f, "dl_vlan_pcp=", w & OFPFW10_DL_VLAN_PCP, verbosity,
@@ -1167,7 +1167,7 @@ print_port_stat(struct ds *string, const char *leader, uint64_t stat, int more)
 static void
 ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh)
 {
-    uint16_t ofp10_port;
+    ofp_port_t ofp10_port;
     enum ofperr error;
 
     error = ofputil_decode_port_stats_request(oh, &ofp10_port);
@@ -1205,7 +1205,7 @@ ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh,
         }
 
         ds_put_cstr(string, "  port ");
-        if (ps.port_no < 10) {
+        if (ofp_to_u16(ps.port_no) < 10) {
             ds_put_char(string, ' ');
         }
         ofputil_format_port(ps.port_no, string);
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 26da477..8d0a8da 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.in_port.ofp_port = OFPP_NONE;
     }
 
     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.in_port.ofp_port = u16_to_ofp(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.in_port.ofp_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(ofp_to_u16(match->flow.in_port.ofp_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);
@@ -311,7 +311,7 @@ ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch,
     match_init_catchall(match);
 
     if (!(wc & OFPFW11_IN_PORT)) {
-        uint16_t ofp_port;
+        ofp_port_t ofp_port;
         enum ofperr error;
 
         error = ofputil_port_from_ofp11(ofmatch->in_port, &ofp_port);
@@ -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.in_port.ofp_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.in_port.ofp_port);
     }
 
     memcpy(ofmatch->dl_src, match->flow.dl_src, ETH_ADDR_LEN);
@@ -1567,7 +1567,7 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
             fm->idle_timeout = ntohs(ofm->idle_timeout);
             fm->hard_timeout = ntohs(ofm->hard_timeout);
             fm->buffer_id = ntohl(ofm->buffer_id);
-            fm->out_port = ntohs(ofm->out_port);
+            fm->out_port = u16_to_ofp(ntohs(ofm->out_port));
             fm->flags = ntohs(ofm->flags);
         } else if (raw == OFPRAW_NXT_FLOW_MOD) {
             /* Nicira extended flow_mod. */
@@ -1598,7 +1598,7 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
             fm->idle_timeout = ntohs(nfm->idle_timeout);
             fm->hard_timeout = ntohs(nfm->hard_timeout);
             fm->buffer_id = ntohl(nfm->buffer_id);
-            fm->out_port = ntohs(nfm->out_port);
+            fm->out_port = u16_to_ofp(ntohs(nfm->out_port));
             fm->flags = ntohs(nfm->flags);
         } else {
             NOT_REACHED();
@@ -1653,7 +1653,7 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
     case OFPUTIL_P_OF13_OXM: {
         struct ofp11_flow_mod *ofm;
 
-        msg = ofpraw_alloc(OFPRAW_OFPT11_FLOW_MOD, 
+        msg = ofpraw_alloc(OFPRAW_OFPT11_FLOW_MOD,
                            ofputil_protocol_to_ofp_version(protocol),
                            NXM_TYPICAL_LEN + fm->ofpacts_len);
         ofm = ofpbuf_put_zeros(msg, sizeof *ofm);
@@ -1691,7 +1691,7 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
         ofm->hard_timeout = htons(fm->hard_timeout);
         ofm->priority = htons(fm->priority);
         ofm->buffer_id = htonl(fm->buffer_id);
-        ofm->out_port = htons(fm->out_port);
+        ofm->out_port = htons(ofp_to_u16(fm->out_port));
         ofm->flags = htons(fm->flags);
         ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg);
         break;
@@ -1713,7 +1713,7 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
         nfm->hard_timeout = htons(fm->hard_timeout);
         nfm->priority = htons(fm->priority);
         nfm->buffer_id = htonl(fm->buffer_id);
-        nfm->out_port = htons(fm->out_port);
+        nfm->out_port = htons(ofp_to_u16(fm->out_port));
         nfm->flags = htons(fm->flags);
         nfm->match_len = htons(match_len);
         ofpacts_put_openflow10(fm->ofpacts, fm->ofpacts_len, msg);
@@ -1766,7 +1766,7 @@ ofputil_decode_ofpst10_flow_request(struct ofputil_flow_stats_request *fsr,
 {
     fsr->aggregate = aggregate;
     ofputil_match_from_ofp10_match(&ofsr->match, &fsr->match);
-    fsr->out_port = ntohs(ofsr->out_port);
+    fsr->out_port = u16_to_ofp(ntohs(ofsr->out_port));
     fsr->table_id = ofsr->table_id;
     fsr->cookie = fsr->cookie_mask = htonll(0);
 
@@ -1818,7 +1818,7 @@ ofputil_decode_nxst_flow_request(struct ofputil_flow_stats_request *fsr,
     }
 
     fsr->aggregate = aggregate;
-    fsr->out_port = ntohs(nfsr->out_port);
+    fsr->out_port = u16_to_ofp(ntohs(nfsr->out_port));
     fsr->table_id = nfsr->table_id;
 
     return 0;
@@ -1902,7 +1902,7 @@ ofputil_encode_flow_stats_request(const struct ofputil_flow_stats_request *fsr,
         ofsr = ofpbuf_put_zeros(msg, sizeof *ofsr);
         ofputil_match_to_ofp10_match(&fsr->match, &ofsr->match);
         ofsr->table_id = fsr->table_id;
-        ofsr->out_port = htons(fsr->out_port);
+        ofsr->out_port = htons(ofp_to_u16(fsr->out_port));
         break;
     }
 
@@ -1920,7 +1920,7 @@ ofputil_encode_flow_stats_request(const struct ofputil_flow_stats_request *fsr,
                                  fsr->cookie, fsr->cookie_mask);
 
         nfsr = msg->l3;
-        nfsr->out_port = htons(fsr->out_port);
+        nfsr->out_port = htons(ofp_to_u16(fsr->out_port));
         nfsr->match_len = htons(match_len);
         nfsr->table_id = fsr->table_id;
         break;
@@ -2443,7 +2443,7 @@ 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.in_port = match->flow.in_port.ofp_port;
     pin->fmd.tun_id = match->flow.tunnel.tun_id;
     pin->fmd.tun_src = match->flow.tunnel.ip_src;
     pin->fmd.tun_dst = match->flow.tunnel.ip_dst;
@@ -2502,7 +2502,7 @@ ofputil_decode_packet_in(struct ofputil_packet_in *pin,
         pin->packet = opi->data;
         pin->packet_len = b.size;
 
-        pin->fmd.in_port = ntohs(opi->in_port);
+        pin->fmd.in_port = u16_to_ofp(ntohs(opi->in_port));
         pin->reason = opi->reason;
         pin->buffer_id = ntohl(opi->buffer_id);
         pin->total_len = ntohs(opi->total_len);
@@ -2620,7 +2620,7 @@ ofputil_encode_packet_in(const struct ofputil_packet_in *pin,
                                   htonl(0), send_len);
         opi = ofpbuf_put_zeros(packet, offsetof(struct ofp10_packet_in, data));
         opi->total_len = htons(pin->total_len);
-        opi->in_port = htons(pin->fmd.in_port);
+        opi->in_port = htons(ofp_to_u16(pin->fmd.in_port));
         opi->reason = pin->reason;
         opi->buffer_id = htonl(pin->buffer_id);
 
@@ -2737,7 +2737,7 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po,
         const struct ofp10_packet_out *opo = ofpbuf_pull(&b, sizeof *opo);
 
         po->buffer_id = ntohl(opo->buffer_id);
-        po->in_port = ntohs(opo->in_port);
+        po->in_port = u16_to_ofp(ntohs(opo->in_port));
 
         error = ofpacts_pull_openflow10(&b, ntohs(opo->actions_len), ofpacts);
         if (error) {
@@ -2747,7 +2747,8 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po,
         NOT_REACHED();
     }
 
-    if (po->in_port >= OFPP_MAX && po->in_port != OFPP_LOCAL
+    if (ofp_to_u16(po->in_port) >= ofp_to_u16(OFPP_MAX)
+        && po->in_port != OFPP_LOCAL
         && po->in_port != OFPP_NONE && po->in_port != OFPP_CONTROLLER) {
         VLOG_WARN_RL(&bad_ofmsg_rl, "packet-out has bad input port %#"PRIx16,
                      po->in_port);
@@ -2834,7 +2835,7 @@ ofputil_decode_ofp10_phy_port(struct ofputil_phy_port *pp,
 {
     memset(pp, 0, sizeof *pp);
 
-    pp->port_no = ntohs(opp->port_no);
+    pp->port_no = u16_to_ofp(ntohs(opp->port_no));
     memcpy(pp->hw_addr, opp->hw_addr, OFP_ETH_ALEN);
     ovs_strlcpy(pp->name, opp->name, OFP_MAX_PORT_NAME_LEN);
 
@@ -2902,7 +2903,7 @@ ofputil_encode_ofp10_phy_port(const struct ofputil_phy_port *pp,
 {
     memset(opp, 0, sizeof *opp);
 
-    opp->port_no = htons(pp->port_no);
+    opp->port_no = htons(ofp_to_u16(pp->port_no));
     memcpy(opp->hw_addr, pp->hw_addr, ETH_ADDR_LEN);
     ovs_strlcpy(opp->name, pp->name, OFP_MAX_PORT_NAME_LEN);
 
@@ -3312,7 +3313,7 @@ ofputil_decode_port_mod(const struct ofp_header *oh,
     if (raw == OFPRAW_OFPT10_PORT_MOD) {
         const struct ofp10_port_mod *opm = b.data;
 
-        pm->port_no = ntohs(opm->port_no);
+        pm->port_no = u16_to_ofp(ntohs(opm->port_no));
         memcpy(pm->hw_addr, opm->hw_addr, ETH_ADDR_LEN);
         pm->config = ntohl(opm->config) & OFPPC10_ALL;
         pm->mask = ntohl(opm->mask) & OFPPC10_ALL;
@@ -3354,7 +3355,7 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm,
 
         b = ofpraw_alloc(OFPRAW_OFPT10_PORT_MOD, ofp_version, 0);
         opm = ofpbuf_put_zeros(b, sizeof *opm);
-        opm->port_no = htons(pm->port_no);
+        opm->port_no = htons(ofp_to_u16(pm->port_no));
         memcpy(opm->hw_addr, pm->hw_addr, ETH_ADDR_LEN);
         opm->config = htonl(pm->config & OFPPC10_ALL);
         opm->mask = htonl(pm->mask & OFPPC10_ALL);
@@ -3690,7 +3691,7 @@ ofputil_decode_flow_monitor_request(struct ofputil_flow_monitor_request *rq,
 
     rq->id = ntohl(nfmr->id);
     rq->flags = flags;
-    rq->out_port = ntohs(nfmr->out_port);
+    rq->out_port = u16_to_ofp(ntohs(nfmr->out_port));
     rq->table_id = nfmr->table_id;
 
     return nx_pull_match(msg, ntohs(nfmr->match_len), &rq->match, NULL, NULL);
@@ -3715,7 +3716,7 @@ ofputil_append_flow_monitor_request(
     nfmr = ofpbuf_at_assert(msg, start_ofs, sizeof *nfmr);
     nfmr->id = htonl(rq->id);
     nfmr->flags = htons(rq->flags);
-    nfmr->out_port = htons(rq->out_port);
+    nfmr->out_port = htons(ofp_to_u16(rq->out_port));
     nfmr->match_len = htons(match_len);
     nfmr->table_id = rq->table_id;
 }
@@ -3923,7 +3924,7 @@ ofputil_encode_packet_out(const struct ofputil_packet_out *po,
 
         opo = msg->l3;
         opo->buffer_id = htonl(po->buffer_id);
-        opo->in_port = htons(po->in_port);
+        opo->in_port = htons(ofp_to_u16(po->in_port));
         opo->actions_len = htons(msg->size - actions_ofs);
         break;
     }
@@ -4042,22 +4043,22 @@ ofputil_frag_handling_from_string(const char *s, enum ofp_config_flags *flags)
  *
  * See the definition of OFP11_MAX for an explanation of the mapping. */
 enum ofperr
-ofputil_port_from_ofp11(ovs_be32 ofp11_port, uint16_t *ofp10_port)
+ofputil_port_from_ofp11(ovs_be32 ofp11_port, ofp_port_t *ofp10_port)
 {
     uint32_t ofp11_port_h = ntohl(ofp11_port);
 
-    if (ofp11_port_h < OFPP_MAX) {
-        *ofp10_port = ofp11_port_h;
+    if (ofp11_port_h < ofp_to_u16(OFPP_MAX)) {
+        *ofp10_port = u16_to_ofp(ofp11_port_h);
         return 0;
-    } else if (ofp11_port_h >= OFPP11_MAX) {
-        *ofp10_port = ofp11_port_h - OFPP11_OFFSET;
+    } else if (ofp11_port_h >= ofp11_to_u32(OFPP11_MAX)) {
+        *ofp10_port = u16_to_ofp(ofp11_port_h - OFPP11_OFFSET);
         return 0;
     } else {
         *ofp10_port = OFPP_NONE;
         VLOG_WARN_RL(&bad_ofmsg_rl, "port %"PRIu32" is outside the supported "
                      "range 0 through %d or 0x%"PRIx32" through 0x%"PRIx32,
-                     ofp11_port_h, OFPP_MAX - 1,
-                     (uint32_t) OFPP11_MAX, UINT32_MAX);
+                     ofp11_port_h, ofp_to_u16(OFPP_MAX) - 1,
+                     ofp11_to_u32(OFPP11_MAX), UINT32_MAX);
         return OFPERR_OFPBAC_BAD_OUT_PORT;
     }
 }
@@ -4067,18 +4068,18 @@ ofputil_port_from_ofp11(ovs_be32 ofp11_port, uint16_t *ofp10_port)
  *
  * See the definition of OFP11_MAX for an explanation of the mapping. */
 ovs_be32
-ofputil_port_to_ofp11(uint16_t ofp10_port)
+ofputil_port_to_ofp11(ofp_port_t ofp10_port)
 {
-    return htonl(ofp10_port < OFPP_MAX
-                 ? ofp10_port
-                 : ofp10_port + OFPP11_OFFSET);
+    return htonl(ofp_to_u16(ofp10_port) < ofp_to_u16(OFPP_MAX)
+                 ? ofp_to_u16(ofp10_port)
+                 : ofp_to_u16(ofp10_port) + OFPP11_OFFSET);
 }
 
 /* Checks that 'port' is a valid output port for the OFPAT10_OUTPUT action, given
  * that the switch will never have more than 'max_ports' ports.  Returns 0 if
  * 'port' is valid, otherwise an OpenFlow return code. */
 enum ofperr
-ofputil_check_output_port(uint16_t port, int max_ports)
+ofputil_check_output_port(ofp_port_t port, ofp_port_t max_ports)
 {
     switch (port) {
     case OFPP_IN_PORT:
@@ -4092,7 +4093,7 @@ ofputil_check_output_port(uint16_t port, int max_ports)
         return 0;
 
     default:
-        if (port < max_ports) {
+        if (ofp_to_u16(port) < ofp_to_u16(max_ports)) {
             return 0;
         }
         return OFPERR_OFPBAC_BAD_OUT_PORT;
@@ -4128,46 +4129,42 @@ ofputil_check_output_port(uint16_t port, int max_ports)
  * of OpenFlow 1.1+ port numbers, mapping those port numbers into the 16-bit
  * range as described in include/openflow/openflow-1.1.h. */
 bool
-ofputil_port_from_string(const char *s, uint16_t *portp)
+ofputil_port_from_string(const char *s, ofp_port_t *portp)
 {
-    unsigned int port32;
+    uint32_t port32;
 
     *portp = 0;
     if (str_to_uint(s, 10, &port32)) {
-        if (port32 < OFPP_MAX) {
-            *portp = port32;
-            return true;
-        } else if (port32 < OFPP_FIRST_RESV) {
+        if (port32 < ofp_to_u16(OFPP_MAX)) {
+            /* Pass. */
+        } else if (port32 < ofp_to_u16(OFPP_FIRST_RESV)) {
             VLOG_WARN("port %u is a reserved OF1.0 port number that will "
                       "be translated to %u when talking to an OF1.1 or "
                       "later controller", port32, port32 + OFPP11_OFFSET);
-            *portp = port32;
-            return true;
-        } else if (port32 <= OFPP_LAST_RESV) {
+        } else if (port32 <= ofp_to_u16(OFPP_LAST_RESV)) {
             struct ds msg;
 
             ds_init(&msg);
-            ofputil_format_port(port32, &msg);
+            ofputil_format_port(u16_to_ofp(port32), &msg);
             VLOG_WARN_ONCE("referring to port %s as %u is deprecated for "
                            "compatibility with future versions of OpenFlow",
                            ds_cstr(&msg), port32);
             ds_destroy(&msg);
-
-            *portp = port32;
-            return true;
-        } else if (port32 < OFPP11_MAX) {
+        } else if (port32 < ofp11_to_u32(OFPP11_MAX)) {
             VLOG_WARN("port %u is outside the supported range 0 through "
                       "%"PRIx16" or 0x%x through 0x%"PRIx32, port32,
-                      UINT16_MAX, (unsigned int) OFPP11_MAX, UINT32_MAX);
+                      UINT16_MAX, ofp11_to_u32(OFPP11_MAX), UINT32_MAX);
             return false;
         } else {
-            *portp = port32 - OFPP11_OFFSET;
-            return true;
+            port32 -= OFPP11_OFFSET;
         }
+
+        *portp = u16_to_ofp(port32);
+        return true;
     } else {
         struct pair {
             const char *name;
-            uint16_t value;
+            ofp_port_t value;
         };
         static const struct pair pairs[] = {
 #define OFPUTIL_NAMED_PORT(NAME) {#NAME, OFPP_##NAME},
@@ -4190,7 +4187,7 @@ ofputil_port_from_string(const char *s, uint16_t *portp)
  * Most ports' string representation is just the port number, but for special
  * ports, e.g. OFPP_LOCAL, it is the name, e.g. "LOCAL". */
 void
-ofputil_format_port(uint16_t port, struct ds *s)
+ofputil_format_port(ofp_port_t port, struct ds *s)
 {
     const char *name;
 
@@ -4531,7 +4528,7 @@ ofputil_parse_key_value(char **stringp, char **keyp, char **valuep)
  * will be for Open Flow version 'ofp_version'. Returns message
  * as a struct ofpbuf. Returns encoded message on success, NULL on error */
 struct ofpbuf *
-ofputil_encode_dump_ports_request(enum ofp_version ofp_version, uint16_t port)
+ofputil_encode_dump_ports_request(enum ofp_version ofp_version, ofp_port_t port)
 {
     struct ofpbuf *request;
 
@@ -4540,7 +4537,7 @@ ofputil_encode_dump_ports_request(enum ofp_version ofp_version, uint16_t port)
         struct ofp10_port_stats_request *req;
         request = ofpraw_alloc(OFPRAW_OFPST10_PORT_REQUEST, ofp_version, 0);
         req = ofpbuf_put_zeros(request, sizeof *req);
-        req->port_no = htons(port);
+        req->port_no = htons(ofp_to_u16(port));
         break;
     }
     case OFP11_VERSION:
@@ -4563,7 +4560,7 @@ static void
 ofputil_port_stats_to_ofp10(const struct ofputil_port_stats *ops,
                             struct ofp10_port_stats *ps10)
 {
-    ps10->port_no = htons(ops->port_no);
+    ps10->port_no = htons(ofp_to_u16(ops->port_no));
     memset(ps10->pad, 0, sizeof ps10->pad);
     put_32aligned_be64(&ps10->rx_packets, htonll(ops->stats.rx_packets));
     put_32aligned_be64(&ps10->tx_packets, htonll(ops->stats.tx_packets));
@@ -4647,7 +4644,7 @@ ofputil_port_stats_from_ofp10(struct ofputil_port_stats *ops,
 {
     memset(ops, 0, sizeof *ops);
 
-    ops->port_no = ntohs(ps10->port_no);
+    ops->port_no = u16_to_ofp(ntohs(ps10->port_no));
     ops->stats.rx_packets = ntohll(get_32aligned_be64(&ps10->rx_packets));
     ops->stats.tx_packets = ntohll(get_32aligned_be64(&ps10->tx_packets));
     ops->stats.rx_bytes = ntohll(get_32aligned_be64(&ps10->rx_bytes));
@@ -4787,7 +4784,7 @@ ofputil_decode_port_stats(struct ofputil_port_stats *ps, struct ofpbuf *msg)
  * Returns 0 if successful, otherwise an OFPERR_* number. */
 enum ofperr
 ofputil_decode_port_stats_request(const struct ofp_header *request,
-                                  uint16_t *ofp10_port)
+                                  ofp_port_t *ofp10_port)
 {
     switch ((enum ofp_version)request->version) {
     case OFP13_VERSION:
@@ -4799,7 +4796,7 @@ ofputil_decode_port_stats_request(const struct ofp_header *request,
 
     case OFP10_VERSION: {
         const struct ofp10_port_stats_request *psr10 = ofpmsg_body(request);
-        *ofp10_port = ntohs(psr10->port_no);
+        *ofp10_port = u16_to_ofp(ntohs(psr10->port_no));
         return 0;
     }
 
@@ -4826,7 +4823,7 @@ ofputil_decode_queue_stats_request(const struct ofp_header *request,
     case OFP10_VERSION: {
         const struct ofp10_queue_stats_request *qsr10 = ofpmsg_body(request);
         oqsr->queue_id = ntohl(qsr10->queue_id);
-        oqsr->port_no = ntohs(qsr10->port_no);
+        oqsr->port_no = u16_to_ofp(ntohs(qsr10->port_no));
         /* OF 1.0 uses OFPP_ALL for OFPP_ANY */
         if (oqsr->port_no == OFPP_ALL) {
             oqsr->port_no = OFPP_ANY;
@@ -4865,7 +4862,8 @@ ofputil_encode_queue_stats_request(enum ofp_version ofp_version,
         req = ofpbuf_put_zeros(request, sizeof *req);
         /* OpenFlow 1.0 needs OFPP_ALL instead of OFPP_ANY */
         req->port_no = htons(oqsr->port_no == OFPP_ANY
-                             ? OFPP_ALL : oqsr->port_no);
+                             ? ofp_to_u16(OFPP_ALL)
+                               : ofp_to_u16(oqsr->port_no));
         req->queue_id = htonl(oqsr->queue_id);
         break;
     }
@@ -4895,7 +4893,7 @@ static enum ofperr
 ofputil_queue_stats_from_ofp10(struct ofputil_queue_stats *oqs,
                                const struct ofp10_queue_stats *qs10)
 {
-    oqs->port_no = ntohs(qs10->port_no);
+    oqs->port_no = u16_to_ofp(ntohs(qs10->port_no));
     oqs->queue_id = ntohl(qs10->queue_id);
     oqs->stats.tx_bytes = ntohll(get_32aligned_be64(&qs10->tx_bytes));
     oqs->stats.tx_packets = ntohll(get_32aligned_be64(&qs10->tx_packets));
@@ -5000,7 +4998,7 @@ static void
 ofputil_queue_stats_to_ofp10(const struct ofputil_queue_stats *oqs,
                              struct ofp10_queue_stats *qs10)
 {
-    qs10->port_no = htons(oqs->port_no);
+    qs10->port_no = htons(ofp_to_u16(oqs->port_no));
     memset(qs10->pad, 0, sizeof qs10->pad);
     qs10->queue_id = htonl(oqs->queue_id);
     put_32aligned_be64(&qs10->tx_bytes, htonll(oqs->stats.tx_bytes));
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index 1c8d6cd..42ab88b 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -32,12 +32,14 @@
 struct ofpbuf;
 
 /* Port numbers. */
-enum ofperr ofputil_port_from_ofp11(ovs_be32 ofp11_port, uint16_t *ofp10_port);
-ovs_be32 ofputil_port_to_ofp11(uint16_t ofp10_port);
+enum ofperr ofputil_port_from_ofp11(ovs_be32 ofp11_port,
+                                    ofp_port_t *ofp10_port);
+ovs_be32 ofputil_port_to_ofp11(ofp_port_t ofp10_port);
 
-enum ofperr ofputil_check_output_port(uint16_t ofp_port, int max_ports);
-bool ofputil_port_from_string(const char *, uint16_t *portp);
-void ofputil_format_port(uint16_t port, struct ds *);
+enum ofperr ofputil_check_output_port(ofp_port_t ofp_port,
+                                      ofp_port_t max_ports);
+bool ofputil_port_from_string(const char *, ofp_port_t *portp);
+void ofputil_format_port(ofp_port_t port, struct ds *);
 
 /* Converting OFPFW10_NW_SRC_MASK and OFPFW10_NW_DST_MASK wildcard bit counts
  * to and from IP bitmasks. */
@@ -219,7 +221,7 @@ struct ofputil_flow_mod {
     uint16_t idle_timeout;
     uint16_t hard_timeout;
     uint32_t buffer_id;
-    uint16_t out_port;
+    ofp_port_t out_port;
     uint16_t flags;
     struct ofpact *ofpacts;     /* Series of "struct ofpact"s. */
     size_t ofpacts_len;         /* Length of ofpacts, in bytes. */
@@ -241,7 +243,7 @@ struct ofputil_flow_stats_request {
     struct match match;
     ovs_be64 cookie;
     ovs_be64 cookie_mask;
-    uint16_t out_port;
+    ofp_port_t out_port;
     uint8_t table_id;
 };
 
@@ -350,7 +352,7 @@ struct ofputil_packet_out {
     const void *packet;         /* Packet data, if buffer_id == UINT32_MAX. */
     size_t packet_len;          /* Length of packet data in bytes. */
     uint32_t buffer_id;         /* Buffer id or UINT32_MAX if no buffer. */
-    uint16_t in_port;           /* Packet's input port. */
+    ofp_port_t in_port;         /* Packet's input port. */
     struct ofpact *ofpacts;     /* Actions. */
     size_t ofpacts_len;         /* Size of ofpacts in bytes. */
 };
@@ -390,7 +392,7 @@ enum ofputil_port_state {
 
 /* Abstract ofp10_phy_port or ofp11_port. */
 struct ofputil_phy_port {
-    uint16_t port_no;
+    ofp_port_t port_no;
     uint8_t hw_addr[OFP_ETH_ALEN];
     char name[OFP_MAX_PORT_NAME_LEN];
     enum ofputil_port_config config;
@@ -498,7 +500,7 @@ struct ofpbuf *ofputil_encode_port_status(const struct ofputil_port_status *,
 
 /* Abstract ofp_port_mod. */
 struct ofputil_port_mod {
-    uint16_t port_no;
+    ofp_port_t port_no;
     uint8_t hw_addr[OFP_ETH_ALEN];
     enum ofputil_port_config config;
     enum ofputil_port_config mask;
@@ -535,7 +537,7 @@ struct ofpbuf *ofputil_encode_table_stats_reply(
 struct ofputil_flow_monitor_request {
     uint32_t id;
     enum nx_flow_monitor_flags flags;
-    uint16_t out_port;
+    ofp_port_t out_port;
     uint8_t table_id;
     struct match match;
 };
@@ -677,7 +679,7 @@ void *ofputil_put_action(enum ofputil_action_code, struct ofpbuf *buf);
 #define OFP_ACTION_ALIGN 8      /* Alignment of ofp_actions. */
 
 enum ofperr validate_actions(const union ofp_action *, size_t n_actions,
-                             const struct flow *, int max_ports);
+                             const struct flow *, ofp_port_t max_ports);
 bool action_outputs_to_port(const union ofp_action *, ovs_be16 port);
 
 enum ofperr ofputil_pull_actions(struct ofpbuf *, unsigned int actions_len,
@@ -691,23 +693,23 @@ union ofp_action *ofputil_actions_clone(const union ofp_action *, size_t n);
 bool ofputil_parse_key_value(char **stringp, char **keyp, char **valuep);
 
 struct ofputil_port_stats {
-    uint16_t port_no;
+    ofp_port_t port_no;
     struct netdev_stats stats;
     uint32_t duration_sec;      /* UINT32_MAX if unknown. */
     uint32_t duration_nsec;
 };
 
 struct ofpbuf *ofputil_encode_dump_ports_request(enum ofp_version ofp_version,
-                                                 uint16_t port);
+                                                 ofp_port_t port);
 void ofputil_append_port_stat(struct list *replies,
                               const struct ofputil_port_stats *ops);
 size_t ofputil_count_port_stats(const struct ofp_header *);
 int ofputil_decode_port_stats(struct ofputil_port_stats *, struct ofpbuf *msg);
 enum ofperr ofputil_decode_port_stats_request(const struct ofp_header *request,
-                                              uint16_t *ofp10_port);
+                                              ofp_port_t *ofp10_port);
 
 struct ofputil_queue_stats_request {
-    uint16_t port_no;           /* OFPP_ANY means "all ports". */
+    ofp_port_t port_no;           /* OFPP_ANY means "all ports". */
     uint32_t queue_id;
 };
 
@@ -719,7 +721,7 @@ ofputil_encode_queue_stats_request(enum ofp_version ofp_version,
                                    const struct ofputil_queue_stats_request *oqsr);
 
 struct ofputil_queue_stats {
-    uint16_t port_no;
+    ofp_port_t port_no;
     uint32_t queue_id;
     struct netdev_queue_stats stats;
 };
diff --git a/lib/util.c b/lib/util.c
index cd4019e..776caab 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -27,7 +27,6 @@
 #include <unistd.h>
 #include "byte-order.h"
 #include "coverage.h"
-#include "openvswitch/types.h"
 #include "vlog.h"
 
 VLOG_DEFINE_THIS_MODULE(util);
@@ -481,6 +480,17 @@ str_to_ullong(const char *s, int base, unsigned long long *ull)
     return str_to_llong(s, base, (long long *) ull);
 }
 
+bool
+str_to_ofp(const char *s, ofp_port_t *ofp_port)
+{
+    bool ret;
+    uint32_t port_;
+
+    ret = str_to_uint(s, 10, &port_);
+    *ofp_port = OFP_PORT_C(port_);
+    return ret;
+}
+
 /* Converts floating-point string 's' into a double.  If successful, stores
  * the double in '*d' and returns true; on failure, stores 0 in '*d' and
  * returns false.
diff --git a/lib/util.h b/lib/util.h
index f5589e3..4a06a75 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include "compiler.h"
+#include "openvswitch/types.h"
 
 #ifndef va_copy
 #ifdef __va_copy
@@ -224,6 +225,8 @@ bool str_to_ullong(const char *, int base, unsigned long long *);
 
 bool str_to_double(const char *, double *);
 
+bool str_to_ofp(const char *, ofp_port_t *);
+
 int hexit_value(int c);
 unsigned int hexits_value(const char *s, size_t n, bool *ok);
 
diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
index 0951968..9ddae5c 100644
--- a/ofproto/connmgr.c
+++ b/ofproto/connmgr.c
@@ -1039,7 +1039,7 @@ ofconn_send_error(const struct ofconn *ofconn,
 /* Same as pktbuf_retrieve(), using the pktbuf owned by 'ofconn'. */
 enum ofperr
 ofconn_pktbuf_retrieve(struct ofconn *ofconn, uint32_t id,
-                       struct ofpbuf **bufferp, uint16_t *in_port)
+                       struct ofpbuf **bufferp, ofp_port_t *in_port)
 {
     return pktbuf_retrieve(ofconn->pktbuf, id, bufferp, in_port);
 }
@@ -1646,7 +1646,7 @@ any_extras_changed(const struct connmgr *mgr,
 
 bool
 connmgr_must_output_local(struct connmgr *mgr, const struct flow *flow,
-                          uint32_t local_odp_port,
+                          odp_port_t local_odp_port,
                           const struct nlattr *odp_actions,
                           size_t actions_len)
 {
diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h
index 429e678..0242116 100644
--- a/ofproto/connmgr.h
+++ b/ofproto/connmgr.h
@@ -125,7 +125,7 @@ void ofconn_send_error(const struct ofconn *, const struct ofp_header *request,
                        enum ofperr);
 
 enum ofperr ofconn_pktbuf_retrieve(struct ofconn *, uint32_t id,
-                                   struct ofpbuf **bufferp, uint16_t *in_port);
+                                   struct ofpbuf **bufferp, ofp_port_t *in_port);
 
 bool ofconn_has_pending_opgroups(const struct ofconn *);
 void ofconn_add_opgroup(struct ofconn *, struct list *);
@@ -157,7 +157,7 @@ void connmgr_set_in_band_queue(struct connmgr *, int queue_id);
 
 /* In-band implementation. */
 bool connmgr_must_output_local(struct connmgr *, const struct flow *,
-                               uint32_t local_odp_port,
+                               odp_port_t local_odp_port,
                                const struct nlattr *odp_actions,
                                size_t actions_len);
 
@@ -173,7 +173,7 @@ struct ofmonitor {
     enum nx_flow_monitor_flags flags;
 
     /* Matching. */
-    uint16_t out_port;
+    ofp_port_t out_port;
     uint8_t table_id;
     struct minimatch match;
 };
diff --git a/ofproto/in-band.c b/ofproto/in-band.c
index ba6fc54..0746bab 100644
--- a/ofproto/in-band.c
+++ b/ofproto/in-band.c
@@ -225,7 +225,7 @@ refresh_local(struct in_band *ib)
 /* Returns true if the rule that would match 'flow' with 'actions' is
  * allowed to be set up in the datapath. */
 bool
-in_band_rule_check(const struct flow *flow, uint32_t local_odp_port,
+in_band_rule_check(const struct flow *flow, odp_port_t local_odp_port,
                    const struct nlattr *actions, size_t actions_len)
 {
     /* Don't allow flows that would prevent DHCP replies from being seen
@@ -239,7 +239,7 @@ in_band_rule_check(const struct flow *flow, uint32_t local_odp_port,
 
         NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) {
             if (nl_attr_type(a) == OVS_ACTION_ATTR_OUTPUT
-                && nl_attr_get_u32(a) == local_odp_port) {
+                && nl_attr_get_odp_port(a) == local_odp_port) {
                 return true;
             }
         }
diff --git a/ofproto/in-band.h b/ofproto/in-band.h
index 4f52e00..5449312 100644
--- a/ofproto/in-band.h
+++ b/ofproto/in-band.h
@@ -21,6 +21,7 @@
 #include <stddef.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include "flow.h"
 
 struct flow;
 struct in_band;
@@ -39,7 +40,7 @@ void in_band_set_remotes(struct in_band *,
 bool in_band_run(struct in_band *);
 void in_band_wait(struct in_band *);
 
-bool in_band_rule_check(const struct flow *, uint32_t local_odp_port,
+bool in_band_rule_check(const struct flow *, odp_port_t local_odp_port,
                         const struct nlattr *odp_actions, size_t actions_len);
 
 #endif /* in-band.h */
diff --git a/ofproto/netflow.c b/ofproto/netflow.c
index 7366986..d66486d 100644
--- a/ofproto/netflow.c
+++ b/ofproto/netflow.c
@@ -85,11 +85,13 @@ 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->output = htons(iface | (nf_flow->output_iface & 0x1ff));
+        nf_rec->input = htons(iface
+            | (ofp_to_u16(expired->flow.in_port.ofp_port) & 0x1ff));
+        nf_rec->output = htons(iface
+            | (ofp_to_u16(nf_flow->output_iface) & 0x1ff));
     } else {
-        nf_rec->input = htons(expired->flow.in_port);
-        nf_rec->output = htons(nf_flow->output_iface);
+        nf_rec->input = htons(ofp_to_u16(expired->flow.in_port.ofp_port));
+        nf_rec->output = htons(ofp_to_u16(nf_flow->output_iface));
     }
     nf_rec->packet_count = htonl(packet_count);
     nf_rec->byte_count = htonl(byte_count);
@@ -263,7 +265,7 @@ netflow_flow_init(struct netflow_flow *nf_flow OVS_UNUSED)
 void
 netflow_flow_clear(struct netflow_flow *nf_flow)
 {
-    uint16_t output_iface = nf_flow->output_iface;
+    ofp_port_t output_iface = nf_flow->output_iface;
 
     memset(nf_flow, 0, sizeof *nf_flow);
     nf_flow->output_iface = output_iface;
diff --git a/ofproto/netflow.h b/ofproto/netflow.h
index c01ff15..cfb0a8d 100644
--- a/ofproto/netflow.h
+++ b/ofproto/netflow.h
@@ -38,11 +38,9 @@ struct netflow_options {
     bool add_id_to_iface;
 };
 
-enum netflow_output_ports {
-    NF_OUT_FLOOD = UINT16_MAX,
-    NF_OUT_MULTI = UINT16_MAX - 1,
-    NF_OUT_DROP = UINT16_MAX - 2
-};
+#define NF_OUT_FLOOD OFPP_NONE
+#define NF_OUT_MULTI (u16_to_ofp(ofp_to_u16(OFPP_NONE) - 1))
+#define NF_OUT_DROP  (u16_to_ofp(ofp_to_u16(OFPP_NONE) - 2))
 
 struct netflow_flow {
     long long int last_expired;   /* Time this flow last timed out. */
@@ -51,7 +49,7 @@ struct netflow_flow {
     uint64_t packet_count_off;    /* Packet count at last time out. */
     uint64_t byte_count_off;      /* Byte count at last time out. */
 
-    uint16_t output_iface;        /* Output interface index. */
+    ofp_port_t output_iface;      /* Output interface index. */
     uint8_t tcp_flags;            /* Bitwise-OR of all TCP flags seen. */
 };
 
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index 9ad0eaf..5d53ee0 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -46,7 +46,7 @@ struct dpif_sflow_port {
     struct hmap_node hmap_node; /* In struct dpif_sflow's "ports" hmap. */
     SFLDataSource_instance dsi; /* sFlow library's notion of port number. */
     struct ofport *ofport;      /* To retrive port stats. */
-    uint32_t odp_port;
+    odp_port_t odp_port;
 };
 
 struct dpif_sflow {
@@ -142,12 +142,13 @@ sflow_agent_send_packet_cb(void *ds_, SFLAgent *agent OVS_UNUSED,
 }
 
 static struct dpif_sflow_port *
-dpif_sflow_find_port(const struct dpif_sflow *ds, uint32_t odp_port)
+dpif_sflow_find_port(const struct dpif_sflow *ds, odp_port_t odp_port)
 {
     struct dpif_sflow_port *dsp;
 
     HMAP_FOR_EACH_IN_BUCKET (dsp, hmap_node,
-                             hash_int(odp_port, 0), &ds->ports) {
+                             hash_int(odp_to_u32(odp_port), 0),
+                                      &ds->ports) {
         if (dsp->odp_port == odp_port) {
             return dsp;
         }
@@ -167,7 +168,7 @@ sflow_agent_get_counters(void *ds_, SFLPoller *poller,
     struct netdev_stats stats;
     enum netdev_flags flags;
 
-    dsp = dpif_sflow_find_port(ds, poller->bridgePort);
+    dsp = dpif_sflow_find_port(ds, u32_to_odp(poller->bridgePort));
     if (!dsp) {
         return;
     }
@@ -338,12 +339,12 @@ dpif_sflow_add_poller(struct dpif_sflow *ds, struct dpif_sflow_port *dsp)
                                             sflow_agent_get_counters);
     sfl_poller_set_sFlowCpInterval(poller, ds->options->polling_interval);
     sfl_poller_set_sFlowCpReceiver(poller, RECEIVER_INDEX);
-    sfl_poller_set_bridgePort(poller, dsp->odp_port);
+    sfl_poller_set_bridgePort(poller, odp_to_u32(dsp->odp_port));
 }
 
 void
 dpif_sflow_add_port(struct dpif_sflow *ds, struct ofport *ofport,
-                    uint32_t odp_port)
+                    odp_port_t odp_port)
 {
     struct dpif_sflow_port *dsp;
     int ifindex;
@@ -362,7 +363,7 @@ dpif_sflow_add_port(struct dpif_sflow *ds, struct ofport *ofport,
     dsp->ofport = ofport;
     dsp->odp_port = odp_port;
     SFL_DS_SET(dsp->dsi, SFL_DSCLASS_IFINDEX, ifindex, 0);
-    hmap_insert(&ds->ports, &dsp->hmap_node, hash_int(odp_port, 0));
+    hmap_insert(&ds->ports, &dsp->hmap_node, hash_int(odp_to_u32(odp_port), 0));
 
     /* Add poller. */
     if (ds->sflow_agent) {
@@ -382,7 +383,7 @@ dpif_sflow_del_port__(struct dpif_sflow *ds, struct dpif_sflow_port *dsp)
 }
 
 void
-dpif_sflow_del_port(struct dpif_sflow *ds, uint32_t odp_port)
+dpif_sflow_del_port(struct dpif_sflow *ds, odp_port_t odp_port)
 {
     struct dpif_sflow_port *dsp = dpif_sflow_find_port(ds, odp_port);
     if (dsp) {
@@ -488,7 +489,7 @@ dpif_sflow_set_options(struct dpif_sflow *ds,
 
 int
 dpif_sflow_odp_port_to_ifindex(const struct dpif_sflow *ds,
-                               uint32_t odp_port)
+                               odp_port_t odp_port)
 {
     struct dpif_sflow_port *dsp = dpif_sflow_find_port(ds, odp_port);
     return dsp ? SFL_DS_INDEX(dsp->dsi) : 0;
@@ -496,7 +497,7 @@ dpif_sflow_odp_port_to_ifindex(const struct dpif_sflow *ds,
 
 void
 dpif_sflow_received(struct dpif_sflow *ds, struct ofpbuf *packet,
-                    const struct flow *flow, uint32_t odp_in_port,
+                    const struct flow *flow, odp_port_t odp_in_port,
                     const union user_action_cookie *cookie)
 {
     SFL_FLOW_SAMPLE_TYPE fs;
diff --git a/ofproto/ofproto-dpif-sflow.h b/ofproto/ofproto-dpif-sflow.h
index 02a0f17..d0f83bc 100644
--- a/ofproto/ofproto-dpif-sflow.h
+++ b/ofproto/ofproto-dpif-sflow.h
@@ -38,8 +38,8 @@ void dpif_sflow_clear(struct dpif_sflow *);
 bool dpif_sflow_is_enabled(const struct dpif_sflow *);
 
 void dpif_sflow_add_port(struct dpif_sflow *ds, struct ofport *ofport,
-                         uint32_t odp_port);
-void dpif_sflow_del_port(struct dpif_sflow *, uint32_t odp_port);
+                         odp_port_t odp_port);
+void dpif_sflow_del_port(struct dpif_sflow *, odp_port_t odp_port);
 
 void dpif_sflow_run(struct dpif_sflow *);
 void dpif_sflow_wait(struct dpif_sflow *);
@@ -47,9 +47,10 @@ void dpif_sflow_wait(struct dpif_sflow *);
 void dpif_sflow_received(struct dpif_sflow *,
                          struct ofpbuf *,
                          const struct flow *,
-                         uint32_t odp_port,
+                         odp_port_t odp_port,
                          const union user_action_cookie *);
 
-int dpif_sflow_odp_port_to_ifindex(const struct dpif_sflow *, uint32_t);
+int dpif_sflow_odp_port_to_ifindex(const struct dpif_sflow *,
+                                   odp_port_t odp_port);
 
 #endif /* ofproto/ofproto-dpif-sflow.h */
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 1c234ec..8d760fd 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -80,7 +80,7 @@ struct xlate_ctx {
     uint32_t orig_skb_priority; /* Priority when packet arrived. */
     uint8_t table_id;           /* OpenFlow table ID where flow was found. */
     uint32_t sflow_n_outputs;   /* Number of output ports. */
-    uint32_t sflow_odp_port;    /* Output port for composing sFlow action. */
+    odp_port_t sflow_odp_port;  /* Output port for composing sFlow action. */
     uint16_t user_cookie_offset;/* Used for user_action_cookie fixup. */
     bool exit;                  /* No further actions should be processed. */
 };
@@ -100,13 +100,13 @@ static void do_xlate_actions(const struct ofpact *, size_t ofpacts_len,
                              struct xlate_ctx *);
 static void xlate_normal(struct xlate_ctx *);
 static void xlate_report(struct xlate_ctx *, const char *);
-static void xlate_table_action(struct xlate_ctx *, uint16_t in_port,
+static void xlate_table_action(struct xlate_ctx *, ofp_port_t in_port,
                                uint8_t table_id, bool may_packet_in);
 static bool input_vid_is_valid(uint16_t vid, struct ofbundle *, bool warn);
 static uint16_t input_vid_to_vlan(const struct ofbundle *, uint16_t vid);
 static void output_normal(struct xlate_ctx *, const struct ofbundle *,
                           uint16_t vlan);
-static void compose_output_action(struct xlate_ctx *, uint16_t ofp_port);
+static void compose_output_action(struct xlate_ctx *, ofp_port_t ofp_port);
 
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
@@ -130,7 +130,7 @@ vlan_is_mirrored(const struct ofmirror *m, int vlan)
 }
 
 static struct ofbundle *
-lookup_input_bundle(const struct ofproto_dpif *ofproto, uint16_t in_port,
+lookup_input_bundle(const struct ofproto_dpif *ofproto, ofp_port_t in_port,
                     bool warn, struct ofport_dpif **in_ofportp)
 {
     struct ofport_dpif *ofport;
@@ -183,7 +183,7 @@ add_mirror_actions(struct 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->in_port.ofp_port,
                                     ctx->xin->packet != NULL, NULL);
     if (!in_bundle) {
         return;
@@ -219,7 +219,7 @@ add_mirror_actions(struct xlate_ctx *ctx, const struct flow *orig_flow)
             continue;
         }
 
-        ofport = get_odp_port(ofproto, nl_attr_get_u32(a));
+        ofport = get_odp_port(ofproto, nl_attr_get_odp_port(a));
         if (ofport && ofport->bundle) {
             mirrors |= ofport->bundle->dst_mirrors;
         }
@@ -554,7 +554,7 @@ xlate_normal(struct xlate_ctx *ctx)
     memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst);
     memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci);
 
-    in_bundle = lookup_input_bundle(ctx->ofproto, flow->in_port,
+    in_bundle = lookup_input_bundle(ctx->ofproto, flow->in_port.ofp_port,
                                     ctx->xin->packet != NULL, &in_port);
     if (!in_bundle) {
         xlate_report(ctx, "no input bundle, dropping");
@@ -660,7 +660,7 @@ compose_sample_action(const struct ofproto_dpif *ofproto,
 
 static void
 compose_sflow_cookie(const struct ofproto_dpif *ofproto,
-                     ovs_be16 vlan_tci, uint32_t odp_port,
+                     ovs_be16 vlan_tci, odp_port_t odp_port,
                      unsigned int n_outputs, union user_action_cookie *cookie)
 {
     int ifindex;
@@ -695,18 +695,18 @@ static size_t
 compose_sflow_action(const struct ofproto_dpif *ofproto,
                      struct ofpbuf *odp_actions,
                      const struct flow *flow,
-                     uint32_t odp_port)
+                     odp_port_t odp_port)
 {
     uint32_t probability;
     union user_action_cookie cookie;
 
-    if (!ofproto->sflow || flow->in_port == OFPP_NONE) {
+    if (!ofproto->sflow || flow->in_port.ofp_port == OFPP_NONE) {
         return 0;
     }
 
     probability = dpif_sflow_get_probability(ofproto->sflow);
     compose_sflow_cookie(ofproto, htons(0), odp_port,
-                         odp_port == OVSP_NONE ? 0 : 1, &cookie);
+                         odp_port == ODPP_NONE ? 0 : 1, &cookie);
 
     return compose_sample_action(ofproto, odp_actions, flow,  probability,
                                  &cookie, sizeof cookie.sflow);
@@ -739,7 +739,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->in_port.ofp_port == OFPP_NONE) {
         return;
     }
 
@@ -758,7 +758,7 @@ add_sflow_action(struct xlate_ctx *ctx)
 {
     ctx->user_cookie_offset = compose_sflow_action(ctx->ofproto,
                                                    &ctx->xout->odp_actions,
-                                                   &ctx->xin->flow, OVSP_NONE);
+                                                   &ctx->xin->flow, ODPP_NONE);
     ctx->sflow_odp_port = 0;
     ctx->sflow_n_outputs = 0;
 }
@@ -829,7 +829,7 @@ process_special(struct xlate_ctx *ctx, const struct flow *flow,
 }
 
 static void
-compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
+compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
                         bool check_stp)
 {
     const struct ofport_dpif *ofport = get_ofp_port(ctx->ofproto, ofp_port);
@@ -837,7 +837,7 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
     ovs_be16 flow_vlan_tci;
     uint32_t flow_skb_mark;
     uint8_t flow_nw_tos;
-    uint32_t out_port, odp_port;
+    odp_port_t out_port, odp_port;
     uint8_t dscp;
 
     /* If 'struct flow' gets additional metadata, we'll need to zero it out
@@ -861,7 +861,7 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
         enum slow_path_reason special;
 
         ctx->ofproto = ofproto_dpif_cast(peer->up.ofproto);
-        flow->in_port = peer->up.ofp_port;
+        flow->in_port.ofp_port = peer->up.ofp_port;
         flow->metadata = htonll(0);
         memset(&flow->tunnel, 0, sizeof flow->tunnel);
         memset(flow->regs, 0, sizeof flow->regs);
@@ -872,13 +872,13 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
             ctx->xout->slow = special;
         } else if (may_receive(peer, ctx)) {
             if (stp_forward_in_state(peer->stp_state)) {
-                xlate_table_action(ctx, flow->in_port, 0, true);
+                xlate_table_action(ctx, flow->in_port.ofp_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->xout->odp_actions.size;
-                xlate_table_action(ctx, flow->in_port, 0, true);
+                xlate_table_action(ctx, flow->in_port.ofp_port, 0, true);
                 ctx->base_flow = old_base_flow;
                 ctx->xout->odp_actions.size = old_size;
             }
@@ -911,7 +911,7 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
           */
         struct flow_tnl flow_tnl = flow->tunnel;
         odp_port = tnl_port_send(ofport->tnl_port, flow, &ctx->xout->wc);
-        if (odp_port == OVSP_NONE) {
+        if (odp_port == ODPP_NONE) {
             xlate_report(ctx, "Tunneling decided against output");
             goto out; /* restore flow_nw_tos */
         }
@@ -927,7 +927,7 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
                                  &ctx->xout->odp_actions);
         flow->tunnel = flow_tnl; /* Restore tunnel metadata */
     } else {
-        uint16_t vlandev_port;
+        ofp_port_t vlandev_port;
         odp_port = ofport->odp_port;
         vlandev_port = vsp_realdev_to_vlandev(ctx->ofproto, ofp_port,
                                               flow->vlan_tci);
@@ -940,9 +940,9 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
         flow->skb_mark &= ~IPSEC_MARK;
     }
 
-    if (out_port != OVSP_NONE) {
+    if (out_port != ODPP_NONE) {
         commit_odp_actions(flow, &ctx->base_flow, &ctx->xout->odp_actions);
-        nl_msg_put_u32(&ctx->xout->odp_actions, OVS_ACTION_ATTR_OUTPUT,
+        nl_msg_put_odp_port(&ctx->xout->odp_actions, OVS_ACTION_ATTR_OUTPUT,
                        out_port);
 
         ctx->sflow_odp_port = odp_port;
@@ -958,7 +958,7 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
 }
 
 static void
-compose_output_action(struct xlate_ctx *ctx, uint16_t ofp_port)
+compose_output_action(struct xlate_ctx *ctx, ofp_port_t ofp_port)
 {
     compose_output_action__(ctx, ofp_port, true);
 }
@@ -1007,17 +1007,17 @@ ctx_rule_hooks(struct xlate_ctx *ctx, struct rule_dpif *rule,
 
 static void
 xlate_table_action(struct xlate_ctx *ctx,
-                   uint16_t in_port, uint8_t table_id, bool may_packet_in)
+                   ofp_port_t in_port, uint8_t table_id, bool may_packet_in)
 {
     if (ctx->recurse < MAX_RESUBMIT_RECURSION) {
         struct rule_dpif *rule;
-        uint16_t old_in_port = ctx->xin->flow.in_port;
+        ofp_port_t old_in_port = ctx->xin->flow.in_port.ofp_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->xin->flow.in_port = in_port;
+        ctx->xin->flow.in_port.ofp_port = in_port;
         rule = rule_dpif_lookup_in_table(ctx->ofproto, &ctx->xin->flow,
                                          &ctx->xout->wc, table_id);
 
@@ -1025,7 +1025,7 @@ xlate_table_action(struct xlate_ctx *ctx,
 
         /* Restore the original input port.  Otherwise OFPP_NORMAL and
          * OFPP_IN_PORT will have surprising behavior. */
-        ctx->xin->flow.in_port = old_in_port;
+        ctx->xin->flow.in_port.ofp_port = old_in_port;
 
         rule = ctx_rule_hooks(ctx, rule, may_packet_in);
 
@@ -1053,12 +1053,12 @@ static void
 xlate_ofpact_resubmit(struct xlate_ctx *ctx,
                       const struct ofpact_resubmit *resubmit)
 {
-    uint16_t in_port;
+    ofp_port_t in_port;
     uint8_t table_id;
 
     in_port = resubmit->in_port;
     if (in_port == OFPP_IN_PORT) {
-        in_port = ctx->xin->flow.in_port;
+        in_port = ctx->xin->flow.in_port.ofp_port;
     }
 
     table_id = resubmit->table_id;
@@ -1075,9 +1075,9 @@ flood_packets(struct xlate_ctx *ctx, bool all)
     struct ofport_dpif *ofport;
 
     HMAP_FOR_EACH (ofport, up.hmap_node, &ctx->ofproto->up.ports) {
-        uint16_t ofp_port = ofport->up.ofp_port;
+        ofp_port_t ofp_port = ofport->up.ofp_port;
 
-        if (ofp_port == ctx->xin->flow.in_port) {
+        if (ofp_port == ctx->xin->flow.in_port.ofp_port) {
             continue;
         }
 
@@ -1246,18 +1246,19 @@ compose_dec_mpls_ttl_action(struct xlate_ctx *ctx)
 
 static void
 xlate_output_action(struct xlate_ctx *ctx,
-                    uint16_t port, uint16_t max_len, bool may_packet_in)
+                    ofp_port_t port, uint16_t max_len, bool may_packet_in)
 {
-    uint16_t prev_nf_output_iface = ctx->xout->nf_output_iface;
+    ofp_port_t prev_nf_output_iface = ctx->xout->nf_output_iface;
 
     ctx->xout->nf_output_iface = NF_OUT_DROP;
 
     switch (port) {
     case OFPP_IN_PORT:
-        compose_output_action(ctx, ctx->xin->flow.in_port);
+        compose_output_action(ctx, ctx->xin->flow.in_port.ofp_port);
         break;
     case OFPP_TABLE:
-        xlate_table_action(ctx, ctx->xin->flow.in_port, 0, may_packet_in);
+        xlate_table_action(ctx, ctx->xin->flow.in_port.ofp_port,
+                           0, may_packet_in);
         break;
     case OFPP_NORMAL:
         xlate_normal(ctx);
@@ -1275,7 +1276,7 @@ xlate_output_action(struct xlate_ctx *ctx,
         break;
     case OFPP_LOCAL:
     default:
-        if (port != ctx->xin->flow.in_port) {
+        if (port != ctx->xin->flow.in_port.ofp_port) {
             compose_output_action(ctx, port);
         } else {
             xlate_report(ctx, "skipping output to input port");
@@ -1303,7 +1304,8 @@ xlate_output_reg_action(struct xlate_ctx *ctx,
 
         memset(&value, 0xff, sizeof value);
         mf_write_subfield_flow(&or->src, &value, &ctx->xout->wc.masks);
-        xlate_output_action(ctx, port, or->max_len, false);
+        xlate_output_action(ctx, u16_to_ofp(port),
+                            or->max_len, false);
     }
 }
 
@@ -1311,7 +1313,7 @@ static void
 xlate_enqueue_action(struct xlate_ctx *ctx,
                      const struct ofpact_enqueue *enqueue)
 {
-    uint16_t ofp_port = enqueue->port;
+    ofp_port_t ofp_port = enqueue->port;
     uint32_t queue_id = enqueue->queue;
     uint32_t flow_priority, priority;
     int error;
@@ -1326,8 +1328,8 @@ xlate_enqueue_action(struct xlate_ctx *ctx,
 
     /* Check output port. */
     if (ofp_port == OFPP_IN_PORT) {
-        ofp_port = ctx->xin->flow.in_port;
-    } else if (ofp_port == ctx->xin->flow.in_port) {
+        ofp_port = ctx->xin->flow.in_port.ofp_port;
+    } else if (ofp_port == ctx->xin->flow.in_port.ofp_port) {
         return;
     }
 
@@ -1360,7 +1362,7 @@ xlate_set_queue_action(struct xlate_ctx *ctx, uint32_t queue_id)
 }
 
 static bool
-slave_enabled_cb(uint16_t ofp_port, void *ofproto_)
+slave_enabled_cb(ofp_port_t ofp_port, void *ofproto_)
 {
     struct ofproto_dpif *ofproto = ofproto_;
     struct ofport_dpif *port;
@@ -1385,12 +1387,12 @@ static void
 xlate_bundle_action(struct xlate_ctx *ctx,
                     const struct ofpact_bundle *bundle)
 {
-    uint16_t port;
+    ofp_port_t port;
 
     port = bundle_execute(bundle, &ctx->xin->flow, &ctx->xout->wc,
                           slave_enabled_cb, ctx->ofproto);
     if (bundle->dst.field) {
-        nxm_reg_load(&bundle->dst, port, &ctx->xin->flow);
+        nxm_reg_load(&bundle->dst, ofp_to_u16(port), &ctx->xin->flow);
     } else {
         xlate_output_action(ctx, port, 0, false);
     }
@@ -1967,17 +1969,17 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
         }
     }
 
-    in_port = get_ofp_port(ctx.ofproto, flow->in_port);
+    in_port = get_ofp_port(ctx.ofproto, flow->in_port.ofp_port);
     special = process_special(&ctx, flow, in_port, ctx.xin->packet);
     if (special) {
         ctx.xout->slow = special;
     } else {
         static struct vlog_rate_limit trace_rl = VLOG_RATE_LIMIT_INIT(1, 1);
         size_t sample_actions_len;
-        uint32_t local_odp_port;
+        odp_port_t local_odp_port;
 
-        if (flow->in_port
-            != vsp_realdev_to_vlandev(ctx.ofproto, flow->in_port,
+        if (flow->in_port.ofp_port
+            != vsp_realdev_to_vlandev(ctx.ofproto, flow->in_port.ofp_port,
                                       flow->vlan_tci)) {
             ctx.base_flow.vlan_tci = 0;
         }
diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h
index 9ee9b33..f5f0cd0 100644
--- a/ofproto/ofproto-dpif-xlate.h
+++ b/ofproto/ofproto-dpif-xlate.h
@@ -37,7 +37,7 @@ struct xlate_out {
     bool has_learn;             /* Actions include NXAST_LEARN? */
     bool has_normal;            /* Actions output to OFPP_NORMAL? */
     bool has_fin_timeout;       /* Actions include NXAST_FIN_TIMEOUT? */
-    uint16_t nf_output_iface;   /* Output interface index for NetFlow. */
+    ofp_port_t nf_output_iface; /* Output interface index for NetFlow. */
     mirror_mask_t mirrors;      /* Bitmap of associated mirrors. */
 
     uint64_t odp_actions_stub[256 / 8];
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index e3acbc6..9595842 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -277,17 +277,17 @@ struct priority_to_dscp {
 struct vlan_splinter {
     struct hmap_node realdev_vid_node;
     struct hmap_node vlandev_node;
-    uint16_t realdev_ofp_port;
-    uint16_t vlandev_ofp_port;
+    ofp_port_t realdev_ofp_port;
+    ofp_port_t vlandev_ofp_port;
     int vid;
 };
 
 static bool vsp_adjust_flow(const struct ofproto_dpif *, struct flow *);
 static void vsp_remove(struct ofport_dpif *);
-static void vsp_add(struct ofport_dpif *, uint16_t realdev_ofp_port, int vid);
+static void vsp_add(struct ofport_dpif *, ofp_port_t realdev_ofp_port, int vid);
 
-static uint16_t odp_port_to_ofp_port(const struct ofproto_dpif *,
-                                     uint32_t odp_port);
+static ofp_port_t odp_port_to_ofp_port(const struct ofproto_dpif *,
+                                       odp_port_t odp_port);
 
 static struct ofport_dpif *
 ofport_dpif_cast(const struct ofport *ofport)
@@ -396,7 +396,7 @@ static struct shash all_dpif_backers = SHASH_INITIALIZER(&all_dpif_backers);
 
 static void drop_key_clear(struct dpif_backer *);
 static struct ofport_dpif *
-odp_port_to_ofport(const struct dpif_backer *, uint32_t odp_port);
+odp_port_to_ofport(const struct dpif_backer *, odp_port_t odp_port);
 static void update_moving_averages(struct dpif_backer *backer);
 
 /* Defer flow mod completion until "ovs-appctl ofproto/unclog"?  (Useful only
@@ -584,17 +584,19 @@ type_run(const char *type)
                 } else {
                     node = simap_find(&backer->tnl_backers, dp_port);
                     if (!node) {
-                        uint32_t odp_port = UINT32_MAX;
+                        odp_port_t odp_port = ODPP_NONE;
 
                         if (!dpif_port_add(backer->dpif, iter->up.netdev,
                                            &odp_port)) {
-                            simap_put(&backer->tnl_backers, dp_port, odp_port);
+                            simap_put(&backer->tnl_backers, dp_port,
+                                      odp_to_u32(odp_port));
                             node = simap_find(&backer->tnl_backers, dp_port);
                         }
                     }
                 }
 
-                iter->odp_port = node ? node->data : OVSP_NONE;
+                iter->odp_port = node ? u32_to_odp(node->data)
+                                        : ODPP_NONE;
                 if (tnl_port_reconfigure(&iter->up, iter->odp_port,
                                          &iter->tnl_port)) {
                     backer->need_revalidate = REV_RECONFIGURE;
@@ -603,7 +605,7 @@ type_run(const char *type)
         }
 
         SIMAP_FOR_EACH (node, &tmp_backers) {
-            dpif_port_del(backer->dpif, node->data);
+            dpif_port_del(backer->dpif, u32_to_odp(node->data));
         }
         simap_destroy(&tmp_backers);
 
@@ -877,7 +879,7 @@ close_dpif_backer(struct dpif_backer *backer)
 /* Datapath port slated for removal from datapath. */
 struct odp_garbage {
     struct list list_node;
-    uint32_t odp_port;
+    odp_port_t odp_port;
 };
 
 static int
@@ -1003,7 +1005,7 @@ construct(struct ofproto *ofproto_)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
     struct shash_node *node, *next;
-    int max_ports;
+    odp_port_t max_ports;
     int error;
     int i;
 
@@ -1013,7 +1015,8 @@ construct(struct ofproto *ofproto_)
     }
 
     max_ports = dpif_get_max_ports(ofproto->backer->dpif);
-    ofproto_init_max_ports(ofproto_, MIN(max_ports, OFPP_MAX));
+    ofproto_init_max_ports(ofproto_, u16_to_ofp(MIN(odp_to_u32(max_ports),
+                                                    ofp_to_u16(OFPP_MAX))));
 
     ofproto->netflow = NULL;
     ofproto->sflow = NULL;
@@ -1469,7 +1472,7 @@ port_construct(struct ofport *port_)
 	 * because the patch port represents an interface that sFlow considers
 	 * to be "internal" to the switch as a whole, and therefore not an
 	 * candidate for counter polling. */
-        port->odp_port = OVSP_NONE;
+        port->odp_port = ODPP_NONE;
         ofport_update_peer(port);
         return 0;
     }
@@ -1497,7 +1500,7 @@ port_construct(struct ofport *port_)
         }
 
         hmap_insert(&ofproto->backer->odp_to_ofport_map, &port->odp_port_node,
-                    hash_int(port->odp_port, 0));
+                    hash_int(odp_to_u32(port->odp_port), 0));
     }
     dpif_port_destroy(&dpif_port);
 
@@ -1535,7 +1538,7 @@ port_destruct(struct ofport *port_)
         port->peer = NULL;
     }
 
-    if (port->odp_port != OVSP_NONE && !port->tnl_port) {
+    if (port->odp_port != ODPP_NONE && !port->tnl_port) {
         hmap_remove(&ofproto->backer->odp_to_ofport_map, &port->odp_port_node);
     }
 
@@ -2178,7 +2181,7 @@ bundle_del_port(struct ofport_dpif *port)
 }
 
 static bool
-bundle_add_port(struct ofbundle *bundle, uint16_t ofp_port,
+bundle_add_port(struct ofbundle *bundle, ofp_port_t ofp_port,
                 struct lacp_slave_settings *lacp)
 {
     struct ofport_dpif *port;
@@ -2821,14 +2824,14 @@ set_mac_table_config(struct ofproto *ofproto_, unsigned int idle_time,
 /* Ports. */
 
 struct ofport_dpif *
-get_ofp_port(const struct ofproto_dpif *ofproto, uint16_t ofp_port)
+get_ofp_port(const struct ofproto_dpif *ofproto, ofp_port_t ofp_port)
 {
     struct ofport *ofport = ofproto_get_port(&ofproto->up, ofp_port);
     return ofport ? ofport_dpif_cast(ofport) : NULL;
 }
 
 struct ofport_dpif *
-get_odp_port(const struct ofproto_dpif *ofproto, uint32_t odp_port)
+get_odp_port(const struct ofproto_dpif *ofproto, odp_port_t odp_port)
 {
     struct ofport_dpif *port = odp_port_to_ofport(ofproto->backer, odp_port);
     return port && &ofproto->up == port->up.ofproto ? port : NULL;
@@ -3025,7 +3028,7 @@ port_add(struct ofproto *ofproto_, struct netdev *netdev)
 
     dp_port_name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
     if (!dpif_port_exists(ofproto->backer->dpif, dp_port_name)) {
-        uint32_t port_no = UINT32_MAX;
+        odp_port_t port_no = ODPP_NONE;
         int error;
 
         error = dpif_port_add(ofproto->backer->dpif, netdev, &port_no);
@@ -3033,7 +3036,8 @@ port_add(struct ofproto *ofproto_, struct netdev *netdev)
             return error;
         }
         if (netdev_get_tunnel_config(netdev)) {
-            simap_put(&ofproto->backer->tnl_backers, dp_port_name, port_no);
+            simap_put(&ofproto->backer->tnl_backers,
+                      dp_port_name, odp_to_u32(port_no));
         }
     }
 
@@ -3046,7 +3050,7 @@ port_add(struct ofproto *ofproto_, struct netdev *netdev)
 }
 
 static int
-port_del(struct ofproto *ofproto_, uint16_t ofp_port)
+port_del(struct ofproto *ofproto_, ofp_port_t ofp_port)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
     struct ofport_dpif *ofport = get_ofp_port(ofproto, ofp_port);
@@ -3292,8 +3296,8 @@ static void
 init_flow_miss_execute_op(struct flow_miss *miss, struct ofpbuf *packet,
                           struct flow_miss_op *op)
 {
-    if (miss->flow.in_port
-        != vsp_realdev_to_vlandev(miss->ofproto, miss->flow.in_port,
+    if (miss->flow.in_port.ofp_port
+        != vsp_realdev_to_vlandev(miss->ofproto, miss->flow.in_port.ofp_port,
                                   miss->flow.vlan_tci)) {
         /* This packet was received on a VLAN splinter port.  We
          * added a VLAN to the packet to make the packet resemble
@@ -3598,7 +3602,7 @@ static int
 ofproto_receive(const struct dpif_backer *backer, struct ofpbuf *packet,
                 const struct nlattr *key, size_t key_len,
                 struct flow *flow, enum odp_key_fitness *fitnessp,
-                struct ofproto_dpif **ofproto, uint32_t *odp_in_port)
+                struct ofproto_dpif **ofproto, odp_port_t *odp_in_port)
 {
     const struct ofport_dpif *port;
     enum odp_key_fitness fitness;
@@ -3611,13 +3615,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->in_port.odp_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->in_port.odp_port));
+    flow->in_port.ofp_port = port ? port->up.ofp_port : OFPP_NONE;
     if (!port) {
         goto exit;
     }
@@ -3692,7 +3696,7 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls,
         struct flow_miss *miss = &misses[n_misses];
         struct flow_miss *existing_miss;
         struct ofproto_dpif *ofproto;
-        uint32_t odp_in_port;
+        odp_port_t odp_in_port;
         struct flow flow;
         uint32_t hash;
         int error;
@@ -3731,7 +3735,7 @@ 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.tunnel, &flow.in_port, &miss->flow);
 
         /* Add other packets to a to-do list. */
         hash = flow_hash(&miss->flow, 0);
@@ -3835,7 +3839,7 @@ handle_sflow_upcall(struct dpif_backer *backer,
     struct ofproto_dpif *ofproto;
     union user_action_cookie cookie;
     struct flow flow;
-    uint32_t odp_in_port;
+    odp_port_t odp_in_port;
 
     if (ofproto_receive(backer, upcall->packet, upcall->key, upcall->key_len,
                         &flow, NULL, &ofproto, &odp_in_port)
@@ -4379,7 +4383,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->in_port.ofp_port));
 
     error = dpif_execute(ofproto->backer->dpif, key.data, key.size,
                          odp_actions, actions_len, packet);
@@ -4477,7 +4481,7 @@ facet_account(struct facet *facet)
 
         switch (nl_attr_type(a)) {
         case OVS_ACTION_ATTR_OUTPUT:
-            port = get_odp_port(ofproto, nl_attr_get_u32(a));
+            port = get_odp_port(ofproto, nl_attr_get_odp_port(a));
             if (port && port->bundle && port->bundle->bond) {
                 bond_account(port->bundle->bond, &facet->flow,
                              vlan_tci_to_vid(vlan_tci), n_bytes);
@@ -4800,7 +4804,7 @@ facet_push_stats(struct facet *facet, bool may_learn)
         facet->prev_byte_count = facet->byte_count;
         facet->prev_used = facet->used;
 
-        in_port = get_ofp_port(ofproto, facet->flow.in_port);
+        in_port = get_ofp_port(ofproto, facet->flow.in_port.ofp_port);
         if (in_port && in_port->tnl_port) {
             netdev_vport_inc_rx(in_port->up.netdev, &stats);
         }
@@ -5154,9 +5158,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->in_port.ofp_port);
     if (!port) {
-        VLOG_WARN_RL(&rl, "packet-in on unknown port %"PRIu16, flow->in_port);
+        VLOG_WARN_RL(&rl, "packet-in on unknown OpenFlow port %"PRIu16,
+                     flow->in_port.ofp_port);
         return ofproto->miss_rule;
     }
 
@@ -5328,13 +5333,15 @@ send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
     struct xlate_out xout;
     struct xlate_in xin;
     struct flow flow;
+    union flow_in_port in_port_;
     int error;
 
     ofpbuf_use_stub(&odp_actions, odp_actions_stub, sizeof odp_actions_stub);
     ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
 
     /* Use OFPP_NONE as the in_port to avoid special packet processing. */
-    flow_extract(packet, 0, 0, NULL, OFPP_NONE, &flow);
+    in_port_.ofp_port = OFPP_NONE;
+    flow_extract(packet, 0, 0, NULL, &in_port_, &flow);
     odp_flow_key_from_flow(&key, &flow, ofp_port_to_odp_port(ofproto,
                                                              OFPP_LOCAL));
     dpif_flow_stats_extract(&flow, packet, time_msec(), &stats);
@@ -5391,7 +5398,8 @@ compose_slow_path(const struct ofproto_dpif *ofproto, const struct flow *flow,
 
     ofpbuf_use_stack(&buf, stub, stub_size);
     if (slow & (SLOW_CFM | SLOW_BFD | SLOW_LACP | SLOW_STP)) {
-        uint32_t pid = dpif_port_get_pid(ofproto->backer->dpif, UINT32_MAX);
+        uint32_t pid = dpif_port_get_pid(ofproto->backer->dpif,
+                                         ODPP_NONE);
         odp_put_userspace_action(pid, &cookie, sizeof cookie.slow_path, &buf);
     } else {
         put_userspace_action(ofproto, &buf, flow, &cookie,
@@ -5411,7 +5419,8 @@ 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->in_port.ofp_port));
 
     return odp_put_userspace_action(pid, cookie, cookie_size, odp_actions);
 }
@@ -5587,7 +5596,8 @@ 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->in_port.ofp_port));
 
     dpif_flow_stats_extract(flow, packet, time_msec(), &stats);
 
@@ -5922,6 +5932,9 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
         if (!packet->size) {
             flow_compose(packet, &flow);
         } else {
+            union flow_in_port in_port_;
+
+            in_port_ = flow.in_port;
             ds_put_cstr(&result, "Packet: ");
             s = ofp_packet_to_string(packet->data, packet->size);
             ds_put_cstr(&result, s);
@@ -5930,7 +5943,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[],
             /* Use the metadata from the flow and the packet argument
              * to reconstruct the flow. */
             flow_extract(packet, flow.skb_priority, flow.skb_mark, NULL,
-                         flow.in_port, &flow);
+                         &in_port_, &flow);
         }
     }
 
@@ -6195,13 +6208,13 @@ dpif_show_backer(const struct dpif_backer *backer, struct ds *ds)
             const struct shash_node *node = ports[j];
             struct ofport *ofport = node->data;
             struct smap config;
-            uint32_t odp_port;
+            odp_port_t odp_port;
 
             ds_put_format(ds, "\t\t%s %u/", netdev_get_name(ofport->netdev),
                           ofport->ofp_port);
 
             odp_port = ofp_port_to_odp_port(ofproto, ofport->ofp_port);
-            if (odp_port != OVSP_NONE) {
+            if (odp_port != ODPP_NONE) {
                 ds_put_format(ds, "%"PRIu32":", odp_port);
             } else {
                 ds_put_cstr(ds, "none:");
@@ -6428,7 +6441,7 @@ ofproto_dpif_unixctl_init(void)
  * widespread use, we will delete these interfaces. */
 
 static int
-set_realdev(struct ofport *ofport_, uint16_t realdev_ofp_port, int vid)
+set_realdev(struct ofport *ofport_, ofp_port_t realdev_ofp_port, int vid)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport_->ofproto);
     struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
@@ -6460,9 +6473,9 @@ set_realdev(struct ofport *ofport_, uint16_t realdev_ofp_port, int vid)
 }
 
 static uint32_t
-hash_realdev_vid(uint16_t realdev_ofp_port, int vid)
+hash_realdev_vid(ofp_port_t realdev_ofp_port, int vid)
 {
-    return hash_2words(realdev_ofp_port, vid);
+    return hash_2words(ofp_to_u16(realdev_ofp_port), vid);
 }
 
 /* Returns the OFP port number of the Linux VLAN device that corresponds to
@@ -6472,9 +6485,9 @@ hash_realdev_vid(uint16_t realdev_ofp_port, int vid)
  *
  * Unless VLAN splinters are enabled for port 'realdev_ofp_port', this
  * function just returns its 'realdev_ofp_port' argument. */
-uint16_t
+ofp_port_t
 vsp_realdev_to_vlandev(const struct ofproto_dpif *ofproto,
-                       uint16_t realdev_ofp_port, ovs_be16 vlan_tci)
+                       ofp_port_t realdev_ofp_port, ovs_be16 vlan_tci)
 {
     if (!hmap_is_empty(&ofproto->realdev_vid_map)) {
         int vid = vlan_tci_to_vid(vlan_tci);
@@ -6493,11 +6506,12 @@ vsp_realdev_to_vlandev(const struct ofproto_dpif *ofproto,
 }
 
 static struct vlan_splinter *
-vlandev_find(const struct ofproto_dpif *ofproto, uint16_t vlandev_ofp_port)
+vlandev_find(const struct ofproto_dpif *ofproto, ofp_port_t vlandev_ofp_port)
 {
     struct vlan_splinter *vsp;
 
-    HMAP_FOR_EACH_WITH_HASH (vsp, vlandev_node, hash_int(vlandev_ofp_port, 0),
+    HMAP_FOR_EACH_WITH_HASH (vsp, vlandev_node,
+                             hash_int(ofp_to_u16(vlandev_ofp_port), 0),
                              &ofproto->vlandev_map) {
         if (vsp->vlandev_ofp_port == vlandev_ofp_port) {
             return vsp;
@@ -6516,9 +6530,9 @@ vlandev_find(const struct ofproto_dpif *ofproto, uint16_t vlandev_ofp_port)
  * Returns 0 and does not modify '*vid' if 'vlandev_ofp_port' is not a Linux
  * VLAN device.  Unless VLAN splinters are enabled, this is what this function
  * always does.*/
-static uint16_t
+static ofp_port_t
 vsp_vlandev_to_realdev(const struct ofproto_dpif *ofproto,
-                       uint16_t vlandev_ofp_port, int *vid)
+                       ofp_port_t vlandev_ofp_port, int *vid)
 {
     if (!hmap_is_empty(&ofproto->vlandev_map)) {
         const struct vlan_splinter *vsp;
@@ -6543,17 +6557,17 @@ vsp_vlandev_to_realdev(const struct ofproto_dpif *ofproto,
 static bool
 vsp_adjust_flow(const struct ofproto_dpif *ofproto, struct flow *flow)
 {
-    uint16_t realdev;
+    ofp_port_t realdev;
     int vid;
 
-    realdev = vsp_vlandev_to_realdev(ofproto, flow->in_port, &vid);
+    realdev = vsp_vlandev_to_realdev(ofproto, flow->in_port.ofp_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->in_port.ofp_port = realdev;
     flow->vlan_tci = htons((vid & VLAN_VID_MASK) | VLAN_CFI);
     return true;
 }
@@ -6577,7 +6591,7 @@ vsp_remove(struct ofport_dpif *port)
 }
 
 static void
-vsp_add(struct ofport_dpif *port, uint16_t realdev_ofp_port, int vid)
+vsp_add(struct ofport_dpif *port, ofp_port_t realdev_ofp_port, int vid)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto);
 
@@ -6588,7 +6602,7 @@ vsp_add(struct ofport_dpif *port, uint16_t realdev_ofp_port, int vid)
 
         vsp = xmalloc(sizeof *vsp);
         hmap_insert(&ofproto->vlandev_map, &vsp->vlandev_node,
-                    hash_int(port->up.ofp_port, 0));
+                    hash_int(ofp_to_u16(port->up.ofp_port), 0));
         hmap_insert(&ofproto->realdev_vid_map, &vsp->realdev_vid_node,
                     hash_realdev_vid(realdev_ofp_port, vid));
         vsp->realdev_ofp_port = realdev_ofp_port;
@@ -6601,20 +6615,20 @@ vsp_add(struct ofport_dpif *port, uint16_t realdev_ofp_port, int vid)
     }
 }
 
-uint32_t
-ofp_port_to_odp_port(const struct ofproto_dpif *ofproto, uint16_t ofp_port)
+odp_port_t
+ofp_port_to_odp_port(const struct ofproto_dpif *ofproto, ofp_port_t ofp_port)
 {
     const struct ofport_dpif *ofport = get_ofp_port(ofproto, ofp_port);
-    return ofport ? ofport->odp_port : OVSP_NONE;
+    return ofport ? ofport->odp_port : ODPP_NONE;
 }
 
 static struct ofport_dpif *
-odp_port_to_ofport(const struct dpif_backer *backer, uint32_t odp_port)
+odp_port_to_ofport(const struct dpif_backer *backer, odp_port_t odp_port)
 {
     struct ofport_dpif *port;
 
     HMAP_FOR_EACH_IN_BUCKET (port, odp_port_node,
-                             hash_int(odp_port, 0),
+                             hash_int(odp_to_u32(odp_port), 0),
                              &backer->odp_to_ofport_map) {
         if (port->odp_port == odp_port) {
             return port;
@@ -6624,8 +6638,8 @@ odp_port_to_ofport(const struct dpif_backer *backer, uint32_t odp_port)
     return NULL;
 }
 
-static uint16_t
-odp_port_to_ofp_port(const struct ofproto_dpif *ofproto, uint32_t odp_port)
+static ofp_port_t
+odp_port_to_ofp_port(const struct ofproto_dpif *ofproto, odp_port_t odp_port)
 {
     struct ofport_dpif *port;
 
diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
index 12a9d7e..b9f5eab 100644
--- a/ofproto/ofproto-dpif.h
+++ b/ofproto/ofproto-dpif.h
@@ -127,7 +127,7 @@ struct ofport_dpif {
     struct hmap_node odp_port_node; /* In dpif_backer's "odp_to_ofport_map". */
     struct ofport up;
 
-    uint32_t odp_port;
+    odp_port_t odp_port;
     struct ofbundle *bundle;    /* Bundle that contains this port, if any. */
     struct list bundle_node;    /* In struct ofbundle's "ports" list. */
     struct cfm *cfm;            /* Connectivity Fault Management, if any. */
@@ -151,7 +151,7 @@ struct ofport_dpif {
      * drivers in old versions of Linux that do not properly support VLANs when
      * VLAN devices are not used.  When broken device drivers are no longer in
      * widespread use, we will delete these interfaces. */
-    uint16_t realdev_ofp_port;
+    ofp_port_t realdev_ofp_port;
     int vlandev_vid;
 };
 
@@ -228,12 +228,13 @@ mirror_mask_ffs(mirror_mask_t mask)
 }
 
 struct ofport_dpif *get_ofp_port(const struct ofproto_dpif *,
-                                 uint16_t ofp_port);
+                                 ofp_port_t ofp_port);
 
 struct ofport_dpif *get_odp_port(const struct ofproto_dpif *,
-                                        uint32_t odp_port);
+                                        odp_port_t odp_port);
 
-uint32_t ofp_port_to_odp_port(const struct ofproto_dpif *, uint16_t ofp_port);
+odp_port_t ofp_port_to_odp_port(const struct ofproto_dpif *,
+                              ofp_port_t ofp_port);
 
 struct rule_dpif *rule_dpif_lookup_in_table(struct ofproto_dpif *,
                                             const struct flow *,
@@ -260,9 +261,9 @@ bool stp_should_process_flow(const struct flow *, struct flow_wildcards *);
 void stp_process_packet(const struct ofport_dpif *,
                         const struct ofpbuf *packet);
 
-uint16_t vsp_realdev_to_vlandev(const struct ofproto_dpif *,
-                                uint16_t realdev_ofp_port,
-                                ovs_be16 vlan_tci);
+ofp_port_t vsp_realdev_to_vlandev(const struct ofproto_dpif *,
+                                  ofp_port_t realdev_ofp_port,
+                                  ovs_be16 vlan_tci);
 
 bool ofproto_dpif_dscp_from_priority(const struct ofport_dpif *,
                                      uint32_t priority, uint8_t *dscp);
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index 41b589f..565cb01 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -63,8 +63,8 @@ struct ofproto {
     struct shash port_by_name;
     unsigned long *ofp_port_ids;/* Bitmap of used OpenFlow port numbers. */
     struct simap ofp_requests;  /* OpenFlow port number requests. */
-    uint16_t alloc_port_no;     /* Last allocated OpenFlow port number. */
-    uint16_t max_ports;         /* Max possible OpenFlow port num, plus one. */
+    ofp_port_t alloc_port_no;   /* Last allocated OpenFlow port number. */
+    ofp_port_t max_ports;       /* Max possible OpenFlow port num, plus one. */
 
     /* Flow tables. */
     struct oftable *tables;
@@ -103,10 +103,10 @@ struct ofproto {
 };
 
 void ofproto_init_tables(struct ofproto *, int n_tables);
-void ofproto_init_max_ports(struct ofproto *, uint16_t max_ports);
+void ofproto_init_max_ports(struct ofproto *, ofp_port_t max_ports);
 
 struct ofproto *ofproto_lookup(const char *name);
-struct ofport *ofproto_get_port(const struct ofproto *, uint16_t ofp_port);
+struct ofport *ofproto_get_port(const struct ofproto *, ofp_port_t ofp_port);
 
 /* An OpenFlow port within a "struct ofproto".
  *
@@ -117,7 +117,7 @@ struct ofport {
     struct ofproto *ofproto;    /* The ofproto that contains this port. */
     struct netdev *netdev;
     struct ofputil_phy_port pp;
-    uint16_t ofp_port;          /* OpenFlow port number. */
+    ofp_port_t ofp_port;        /* OpenFlow port number. */
     unsigned int change_seq;
     long long int created;      /* Time created, in msec. */
     int mtu;
@@ -248,12 +248,12 @@ void ofproto_rule_update_used(struct rule *, long long int used);
 void ofproto_rule_expire(struct rule *, uint8_t reason);
 void ofproto_rule_destroy(struct rule *);
 
-bool ofproto_rule_has_out_port(const struct rule *, uint16_t out_port);
+bool ofproto_rule_has_out_port(const struct rule *, ofp_port_t out_port);
 
 void ofoperation_complete(struct ofoperation *, enum ofperr);
 struct rule *ofoperation_get_victim(struct ofoperation *);
 
-bool ofoperation_has_out_port(const struct ofoperation *, uint16_t out_port);
+bool ofoperation_has_out_port(const struct ofoperation *, ofp_port_t out_port);
 
 bool ofproto_rule_is_hidden(const struct rule *);
 
@@ -694,7 +694,7 @@ struct ofproto_class {
      * It doesn't matter whether the new port will be returned by a later call
      * to ->port_poll(); the implementation may do whatever is more
      * convenient. */
-    int (*port_del)(struct ofproto *ofproto, uint16_t ofp_port);
+    int (*port_del)(struct ofproto *ofproto, ofp_port_t ofp_port);
 
     /* Get port stats */
     int (*port_get_stats)(const struct ofport *port,
@@ -1320,7 +1320,7 @@ struct ofproto_class {
      * This function should be NULL if a an implementation does not support
      * it. */
     int (*set_realdev)(struct ofport *ofport,
-                       uint16_t realdev_ofp_port, int vid);
+                       ofp_port_t realdev_ofp_port, int vid);
 };
 
 extern const struct ofproto_class ofproto_dpif_class;
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index eabe850..df2148e 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -449,7 +449,7 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
 
     /* The "max_ports" member should have been set by ->construct(ofproto).
      * Port 0 is not a valid OpenFlow port, so mark that as unavailable. */
-    ofproto->ofp_port_ids = bitmap_allocate(ofproto->max_ports);
+    ofproto->ofp_port_ids = bitmap_allocate(ofp_to_u16(ofproto->max_ports));
     bitmap_set1(ofproto->ofp_port_ids, 0);
 
     /* Check that hidden tables, if any, are at the end. */
@@ -498,9 +498,9 @@ ofproto_init_tables(struct ofproto *ofproto, int n_tables)
  * Reserved ports numbered OFPP_MAX and higher are special and not subject to
  * the 'max_ports' restriction. */
 void
-ofproto_init_max_ports(struct ofproto *ofproto, uint16_t max_ports)
+ofproto_init_max_ports(struct ofproto *ofproto, ofp_port_t max_ports)
 {
-    ovs_assert(max_ports <= OFPP_MAX);
+    ovs_assert(ofp_to_u16(max_ports) <= ofp_to_u16(OFPP_MAX));
     ofproto->max_ports = max_ports;
 }
 
@@ -707,7 +707,7 @@ ofproto_get_stp_status(struct ofproto *ofproto,
  *
  * Returns 0 if successful, otherwise a positive errno value.*/
 int
-ofproto_port_set_stp(struct ofproto *ofproto, uint16_t ofp_port,
+ofproto_port_set_stp(struct ofproto *ofproto, ofp_port_t ofp_port,
                      const struct ofproto_port_stp_settings *s)
 {
     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
@@ -728,7 +728,7 @@ ofproto_port_set_stp(struct ofproto *ofproto, uint16_t ofp_port,
  *
  * Returns 0 if successful, otherwise a positive errno value.*/
 int
-ofproto_port_get_stp_status(struct ofproto *ofproto, uint16_t ofp_port,
+ofproto_port_get_stp_status(struct ofproto *ofproto, ofp_port_t ofp_port,
                             struct ofproto_port_stp_status *s)
 {
     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
@@ -753,7 +753,7 @@ ofproto_port_get_stp_status(struct ofproto *ofproto, uint16_t ofp_port,
  *
  * Returns 0 if successful, otherwise a positive errno value. */
 int
-ofproto_port_set_queues(struct ofproto *ofproto, uint16_t ofp_port,
+ofproto_port_set_queues(struct ofproto *ofproto, ofp_port_t ofp_port,
                         const struct ofproto_port_queue *queues,
                         size_t n_queues)
 {
@@ -774,7 +774,7 @@ ofproto_port_set_queues(struct ofproto *ofproto, uint16_t ofp_port,
 
 /* Clears the CFM configuration from 'ofp_port' on 'ofproto'. */
 void
-ofproto_port_clear_cfm(struct ofproto *ofproto, uint16_t ofp_port)
+ofproto_port_clear_cfm(struct ofproto *ofproto, ofp_port_t ofp_port)
 {
     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
     if (ofport && ofproto->ofproto_class->set_cfm) {
@@ -789,7 +789,7 @@ ofproto_port_clear_cfm(struct ofproto *ofproto, uint16_t ofp_port)
  *
  * This function has no effect if 'ofproto' does not have a port 'ofp_port'. */
 void
-ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port,
+ofproto_port_set_cfm(struct ofproto *ofproto, ofp_port_t ofp_port,
                      const struct cfm_settings *s)
 {
     struct ofport *ofport;
@@ -818,7 +818,7 @@ ofproto_port_set_cfm(struct ofproto *ofproto, uint16_t ofp_port,
 /* Configures BFD on 'ofp_port' in 'ofproto'.  This function has no effect if
  * 'ofproto' does not have a port 'ofp_port'. */
 void
-ofproto_port_set_bfd(struct ofproto *ofproto, uint16_t ofp_port,
+ofproto_port_set_bfd(struct ofproto *ofproto, ofp_port_t ofp_port,
                      const struct smap *cfg)
 {
     struct ofport *ofport;
@@ -846,7 +846,7 @@ ofproto_port_set_bfd(struct ofproto *ofproto, uint16_t ofp_port,
  * OVS database.  Has no effect if 'ofp_port' is not na OpenFlow port in
  * 'ofproto'. */
 int
-ofproto_port_get_bfd_status(struct ofproto *ofproto, uint16_t ofp_port,
+ofproto_port_get_bfd_status(struct ofproto *ofproto, ofp_port_t ofp_port,
                             struct smap *status)
 {
     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
@@ -860,7 +860,7 @@ ofproto_port_get_bfd_status(struct ofproto *ofproto, uint16_t ofp_port,
  * 0 if LACP partner information is not current (generally indicating a
  * connectivity problem), or -1 if LACP is not enabled on 'ofp_port'. */
 int
-ofproto_port_is_lacp_current(struct ofproto *ofproto, uint16_t ofp_port)
+ofproto_port_is_lacp_current(struct ofproto *ofproto, ofp_port_t ofp_port)
 {
     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
     return (ofport && ofproto->ofproto_class->port_is_lacp_current
@@ -1497,16 +1497,17 @@ ofproto_port_open_type(const char *datapath_type, const char *port_type)
  * 'ofp_portp' is non-null). */
 int
 ofproto_port_add(struct ofproto *ofproto, struct netdev *netdev,
-                 uint16_t *ofp_portp)
+                 ofp_port_t *ofp_portp)
 {
-    uint16_t ofp_port = ofp_portp ? *ofp_portp : OFPP_NONE;
+    ofp_port_t ofp_port = ofp_portp ? *ofp_portp : OFPP_NONE;
     int error;
 
     error = ofproto->ofproto_class->port_add(ofproto, netdev);
     if (!error) {
         const char *netdev_name = netdev_get_name(netdev);
 
-        simap_put(&ofproto->ofp_requests, netdev_name, ofp_port);
+        simap_put(&ofproto->ofp_requests, netdev_name,
+                  ofp_to_u16(ofp_port));
         update_port(ofproto, netdev_name);
     }
     if (ofp_portp) {
@@ -1542,7 +1543,7 @@ ofproto_port_query_by_name(const struct ofproto *ofproto, const char *devname,
 /* Deletes port number 'ofp_port' from the datapath for 'ofproto'.
  * Returns 0 if successful, otherwise a positive errno. */
 int
-ofproto_port_del(struct ofproto *ofproto, uint16_t ofp_port)
+ofproto_port_del(struct ofproto *ofproto, ofp_port_t ofp_port)
 {
     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
     const char *name = ofport ? netdev_get_name(ofport->netdev) : "<unknown>";
@@ -1679,43 +1680,45 @@ reinit_ports(struct ofproto *p)
     sset_destroy(&devnames);
 }
 
-static uint16_t
+static ofp_port_t
 alloc_ofp_port(struct ofproto *ofproto, const char *netdev_name)
 {
-    uint16_t ofp_port;
-    uint16_t end_port_no = ofproto->alloc_port_no;
+    ofp_port_t ofp_port;
+    uint16_t end_port_no = ofp_to_u16(ofproto->alloc_port_no);
 
-    ofp_port = simap_get(&ofproto->ofp_requests, netdev_name);
+    ofp_port = u16_to_ofp(simap_get(&ofproto->ofp_requests, netdev_name));
     ofp_port = ofp_port ? ofp_port : OFPP_NONE;
 
-    if (ofp_port >= ofproto->max_ports
-            || bitmap_is_set(ofproto->ofp_port_ids, ofp_port)) {
+    if (ofp_to_u16(ofp_port) >= ofp_to_u16(ofproto->max_ports)
+        || bitmap_is_set(ofproto->ofp_port_ids, ofp_to_u16(ofp_port))) {
+        uint16_t alloc_port_no = ofp_to_u16(ofproto->alloc_port_no);
+
         /* Search for a free OpenFlow port number.  We try not to
          * immediately reuse them to prevent problems due to old
          * flows. */
         for (;;) {
-            if (++ofproto->alloc_port_no >= ofproto->max_ports) {
-                ofproto->alloc_port_no = 0;
+            if (++alloc_port_no >= ofp_to_u16(ofproto->max_ports)) {
+                alloc_port_no = 0;
             }
-            if (!bitmap_is_set(ofproto->ofp_port_ids,
-                               ofproto->alloc_port_no)) {
-                ofp_port = ofproto->alloc_port_no;
+            if (!bitmap_is_set(ofproto->ofp_port_ids, alloc_port_no)) {
+                ofp_port = u16_to_ofp(alloc_port_no);
+                ofproto->alloc_port_no = ofp_port;
                 break;
             }
-            if (ofproto->alloc_port_no == end_port_no) {
+            if (alloc_port_no == end_port_no) {
                 return OFPP_NONE;
             }
         }
     }
-    bitmap_set1(ofproto->ofp_port_ids, ofp_port);
+    bitmap_set1(ofproto->ofp_port_ids, ofp_to_u16(ofp_port));
     return ofp_port;
 }
 
 static void
-dealloc_ofp_port(const struct ofproto *ofproto, uint16_t ofp_port)
+dealloc_ofp_port(const struct ofproto *ofproto, ofp_port_t ofp_port)
 {
-    if (ofp_port < ofproto->max_ports) {
-        bitmap_set0(ofproto->ofp_port_ids, ofp_port);
+    if (ofp_to_u16(ofp_port) < ofp_to_u16(ofproto->max_ports)) {
+        bitmap_set0(ofproto->ofp_port_ids, ofp_to_u16(ofp_port));
     }
 }
 
@@ -1806,7 +1809,8 @@ ofport_install(struct ofproto *p,
     ofport->created = time_msec();
 
     /* Add port to 'p'. */
-    hmap_insert(&p->ports, &ofport->hmap_node, hash_int(ofport->ofp_port, 0));
+    hmap_insert(&p->ports, &ofport->hmap_node,
+                hash_int(ofp_to_u16(ofport->ofp_port), 0));
     shash_add(&p->port_by_name, netdev_name, ofport);
 
     update_mtu(p, ofport);
@@ -1882,7 +1886,7 @@ ofproto_port_set_state(struct ofport *port, enum ofputil_port_state state)
 }
 
 void
-ofproto_port_unregister(struct ofproto *ofproto, uint16_t ofp_port)
+ofproto_port_unregister(struct ofproto *ofproto, ofp_port_t ofp_port)
 {
     struct ofport *port = ofproto_get_port(ofproto, ofp_port);
     if (port) {
@@ -1926,12 +1930,13 @@ ofport_destroy(struct ofport *port)
 }
 
 struct ofport *
-ofproto_get_port(const struct ofproto *ofproto, uint16_t ofp_port)
+ofproto_get_port(const struct ofproto *ofproto, ofp_port_t ofp_port)
 {
     struct ofport *port;
 
     HMAP_FOR_EACH_IN_BUCKET (port, hmap_node,
-                             hash_int(ofp_port, 0), &ofproto->ports) {
+                             hash_int(ofp_to_u16(ofp_port), 0),
+                             &ofproto->ports) {
         if (port->ofp_port == ofp_port) {
             return port;
         }
@@ -1968,6 +1973,7 @@ update_port(struct ofproto *ofproto, const char *name)
     netdev = (!ofproto_port_query_by_name(ofproto, name, &ofproto_port)
               ? ofport_open(ofproto, &ofproto_port, &pp)
               : NULL);
+
     if (netdev) {
         port = ofproto_get_port(ofproto, ofproto_port.ofp_port);
         if (port && !strcmp(netdev_get_name(port->netdev), name)) {
@@ -2029,7 +2035,8 @@ init_ports(struct ofproto *p)
             node = shash_find(&init_ofp_ports, name);
             if (node) {
                 const struct iface_hint *iface_hint = node->data;
-                simap_put(&p->ofp_requests, name, iface_hint->ofp_port);
+                simap_put(&p->ofp_requests, name,
+                          ofp_to_u16(iface_hint->ofp_port));
             }
 
             netdev = ofport_open(p, &ofproto_port, &pp);
@@ -2153,7 +2160,7 @@ ofproto_rule_destroy(struct rule *rule)
 /* Returns true if 'rule' has an OpenFlow OFPAT_OUTPUT or OFPAT_ENQUEUE action
  * that outputs to 'port' (output to OFPP_FLOOD and OFPP_ALL doesn't count). */
 bool
-ofproto_rule_has_out_port(const struct rule *rule, uint16_t port)
+ofproto_rule_has_out_port(const struct rule *rule, ofp_port_t port)
 {
     return (port == OFPP_ANY
             || ofpacts_output_to_port(rule->ofpacts, rule->ofpacts_len, port));
@@ -2162,7 +2169,7 @@ ofproto_rule_has_out_port(const struct rule *rule, uint16_t port)
 /* Returns true if a rule related to 'op' has an OpenFlow OFPAT_OUTPUT or
  * OFPAT_ENQUEUE action that outputs to 'out_port'. */
 bool
-ofoperation_has_out_port(const struct ofoperation *op, uint16_t out_port)
+ofoperation_has_out_port(const struct ofoperation *op, ofp_port_t out_port)
 {
     if (ofproto_rule_has_out_port(op->rule, out_port)) {
         return true;
@@ -2191,13 +2198,15 @@ ofoperation_has_out_port(const struct ofoperation *op, uint16_t out_port)
  *
  * Takes ownership of 'packet'. */
 static int
-rule_execute(struct rule *rule, uint16_t in_port, struct ofpbuf *packet)
+rule_execute(struct rule *rule, ofp_port_t in_port, struct ofpbuf *packet)
 {
     struct flow flow;
+    union flow_in_port in_port_;
 
     ovs_assert(ofpbuf_headroom(packet) >= sizeof(struct ofp10_packet_in));
 
-    flow_extract(packet, 0, 0, NULL, in_port, &flow);
+    in_port_.ofp_port = in_port;
+    flow_extract(packet, 0, 0, NULL, &in_port_, &flow);
     return rule->ofproto->ofproto_class->rule_execute(rule, &flow, packet);
 }
 
@@ -2358,6 +2367,7 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh)
     uint64_t ofpacts_stub[1024 / 8];
     struct ofpbuf ofpacts;
     struct flow flow;
+    union flow_in_port in_port_;
     enum ofperr error;
 
     COVERAGE_INC(ofproto_packet_out);
@@ -2373,7 +2383,8 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh)
     if (error) {
         goto exit_free_ofpacts;
     }
-    if (po.in_port >= p->max_ports && po.in_port < OFPP_MAX) {
+    if (ofp_to_u16(po.in_port) >= ofp_to_u16(p->max_ports)
+        && ofp_to_u16(po.in_port) < ofp_to_u16(OFPP_MAX)) {
         error = OFPERR_OFPBRC_BAD_PORT;
         goto exit_free_ofpacts;
     }
@@ -2391,7 +2402,8 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_header *oh)
     }
 
     /* Verify actions against packet, then send packet if successful. */
-    flow_extract(payload, 0, 0, NULL, po.in_port, &flow);
+    in_port_.ofp_port = po.in_port;
+    flow_extract(payload, 0, 0, NULL, &in_port_, &flow);
     error = ofpacts_check(po.ofpacts, po.ofpacts_len, &flow, p->max_ports);
     if (!error) {
         error = p->ofproto_class->packet_out(p, payload, &flow,
@@ -2579,7 +2591,7 @@ handle_port_stats_request(struct ofconn *ofconn,
     struct ofproto *p = ofconn_get_ofproto(ofconn);
     struct ofport *port;
     struct list replies;
-    uint16_t port_no;
+    ofp_port_t port_no;
     enum ofperr error;
 
     error = ofputil_decode_port_stats_request(request, &port_no);
@@ -2748,7 +2760,7 @@ static enum ofperr
 collect_rules_loose(struct ofproto *ofproto, uint8_t table_id,
                     const struct match *match,
                     ovs_be64 cookie, ovs_be64 cookie_mask,
-                    uint16_t out_port, struct list *rules)
+                    ofp_port_t out_port, struct list *rules)
 {
     struct oftable *table;
     struct cls_rule cr;
@@ -2825,7 +2837,7 @@ static enum ofperr
 collect_rules_strict(struct ofproto *ofproto, uint8_t table_id,
                      const struct match *match, unsigned int priority,
                      ovs_be64 cookie, ovs_be64 cookie_mask,
-                     uint16_t out_port, struct list *rules)
+                     ofp_port_t out_port, struct list *rules)
 {
     struct oftable *table;
     struct cls_rule cr;
@@ -3008,7 +3020,7 @@ ofproto_get_netflow_ids(const struct ofproto *ofproto,
  * The caller must provide and owns '*status', but it does not own and must not
  * modify or free the array returned in 'status->rmps'. */
 bool
-ofproto_port_get_cfm_status(const struct ofproto *ofproto, uint16_t ofp_port,
+ofproto_port_get_cfm_status(const struct ofproto *ofproto, ofp_port_t ofp_port,
                             struct ofproto_cfm_status *status)
 {
     struct ofport *ofport = ofproto_get_port(ofproto, ofp_port);
@@ -4331,7 +4343,7 @@ ofopgroup_complete(struct ofopgroup *group)
         LIST_FOR_EACH (op, group_node, &group->ops) {
             if (op->type != OFOPERATION_DELETE) {
                 struct ofpbuf *packet;
-                uint16_t in_port;
+                ofp_port_t in_port;
 
                 error = ofconn_pktbuf_retrieve(group->ofconn, group->buffer_id,
                                                &packet, &in_port);
@@ -5088,8 +5100,8 @@ ofproto_has_vlan_usage_changed(const struct ofproto *ofproto)
  * device as a VLAN splinter for VLAN ID 'vid'.  If 'realdev_ofp_port' is zero,
  * then the VLAN device is un-enslaved. */
 int
-ofproto_port_set_realdev(struct ofproto *ofproto, uint16_t vlandev_ofp_port,
-                         uint16_t realdev_ofp_port, int vid)
+ofproto_port_set_realdev(struct ofproto *ofproto, ofp_port_t vlandev_ofp_port,
+                         ofp_port_t realdev_ofp_port, int vid)
 {
     struct ofport *ofport;
     int error;
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index 5f8244c..2609c94 100644
--- a/ofproto/ofproto.h
+++ b/ofproto/ofproto.h
@@ -158,7 +158,7 @@ void ofproto_parse_name(const char *name, char **dp_name, char **dp_type);
 struct iface_hint {
     char *br_name;              /* Name of owning bridge. */
     char *br_type;              /* Type of owning bridge. */
-    uint16_t ofp_port;          /* OpenFlow port number. */
+    ofp_port_t ofp_port;        /* OpenFlow port number. */
 };
 
 void ofproto_init(const struct shash *iface_hints);
@@ -185,7 +185,7 @@ void ofproto_get_memory_usage(const struct ofproto *, struct simap *);
 struct ofproto_port {
     char *name;                 /* Network device name, e.g. "eth0". */
     char *type;                 /* Network device type, e.g. "system". */
-    uint16_t ofp_port;          /* OpenFlow port number. */
+    ofp_port_t ofp_port;        /* OpenFlow port number. */
 };
 void ofproto_port_clone(struct ofproto_port *, const struct ofproto_port *);
 void ofproto_port_destroy(struct ofproto_port *);
@@ -218,8 +218,8 @@ int ofproto_port_dump_done(struct ofproto_port_dump *);
 
 const char *ofproto_port_open_type(const char *datapath_type,
                                    const char *port_type);
-int ofproto_port_add(struct ofproto *, struct netdev *, uint16_t *ofp_portp);
-int ofproto_port_del(struct ofproto *, uint16_t ofp_port);
+int ofproto_port_add(struct ofproto *, struct netdev *, ofp_port_t *ofp_portp);
+int ofproto_port_del(struct ofproto *, ofp_port_t ofp_port);
 int ofproto_port_get_stats(const struct ofport *, struct netdev_stats *stats);
 
 int ofproto_port_query_by_name(const struct ofproto *, const char *devname,
@@ -255,21 +255,21 @@ int ofproto_set_stp(struct ofproto *, const struct ofproto_stp_settings *);
 int ofproto_get_stp_status(struct ofproto *, struct ofproto_stp_status *);
 
 /* Configuration of ports. */
-void ofproto_port_unregister(struct ofproto *, uint16_t ofp_port);
+void ofproto_port_unregister(struct ofproto *, ofp_port_t ofp_port);
 
-void ofproto_port_clear_cfm(struct ofproto *, uint16_t ofp_port);
-void ofproto_port_set_cfm(struct ofproto *, uint16_t ofp_port,
+void ofproto_port_clear_cfm(struct ofproto *, ofp_port_t ofp_port);
+void ofproto_port_set_cfm(struct ofproto *, ofp_port_t ofp_port,
                           const struct cfm_settings *);
-void ofproto_port_set_bfd(struct ofproto *, uint16_t ofp_port,
+void ofproto_port_set_bfd(struct ofproto *, ofp_port_t ofp_port,
                           const struct smap *cfg);
-int ofproto_port_get_bfd_status(struct ofproto *, uint16_t ofp_port,
+int ofproto_port_get_bfd_status(struct ofproto *, ofp_port_t ofp_port,
                                 struct smap *);
-int ofproto_port_is_lacp_current(struct ofproto *, uint16_t ofp_port);
-int ofproto_port_set_stp(struct ofproto *, uint16_t ofp_port,
+int ofproto_port_is_lacp_current(struct ofproto *, ofp_port_t ofp_port);
+int ofproto_port_set_stp(struct ofproto *, ofp_port_t ofp_port,
                          const struct ofproto_port_stp_settings *);
-int ofproto_port_get_stp_status(struct ofproto *, uint16_t ofp_port,
+int ofproto_port_get_stp_status(struct ofproto *, ofp_port_t ofp_port,
                                 struct ofproto_port_stp_status *);
-int ofproto_port_set_queues(struct ofproto *, uint16_t ofp_port,
+int ofproto_port_set_queues(struct ofproto *, ofp_port_t ofp_port,
                             const struct ofproto_port_queue *,
                             size_t n_queues);
 
@@ -298,7 +298,7 @@ enum port_vlan_mode {
 struct ofproto_bundle_settings {
     char *name;                 /* For use in log messages. */
 
-    uint16_t *slaves;           /* OpenFlow port numbers for slaves. */
+    ofp_port_t *slaves;         /* OpenFlow port numbers for slaves. */
     size_t n_slaves;
 
     enum port_vlan_mode vlan_mode; /* Selects mode for vlan and trunks */
@@ -317,7 +317,7 @@ struct ofproto_bundle_settings {
      * drivers in old versions of Linux that do not properly support VLANs when
      * VLAN devices are not used.  When broken device drivers are no longer in
      * widespread use, we will delete these interfaces. */
-    uint16_t realdev_ofp_port;  /* OpenFlow port number of real device. */
+    ofp_port_t realdev_ofp_port;/* OpenFlow port number of real device. */
 };
 
 int ofproto_bundle_register(struct ofproto *, void *aux,
@@ -406,7 +406,8 @@ struct ofproto_cfm_status {
     size_t n_rmps;
 };
 
-bool ofproto_port_get_cfm_status(const struct ofproto *, uint16_t ofp_port,
+bool ofproto_port_get_cfm_status(const struct ofproto *,
+                                 ofp_port_t ofp_port,
                                  struct ofproto_cfm_status *);
 
 /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
@@ -418,8 +419,8 @@ bool ofproto_port_get_cfm_status(const struct ofproto *, uint16_t ofp_port,
 
 void ofproto_get_vlan_usage(struct ofproto *, unsigned long int *vlan_bitmap);
 bool ofproto_has_vlan_usage_changed(const struct ofproto *);
-int ofproto_port_set_realdev(struct ofproto *, uint16_t vlandev_ofp_port,
-                             uint16_t realdev_ofp_port, int vid);
+int ofproto_port_set_realdev(struct ofproto *, ofp_port_t vlandev_ofp_port,
+                             ofp_port_t realdev_ofp_port, int vid);
 
 #ifdef  __cplusplus
 }
diff --git a/ofproto/pinsched.c b/ofproto/pinsched.c
index 57e8e23..4c5f3e8 100644
--- a/ofproto/pinsched.c
+++ b/ofproto/pinsched.c
@@ -21,6 +21,7 @@
 #include <arpa/inet.h>
 #include <stdint.h>
 #include <stdlib.h>
+#include "flow.h"
 #include "hash.h"
 #include "hmap.h"
 #include "ofpbuf.h"
@@ -35,7 +36,7 @@
 
 struct pinqueue {
     struct hmap_node node;      /* In struct pinsched's 'queues' hmap. */
-    uint16_t port_no;           /* Port number. */
+    ofp_port_t port_no;           /* Port number. */
     struct list packets;        /* Contains "struct ofpbuf"s. */
     int n;                      /* Number of packets in 'packets'. */
 };
@@ -101,9 +102,9 @@ pinqueue_destroy(struct pinsched *ps, struct pinqueue *q)
 }
 
 static struct pinqueue *
-pinqueue_get(struct pinsched *ps, uint16_t port_no)
+pinqueue_get(struct pinsched *ps, ofp_port_t port_no)
 {
-    uint32_t hash = hash_int(port_no, 0);
+    uint32_t hash = hash_int(ofp_to_u16(port_no), 0);
     struct pinqueue *q;
 
     HMAP_FOR_EACH_IN_BUCKET (q, node, hash, &ps->queues) {
@@ -184,7 +185,7 @@ get_token(struct pinsched *ps)
 }
 
 void
-pinsched_send(struct pinsched *ps, uint16_t port_no,
+pinsched_send(struct pinsched *ps, ofp_port_t port_no,
               struct ofpbuf *packet, pinsched_tx_cb *cb, void *aux)
 {
     if (!ps) {
diff --git a/ofproto/pinsched.h b/ofproto/pinsched.h
index 061cb01..06b22f4 100644
--- a/ofproto/pinsched.h
+++ b/ofproto/pinsched.h
@@ -18,6 +18,7 @@
 #define PINSCHED_H_H 1
 
 #include <stdint.h>
+#include "flow.h"
 
 struct ofpbuf;
 
@@ -27,7 +28,7 @@ void pinsched_get_limits(const struct pinsched *,
                          int *rate_limit, int *burst_limit);
 void pinsched_set_limits(struct pinsched *, int rate_limit, int burst_limit);
 void pinsched_destroy(struct pinsched *);
-void pinsched_send(struct pinsched *, uint16_t port_no, struct ofpbuf *,
+void pinsched_send(struct pinsched *, ofp_port_t port_no, struct ofpbuf *,
                    pinsched_tx_cb *, void *aux);
 void pinsched_run(struct pinsched *, pinsched_tx_cb *, void *aux);
 void pinsched_wait(struct pinsched *);
diff --git a/ofproto/pktbuf.c b/ofproto/pktbuf.c
index 2ec1f0d..65fcef6 100644
--- a/ofproto/pktbuf.c
+++ b/ofproto/pktbuf.c
@@ -51,7 +51,7 @@ struct packet {
     struct ofpbuf *buffer;
     uint32_t cookie;
     long long int timeout;
-    uint16_t in_port;
+    ofp_port_t in_port;
 };
 
 struct pktbuf {
@@ -104,7 +104,7 @@ make_id(unsigned int buffer_idx, unsigned int cookie)
  * The caller retains ownership of 'buffer'. */
 uint32_t
 pktbuf_save(struct pktbuf *pb, const void *buffer, size_t buffer_size,
-            uint16_t in_port)
+            ofp_port_t in_port)
 {
     struct packet *p = &pb->packets[pb->buffer_idx];
     pb->buffer_idx = (pb->buffer_idx + 1) & PKTBUF_MASK;
@@ -161,7 +161,7 @@ pktbuf_get_null(void)
  * OpenFlow port number on which the packet was received in '*in_port'.  The
  * caller becomes responsible for freeing the buffer.  However, if 'id'
  * identifies a "null" packet buffer (created with pktbuf_get_null()), stores
- * NULL in '*bufferp' and UINT16_max in '*in_port'.
+ * NULL in '*bufferp' and OFPP_NONE in '*in_port'.
  *
  * 'in_port' may be NULL if the input port is not of interest.
  *
@@ -171,7 +171,7 @@ pktbuf_get_null(void)
  * On failure, stores NULL in in '*bufferp' and UINT16_MAX in '*in_port'. */
 enum ofperr
 pktbuf_retrieve(struct pktbuf *pb, uint32_t id, struct ofpbuf **bufferp,
-                uint16_t *in_port)
+                ofp_port_t *in_port)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 20);
     struct packet *p;
@@ -218,7 +218,7 @@ pktbuf_retrieve(struct pktbuf *pb, uint32_t id, struct ofpbuf **bufferp,
 error:
     *bufferp = NULL;
     if (in_port) {
-        *in_port = UINT16_MAX;
+        *in_port = OFPP_NONE;
     }
     return error;
 }
diff --git a/ofproto/pktbuf.h b/ofproto/pktbuf.h
index ec99aea..eb1b1ff 100644
--- a/ofproto/pktbuf.h
+++ b/ofproto/pktbuf.h
@@ -30,10 +30,10 @@ int pktbuf_capacity(void);
 struct pktbuf *pktbuf_create(void);
 void pktbuf_destroy(struct pktbuf *);
 uint32_t pktbuf_save(struct pktbuf *, const void *buffer, size_t buffer_size,
-                     uint16_t in_port);
+                     ofp_port_t in_port);
 uint32_t pktbuf_get_null(void);
 enum ofperr pktbuf_retrieve(struct pktbuf *, uint32_t id,
-                            struct ofpbuf **bufferp, uint16_t *in_port);
+                            struct ofpbuf **bufferp, ofp_port_t *in_port);
 void pktbuf_discard(struct pktbuf *, uint32_t id);
 
 unsigned int pktbuf_count_packets(const struct pktbuf *);
diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
index 636c549..dedfca8 100644
--- a/ofproto/tunnel.c
+++ b/ofproto/tunnel.c
@@ -36,7 +36,7 @@ struct tnl_match {
     ovs_be64 in_key;
     ovs_be32 ip_src;
     ovs_be32 ip_dst;
-    uint32_t odp_port;
+    odp_port_t odp_port;
     uint32_t skb_mark;
     bool in_key_flow;
     bool ip_src_flow;
@@ -71,7 +71,7 @@ static void tnl_port_mod_log(const struct tnl_port *, const char *action);
 static const char *tnl_port_get_name(const struct tnl_port *);
 
 static struct tnl_port *
-tnl_port_add__(const struct ofport *ofport, uint32_t odp_port,
+tnl_port_add__(const struct ofport *ofport, odp_port_t odp_port,
                bool warn)
 {
     const struct netdev_tunnel_config *cfg;
@@ -118,7 +118,7 @@ tnl_port_add__(const struct ofport *ofport, uint32_t odp_port,
  * must be added before they can be used by the module. 'ofport' must be a
  * tunnel. */
 struct tnl_port *
-tnl_port_add(const struct ofport *ofport, uint32_t odp_port)
+tnl_port_add(const struct ofport *ofport, odp_port_t odp_port)
 {
     return tnl_port_add__(ofport, odp_port, true);
 }
@@ -129,7 +129,7 @@ tnl_port_add(const struct ofport *ofport, uint32_t odp_port)
  * 'ofport' and 'odp_port' should be the same as would be passed to
  * tnl_port_add(). */
 bool
-tnl_port_reconfigure(const struct ofport *ofport, uint32_t odp_port,
+tnl_port_reconfigure(const struct ofport *ofport, odp_port_t odp_port,
                      struct tnl_port **tnl_portp)
 {
     struct tnl_port *tnl_port = *tnl_portp;
@@ -173,7 +173,7 @@ tnl_port_receive(const struct flow *flow)
     struct tnl_match match;
 
     memset(&match, 0, sizeof match);
-    match.odp_port = flow->in_port;
+    match.odp_port = flow->in_port.odp_port;
     match.ip_src = flow->tunnel.ip_dst;
     match.ip_dst = flow->tunnel.ip_src;
     match.in_key = flow->tunnel.tun_id;
@@ -210,9 +210,9 @@ tnl_port_receive(const struct flow *flow)
 
 /* Given that 'flow' should be output to the ofport corresponding to
  * 'tnl_port', updates 'flow''s tunnel headers and returns the actual datapath
- * port that the output should happen on.  May return OVSP_NONE if the output
+ * port that the output should happen on.  May return ODPP_NONE if the output
  * shouldn't occur. */
-uint32_t
+odp_port_t
 tnl_port_send(const struct tnl_port *tnl_port, struct flow *flow,
               struct flow_wildcards *wc)
 {
@@ -220,7 +220,7 @@ tnl_port_send(const struct tnl_port *tnl_port, struct flow *flow,
     char *pre_flow_str = NULL;
 
     if (tnl_port == &void_tnl_port) {
-        return OVSP_NONE;
+        return ODPP_NONE;
     }
 
     cfg = netdev_get_tunnel_config(tnl_port->ofport->netdev);
diff --git a/ofproto/tunnel.h b/ofproto/tunnel.h
index 803e2d9..343eb96 100644
--- a/ofproto/tunnel.h
+++ b/ofproto/tunnel.h
@@ -31,15 +31,15 @@
 struct ofport;
 struct tnl_port;
 
-bool tnl_port_reconfigure(const struct ofport *, uint32_t odp_port,
+bool tnl_port_reconfigure(const struct ofport *, odp_port_t odp_port,
                           struct tnl_port **);
 
-struct tnl_port *tnl_port_add(const struct ofport *, uint32_t odp_port);
+struct tnl_port *tnl_port_add(const struct ofport *, odp_port_t odp_port);
 void tnl_port_del(struct tnl_port *);
 
 const struct ofport *tnl_port_receive(const struct flow *);
-uint32_t tnl_port_send(const struct tnl_port *, struct flow *,
-                       struct flow_wildcards *wc);
+odp_port_t tnl_port_send(const struct tnl_port *, struct flow *,
+                         struct flow_wildcards *wc);
 
 /* Returns true if 'flow' should be submitted to tnl_port_receive(). */
 static inline bool
diff --git a/tests/test-bundle.c b/tests/test-bundle.c
index c475991..0e7525c 100644
--- a/tests/test-bundle.c
+++ b/tests/test-bundle.c
@@ -31,7 +31,7 @@
 #define MAX_SLAVES 8 /* Maximum supported by this test framework. */
 
 struct slave {
-    uint16_t slave_id;
+    ofp_port_t slave_id;
 
     bool enabled;
     size_t flow_count;
@@ -43,7 +43,7 @@ struct slave_group {
 };
 
 static struct slave *
-slave_lookup(struct slave_group *sg, uint16_t slave_id)
+slave_lookup(struct slave_group *sg, ofp_port_t slave_id)
 {
     size_t i;
 
@@ -57,7 +57,7 @@ slave_lookup(struct slave_group *sg, uint16_t slave_id)
 }
 
 static bool
-slave_enabled_cb(uint16_t slave_id, void *aux)
+slave_enabled_cb(ofp_port_t slave_id, void *aux)
 {
     struct slave *slave;
 
@@ -122,7 +122,7 @@ main(int argc, char *argv[])
     /* Generate 'slaves' array. */
     sg.n_slaves = 0;
     for (i = 0; i < bundle->n_slaves; i++) {
-        uint16_t slave_id = bundle->slaves[i];
+        ofp_port_t slave_id = bundle->slaves[i];
 
         if (slave_lookup(&sg, slave_id)) {
             ovs_fatal(0, "Redundant slaves are not supported. ");
@@ -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].regs[0] = ofp_to_u16(OFPP_NONE);
     }
 
     /* Cycles through each possible liveness permutation for the given
@@ -186,13 +186,13 @@ main(int argc, char *argv[])
         changed = 0;
         for (j = 0; j < N_FLOWS; j++) {
             struct flow *flow = &flows[j];
-            uint16_t old_slave_id, ofp_port;
+            ofp_port_t old_slave_id, ofp_port;
             struct flow_wildcards wc;
 
-            old_slave_id = flow->regs[0];
+            old_slave_id = u16_to_ofp(flow->regs[0]);
             ofp_port = bundle_execute(bundle, flow, &wc, slave_enabled_cb,
                                       &sg);
-            flow->regs[0] = ofp_port;
+            flow->regs[0] = ofp_to_u16(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 f616494..cd081a5 100644
--- a/tests/test-classifier.c
+++ b/tests/test-classifier.c
@@ -240,8 +240,9 @@ 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->in_port.ofp_port
+                    ^ wild.flow.in_port.ofp_port)
+                   & wild.wc.masks.in_port.ofp_port);
         } else {
             NOT_REACHED();
         }
@@ -298,7 +299,7 @@ static ovs_be64 tun_id_values[] = {
 static ovs_be64 metadata_values[] = {
     0,
     CONSTANT_HTONLL(UINT64_C(0xfedcba9876543210)) };
-static uint16_t in_port_values[] = { 1, OFPP_LOCAL };
+static ofp_port_t in_port_values[] = { OFP_PORT_C(1), OFPP_LOCAL };
 static ovs_be16 vlan_tci_values[] = { CONSTANT_HTONS(101), CONSTANT_HTONS(0) };
 static ovs_be16 dl_type_values[]
             = { CONSTANT_HTONS(ETH_TYPE_IP), CONSTANT_HTONS(ETH_TYPE_ARP) };
@@ -410,7 +411,8 @@ compare_classifiers(struct classifier *cls, struct tcls *tcls)
         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.in_port.ofp_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)];
@@ -546,7 +548,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.in_port.ofp_port = OFPP_NONE;
         } else {
             NOT_REACHED();
         }
diff --git a/tests/test-flows.c b/tests/test-flows.c
index c77372f..8308bf8 100644
--- a/tests/test-flows.c
+++ b/tests/test-flows.c
@@ -58,7 +58,7 @@ main(int argc OVS_UNUSED, char *argv[])
         struct ofp10_match extracted_match;
         struct match match;
         struct flow flow;
-
+        union flow_in_port in_port_;
         n++;
 
         retval = pcap_read(pcap, &packet);
@@ -68,7 +68,8 @@ main(int argc OVS_UNUSED, char *argv[])
             ovs_fatal(retval, "error reading pcap file");
         }
 
-        flow_extract(packet, 0, 0, NULL, 1, &flow);
+        in_port_.ofp_port = u16_to_ofp(1);
+        flow_extract(packet, 0, 0, NULL, &in_port_, &flow);
         match_init_exact(&match, &flow);
         ofputil_match_to_ofp10_match(&match, &extracted_match);
 
diff --git a/tests/test-odp.c b/tests/test-odp.c
index 268a105..dc88ddf 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.in_port.odp_port);
 
         if (odp_key.size > ODPUTIL_FLOW_KEY_BYTES) {
             printf ("too long: %zu > %d\n",
diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c
index 54505e8..2786f27 100644
--- a/utilities/ovs-dpctl.c
+++ b/utilities/ovs-dpctl.c
@@ -308,7 +308,7 @@ dpctl_add_if(int argc OVS_UNUSED, char *argv[])
         char *save_ptr = NULL;
         struct netdev *netdev = NULL;
         struct smap args;
-        uint32_t port_no = UINT32_MAX;
+        odp_port_t port_no = ODPP_NONE;
         char *option;
         int error;
 
@@ -335,7 +335,7 @@ dpctl_add_if(int argc OVS_UNUSED, char *argv[])
             if (!strcmp(key, "type")) {
                 type = value;
             } else if (!strcmp(key, "port_no")) {
-                port_no = atoi(value);
+                port_no = u32_to_odp(atoi(value));
             } else if (!smap_add_once(&args, key, value)) {
                 ovs_error(0, "duplicate \"%s\" option", key);
             }
@@ -388,7 +388,7 @@ dpctl_set_if(int argc, char *argv[])
         char *type = NULL;
         const char *name;
         struct smap args;
-        uint32_t port_no;
+        odp_port_t port_no;
         char *option;
         int error;
 
@@ -441,7 +441,7 @@ dpctl_set_if(int argc, char *argv[])
                     failure = true;
                 }
             } else if (!strcmp(key, "port_no")) {
-                if (port_no != atoi(value)) {
+                if (port_no != u32_to_odp(atoi(value))) {
                     ovs_error(0, "%s: can't change port number from "
                               "%"PRIu32" to %d",
                               name, port_no, atoi(value));
@@ -476,7 +476,7 @@ next:
 }
 
 static bool
-get_port_number(struct dpif *dpif, const char *name, uint32_t *port)
+get_port_number(struct dpif *dpif, const char *name, odp_port_t *port)
 {
     struct dpif_port dpif_port;
 
@@ -500,11 +500,11 @@ dpctl_del_if(int argc OVS_UNUSED, char *argv[])
     run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
     for (i = 2; i < argc; i++) {
         const char *name = argv[i];
-        uint32_t port;
+        odp_port_t port;
         int error;
 
         if (!name[strspn(name, "0123456789")]) {
-            port = atoi(name);
+            port = u32_to_odp(atoi(name));
         } else if (!get_port_number(dpif, name, &port)) {
             failure = true;
             continue;
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 48f0fbf..75bedb1 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -632,7 +632,7 @@ ofctl_dump_tables(int argc OVS_UNUSED, char *argv[])
 
 static bool
 fetch_port_by_features(const char *vconn_name,
-                       const char *port_name, unsigned int port_no,
+                       const char *port_name, ofp_port_t port_no,
                        struct ofputil_phy_port *pp, bool *trunc)
 {
     struct ofputil_switch_features features;
@@ -670,7 +670,7 @@ fetch_port_by_features(const char *vconn_name,
     }
 
     while (!ofputil_pull_phy_port(oh->version, &b, pp)) {
-        if (port_no != UINT_MAX
+        if (port_no != OFPP_NONE
             ? port_no == pp->port_no
             : !strcmp(pp->name, port_name)) {
             found = true;
@@ -685,7 +685,7 @@ exit:
 
 static bool
 fetch_port_by_stats(const char *vconn_name,
-                    const char *port_name, unsigned int port_no,
+                    const char *port_name, ofp_port_t port_no,
                     struct ofputil_phy_port *pp)
 {
     struct ofpbuf *request;
@@ -729,8 +729,8 @@ fetch_port_by_stats(const char *vconn_name,
             }
 
             while (!ofputil_pull_phy_port(oh->version, &b, pp)) {
-                if (port_no != UINT_MAX ? port_no == pp->port_no
-                                        : !strcmp(pp->name, port_name)) {
+                if (port_no != OFPP_NONE ? port_no == pp->port_no
+                                         : !strcmp(pp->name, port_name)) {
                     found = true;
                     break;
                 }
@@ -754,13 +754,13 @@ static void
 fetch_ofputil_phy_port(const char *vconn_name, const char *port_name,
                        struct ofputil_phy_port *pp)
 {
-    unsigned int port_no;
+    ofp_port_t port_no;
     bool found;
     bool trunc;
 
     /* Try to interpret the argument as a port number. */
-    if (!str_to_uint(port_name, 10, &port_no)) {
-        port_no = UINT_MAX;
+    if (!str_to_ofp(port_name, &port_no)) {
+        port_no = OFPP_NONE;
     }
 
     /* Try to find the port based on the Features Reply.  If it looks
@@ -779,10 +779,10 @@ fetch_ofputil_phy_port(const char *vconn_name, const char *port_name,
 
 /* Returns the port number corresponding to 'port_name' (which may be a port
  * name or number) within the switch 'vconn_name'. */
-static uint16_t
+static ofp_port_t
 str_to_port_no(const char *vconn_name, const char *port_name)
 {
-    uint16_t port_no;
+    ofp_port_t port_no;
 
     if (ofputil_port_from_string(port_name, &port_no)) {
         return port_no;
@@ -1489,7 +1489,7 @@ ofctl_dump_ports(int argc, char *argv[])
 {
     struct ofpbuf *request;
     struct vconn *vconn;
-    uint16_t port;
+    ofp_port_t port;
 
     open_vconn(argv[1], &vconn);
     port = argc > 2 ? str_to_port_no(argv[1], argv[2]) : OFPP_ANY;
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 3513810..6f573df 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -67,13 +67,13 @@ struct if_cfg {
     struct hmap_node hmap_node;         /* Node in bridge's if_cfg_todo. */
     const struct ovsrec_interface *cfg; /* Interface record. */
     const struct ovsrec_port *parent;   /* Parent port record. */
-    uint16_t ofport;                    /* Requested OpenFlow port number. */
+    ofp_port_t ofport;                  /* Requested OpenFlow port number. */
 };
 
 /* OpenFlow port slated for removal from ofproto. */
 struct ofpp_garbage {
     struct list list_node;      /* Node in bridge's ofpp_garbage. */
-    uint16_t ofp_port;          /* Port to be deleted. */
+    ofp_port_t ofp_port;        /* Port to be deleted. */
 };
 
 struct iface {
@@ -86,7 +86,7 @@ struct iface {
     /* These members are valid only after bridge_reconfigure() causes them to
      * be initialized. */
     struct hmap_node ofp_port_node; /* In struct bridge's "ifaces" hmap. */
-    uint16_t ofp_port;          /* OpenFlow port number, */
+    ofp_port_t ofp_port;        /* OpenFlow port number, */
                                 /* OFPP_NONE if unknown. */
     struct netdev *netdev;      /* Network device. */
     const char *type;           /* Usually same as cfg->type. */
@@ -245,7 +245,8 @@ static bool mirror_configure(struct mirror *);
 static void mirror_refresh_stats(struct mirror *);
 
 static void iface_configure_lacp(struct iface *, struct lacp_slave_settings *);
-static bool iface_create(struct bridge *, struct if_cfg *, uint16_t ofp_port);
+static bool iface_create(struct bridge *, struct if_cfg *,
+                         ofp_port_t ofp_port);
 static bool iface_is_internal(const struct ovsrec_interface *iface,
                               const struct ovsrec_bridge *br);
 static const char *iface_get_type(const struct ovsrec_interface *,
@@ -255,9 +256,9 @@ static struct iface *iface_lookup(const struct bridge *, const char *name);
 static struct iface *iface_find(const char *name);
 static struct if_cfg *if_cfg_lookup(const struct bridge *, const char *name);
 static struct iface *iface_from_ofp_port(const struct bridge *,
-                                         uint16_t ofp_port);
+                                         ofp_port_t ofp_port);
 static void iface_set_mac(struct iface *);
-static void iface_set_ofport(const struct ovsrec_interface *, uint16_t ofport);
+static void iface_set_ofport(const struct ovsrec_interface *, ofp_port_t ofport);
 static void iface_clear_db_record(const struct ovsrec_interface *if_cfg);
 static void iface_configure_qos(struct iface *, const struct ovsrec_qos *);
 static void iface_configure_cfm(struct iface *);
@@ -265,7 +266,7 @@ static void iface_refresh_cfm_stats(struct iface *);
 static void iface_refresh_stats(struct iface *);
 static void iface_refresh_status(struct iface *);
 static bool iface_is_synthetic(const struct iface *);
-static uint16_t iface_pick_ofport(const struct ovsrec_interface *);
+static ofp_port_t iface_pick_ofport(const struct ovsrec_interface *);
 
 /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)
  *
@@ -1277,13 +1278,14 @@ add_del_bridges(const struct ovsrec_open_vswitch *cfg)
 }
 
 static void
-iface_set_ofp_port(struct iface *iface, uint16_t ofp_port)
+iface_set_ofp_port(struct iface *iface, ofp_port_t ofp_port)
 {
     struct bridge *br = iface->port->bridge;
 
     ovs_assert(iface->ofp_port == OFPP_NONE && ofp_port != OFPP_NONE);
     iface->ofp_port = ofp_port;
-    hmap_insert(&br->ifaces, &iface->ofp_port_node, hash_int(ofp_port, 0));
+    hmap_insert(&br->ifaces, &iface->ofp_port_node,
+                hash_int(ofp_to_u16(ofp_port), 0));
     iface_set_ofport(iface->cfg, ofp_port);
 }
 
@@ -1318,7 +1320,7 @@ bridge_refresh_one_ofp_port(struct bridge *br,
 {
     const char *name = ofproto_port->name;
     const char *type = ofproto_port->type;
-    uint16_t ofp_port = ofproto_port->ofp_port;
+    ofp_port_t ofp_port = ofproto_port->ofp_port;
 
     struct iface *iface = iface_lookup(br, name);
     if (iface) {
@@ -1421,7 +1423,7 @@ bridge_refresh_ofp_port(struct bridge *br)
 static int
 iface_do_create(const struct bridge *br,
                 const struct if_cfg *if_cfg,
-                uint16_t *ofp_portp, struct netdev **netdevp)
+                ofp_port_t *ofp_portp, struct netdev **netdevp)
 {
     const struct ovsrec_interface *iface_cfg = if_cfg->cfg;
     const struct ovsrec_port *port_cfg = if_cfg->parent;
@@ -1449,7 +1451,7 @@ iface_do_create(const struct bridge *br,
     }
 
     if (*ofp_portp == OFPP_NONE) {
-        uint16_t ofp_port = if_cfg->ofport;
+        ofp_port_t ofp_port = if_cfg->ofport;
 
         error = ofproto_port_add(br->ofproto, netdev, &ofp_port);
         if (error) {
@@ -1485,7 +1487,7 @@ error:
  *
  * Return true if an iface is successfully created, false otherwise. */
 static bool
-iface_create(struct bridge *br, struct if_cfg *if_cfg, uint16_t ofp_port)
+iface_create(struct bridge *br, struct if_cfg *if_cfg, ofp_port_t ofp_port)
 {
     const struct ovsrec_interface *iface_cfg = if_cfg->cfg;
     const struct ovsrec_port *port_cfg = if_cfg->parent;
@@ -1547,7 +1549,7 @@ iface_create(struct bridge *br, struct if_cfg *if_cfg, uint16_t ofp_port)
 
             error = netdev_open(port->name, "internal", &netdev);
             if (!error) {
-                uint16_t fake_ofp_port = if_cfg->ofport;
+                ofp_port_t fake_ofp_port = if_cfg->ofport;
 
                 ofproto_port_add(br->ofproto, netdev, &fake_ofp_port);
                 netdev_close(netdev);
@@ -3291,7 +3293,7 @@ iface_configure_lacp(struct iface *iface, struct lacp_slave_settings *s)
     key = smap_get_int(&iface->cfg->other_config, "lacp-aggregation-key", 0);
 
     if (portid <= 0 || portid > UINT16_MAX) {
-        portid = iface->ofp_port;
+        portid = ofp_to_u16(iface->ofp_port);
     }
 
     if (priority <= 0 || priority > UINT16_MAX) {
@@ -3479,12 +3481,13 @@ if_cfg_lookup(const struct bridge *br, const char *name)
 }
 
 static struct iface *
-iface_from_ofp_port(const struct bridge *br, uint16_t ofp_port)
+iface_from_ofp_port(const struct bridge *br, ofp_port_t ofp_port)
 {
     struct iface *iface;
 
     HMAP_FOR_EACH_IN_BUCKET (iface, ofp_port_node,
-                             hash_int(ofp_port, 0), &br->ifaces) {
+                             hash_int(ofp_to_u16(ofp_port), 0),
+                             &br->ifaces) {
         if (iface->ofp_port == ofp_port) {
             return iface;
         }
@@ -3520,10 +3523,10 @@ iface_set_mac(struct iface *iface)
 
 /* Sets the ofport column of 'if_cfg' to 'ofport'. */
 static void
-iface_set_ofport(const struct ovsrec_interface *if_cfg, uint16_t ofport)
+iface_set_ofport(const struct ovsrec_interface *if_cfg, ofp_port_t ofport)
 {
     int64_t port_;
-    port_ = (ofport == OFPP_NONE) ? -1 : ofport;
+    port_ = (ofport == OFPP_NONE) ? -1 : ofp_to_u16(ofport);
     if (if_cfg && !ovsdb_idl_row_is_synthetic(&if_cfg->header_)) {
         ovsrec_interface_set_ofport(if_cfg, &port_, 1);
     }
@@ -3709,11 +3712,13 @@ iface_is_synthetic(const struct iface *iface)
     return ovsdb_idl_row_is_synthetic(&iface->cfg->header_);
 }
 
-static uint16_t
+static ofp_port_t
 iface_pick_ofport(const struct ovsrec_interface *cfg)
 {
-    uint16_t ofport = cfg->n_ofport ? *cfg->ofport : OFPP_NONE;
-    return cfg->n_ofport_request ? *cfg->ofport_request : ofport;
+    ofp_port_t ofport = cfg->n_ofport ? u16_to_ofp(*cfg->ofport)
+                                      : OFPP_NONE;
+    return cfg->n_ofport_request ? u16_to_ofp(*cfg->ofport_request)
+                                 : ofport;
 }
 
 
@@ -4091,7 +4096,7 @@ static void
 configure_splinter_port(struct port *port)
 {
     struct ofproto *ofproto = port->bridge->ofproto;
-    uint16_t realdev_ofp_port;
+    ofp_port_t realdev_ofp_port;
     const char *realdev_name;
     struct iface *vlandev, *realdev;
 
-- 
1.7.9.5




More information about the dev mailing list