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

Alex Wang alexw at nicira.com
Fri Jun 7 15:42:15 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>

---
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

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

REMAINING ISSUE

When doing comparisions like '<', '<=', etc, both ofp_port_t and odp_port_t
will be converted to int, even though the L- and R- operands have same type.
This seems to be caused by "usual arithmetic conversion" and I have not found
a satisfying solution yet.

As a workaround, I defined a macro function "PORT_COMPARE()" in "lib/flow.h",
which uses OVS_FORCE to cast both operands to uint32_t and conducts the
comparision. It also makes it easy to check all such comparisons. Just
grep "PORT_COMPARE".

---
 include/linux/openvswitch.h     |    2 +-
 include/openflow/openflow-1.0.h |   56 +++++----
 include/openflow/openflow-1.1.h |    4 +-
 include/openvswitch/types.h     |    6 +
 lib/bundle.c                    |   22 ++--
 lib/bundle.h                    |    6 +-
 lib/dpif-linux.c                |   58 +++++----
 lib/dpif-linux.h                |    4 +-
 lib/dpif-netdev.c               |   89 +++++++-------
 lib/dpif-provider.h             |   10 +-
 lib/dpif.c                      |   22 ++--
 lib/dpif.h                      |   14 +--
 lib/flow.c                      |    8 +-
 lib/flow.h                      |  144 +++++++++++++++++++++-
 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/meta-flow.h                 |    2 +-
 lib/nx-match.c                  |    6 +-
 lib/odp-util.c                  |   10 +-
 lib/odp-util.h                  |    4 +-
 lib/ofp-actions.c               |   34 +++---
 lib/ofp-actions.h               |   12 +-
 lib/ofp-parse.c                 |   12 +-
 lib/ofp-print.c                 |   16 +--
 lib/ofp-util.c                  |  144 +++++++++++-----------
 lib/ofp-util.h                  |   34 +++---
 lib/sflow.h                     |    2 +
 lib/sflow_api.h                 |    6 +-
 lib/sflow_poller.c              |    4 +-
 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               |   12 +-
 ofproto/ofproto-dpif-sflow.c    |   17 +--
 ofproto/ofproto-dpif-sflow.h    |    9 +-
 ofproto/ofproto-dpif.c          |  249 +++++++++++++++++++++------------------
 ofproto/ofproto-provider.h      |   18 +--
 ofproto/ofproto.c               |  105 ++++++++++-------
 ofproto/ofproto.h               |   37 +++---
 ofproto/pinsched.c              |    9 +-
 ofproto/pinsched.h              |    3 +-
 ofproto/pktbuf.c                |   10 +-
 ofproto/pktbuf.h                |    4 +-
 ofproto/tunnel.c                |   12 +-
 ofproto/tunnel.h                |    6 +-
 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           |   19 +--
 vswitchd/bridge.c               |   52 ++++----
 58 files changed, 841 insertions(+), 613 deletions(-)

diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index e890fd8..add1287 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -116,7 +116,7 @@ struct ovs_vport_stats {
 };
 
 /* Fixed logical ports. */
-#define OVSP_LOCAL      ((__u32)0)
+#define OVSP_LOCAL      ((OVS_FORCE odp_port_t) 0)
 
 /* Packet transfer. */
 
diff --git a/include/openflow/openflow-1.0.h b/include/openflow/openflow-1.0.h
index c30fa92..439cc91 100644
--- a/include/openflow/openflow-1.0.h
+++ b/include/openflow/openflow-1.0.h
@@ -28,28 +28,40 @@
  * 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. */
+/* Maximum number of physical switch ports. */
+#define OFPP_MAX        ((OVS_FORCE ofp_port_t) 0xff00)
+
+/* First assigned reserved port number. */
+#define OFPP_FIRST_RESV ((OVS_FORCE ofp_port_t) 0xfff8)
+
+/* Last assigned reserved port number. */
+#define OFPP_LAST_RESV  ((OVS_FORCE ofp_port_t) 0xffff)
+
+/* Reserved output "ports". */
+/* Send the packet out the input port.  This virtual port must be explicitly
+ * used in order to send back out of the input port. */
+#define OFPP_IN_PORT    ((OVS_FORCE ofp_port_t) 0xfff8)
+
+/* Perform actions in flow table. NB: This can only be the destination port
+ * for packet-out messages. */
+#define OFPP_TABLE      ((OVS_FORCE ofp_port_t) 0xfff9)
+
+/* Process with normal L2/L3 switching. */
+#define OFPP_NORMAL     ((OVS_FORCE ofp_port_t) 0xfffa)
+
+/* All physical ports except input port and those disabled by STP. */
+#define OFPP_FLOOD      ((OVS_FORCE ofp_port_t) 0xfffb)
+
+/* All physical ports except input port. */
+#define OFPP_ALL        ((OVS_FORCE ofp_port_t) 0xfffc)
+/* Send to controller. */
+#define OFPP_CONTROLLER ((OVS_FORCE ofp_port_t) 0xfffd)
+/* Local openflow "port". */
+#define OFPP_LOCAL      ((OVS_FORCE ofp_port_t) 0xfffe)
+/* Not associated with a physical port. */
+#define OFPP_NONE       ((OVS_FORCE ofp_port_t) 0xffff)
 
 /* 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..6ed2400 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    ((OVS_FORCE ofp11_port_t) 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..7e1e59d 100644
--- a/include/openvswitch/types.h
+++ b/include/openvswitch/types.h
@@ -60,4 +60,10 @@ 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. */
+typedef uint16_t OVS_BITWISE ofp_port_t;
+typedef uint32_t OVS_BITWISE odp_port_t;
+typedef uint32_t OVS_BITWISE ofp11_port_t;
+
 #endif /* openvswitch/types.h */
diff --git a/lib/bundle.c b/lib/bundle.c
index 92ac1e1..f18268c 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,9 +51,9 @@ 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,
-            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;
@@ -79,9 +79,9 @@ execute_hrw(const struct ofpact_bundle *bundle, const struct flow *flow,
 /* Executes 'bundle' on 'flow'.  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,
-               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:
@@ -179,7 +179,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);
@@ -193,7 +193,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);
@@ -239,7 +239,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] = ofp_htons(bundle->slaves[i]);
     }
 }
 
@@ -264,7 +264,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 5b6bb67..7395b71 100644
--- a/lib/bundle.h
+++ b/lib/bundle.h
@@ -34,12 +34,12 @@ struct ofpbuf;
  *
  * See include/openflow/nicira-ext.h for NXAST_BUNDLE specification. */
 
-uint16_t bundle_execute(const struct ofpact_bundle *, const struct flow *,
-                        bool (*slave_enabled)(uint16_t ofp_port, void *aux),
+ofp_port_t bundle_execute(const struct ofpact_bundle *, const struct flow *,
+                        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 ac20ae7..ae4e15e 100644
--- a/lib/dpif-linux.c
+++ b/lib/dpif-linux.c
@@ -167,7 +167,7 @@ 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 *);
@@ -278,7 +278,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 = (OVS_FORCE odp_port_t) i;
         vport_request.upcall_pid = &upcall_pid;
         dpif_linux_vport_transact(&vport_request, NULL, NULL);
 
@@ -298,9 +298,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 = (OVS_FORCE uint32_t) port_no;
 
     if (dpif->epoll_fd < 0) {
         return 0;
@@ -308,9 +309,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 +332,31 @@ 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 = (OVS_FORCE uint32_t) 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;
@@ -537,7 +540,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 != OVSP_NONE) {
             VLOG_INFO("%s: requested port %"PRIu32" is in use",
                       dpif_name(dpif_), *port_nop);
         }
@@ -569,7 +572,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;
@@ -587,7 +590,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;
@@ -618,7 +621,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);
@@ -631,23 +634,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 (OVS_FORCE odp_port_t) 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 = (OVS_FORCE uint32_t) 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);
     }
 }
@@ -1551,7 +1555,8 @@ 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 = (OVS_FORCE odp_port_t)
+                      nl_attr_get_u32(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]) {
@@ -1581,8 +1586,9 @@ 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 != OVSP_NONE) {
+        nl_msg_put_u32(buf, OVS_VPORT_ATTR_PORT_NO,
+                       (OVS_FORCE uint32_t) vport->port_no);
     }
 
     if (vport->type != OVS_VPORT_TYPE_UNSPEC) {
@@ -1613,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 = OVSP_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..492e543 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;                    /* OVSP_NONE if unknown. */
     enum ovs_vport_type type;
 
     /* Attributes.
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 61031cd..772af97 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
@@ -379,13 +381,14 @@ 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;
     struct netdev *netdev;
     struct netdev_rx *rx;
     const char *open_type;
+    uint32_t port_idx = (OVS_FORCE uint32_t) port_no;
     int mtu;
     int error;
 
@@ -429,7 +432,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[port_idx] = port;
     dp->serial++;
 
     return 0;
@@ -437,51 +440,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);
-    int port_no;
+    uint32_t port_no = (OVS_FORCE uint32_t) *port_nop;
 
-    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, netdev_vport_get_dpif_port(netdev));
     }
-    if (port_no >= 0) {
-        *port_nop = port_no;
+    if (port_no > 0) {
+        *port_nop = (OVS_FORCE odp_port_t) port_no;
         return do_add_port(dp, netdev_vport_get_dpif_port(netdev),
-                           netdev_get_type(netdev), port_no);
+                           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 == OVSP_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 PORT_COMPARE(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)
 {
+    uint32_t port_idx = (OVS_FORCE uint32_t) port_no;
+
     if (!is_valid_port_number(port_no)) {
         *portp = NULL;
         return EINVAL;
     } else {
-        *portp = dp->ports[port_no];
+        *portp = dp->ports[port_idx];
         return *portp ? 0 : ENOENT;
     }
 }
@@ -502,9 +507,10 @@ 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;
+    uint32_t port_idx = (OVS_FORCE uint32_t) port_no;
     int error;
 
     error = get_port_by_number(dp, port_no, &port);
@@ -513,7 +519,7 @@ do_del_port(struct dp_netdev *dp, uint32_t port_no)
     }
 
     list_remove(&port->node);
-    dp->ports[port->port_no] = NULL;
+    dp->ports[port_idx] = NULL;
     dp->serial++;
 
     netdev_close(port->netdev);
@@ -535,7 +541,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);
@@ -564,10 +570,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 (OVS_FORCE odp_port_t) MAX_PORTS;
 }
 
 static void
@@ -597,7 +603,7 @@ dpif_netdev_flow_flush(struct dpif *dpif)
 }
 
 struct dp_netdev_port_state {
-    uint32_t port_no;
+    odp_port_t port_no;
     char *name;
 };
 
@@ -614,17 +620,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 = (OVS_FORCE uint32_t) 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_vport_get_dpif_port(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 = (OVS_FORCE odp_port_t) (port_idx + 1);
             return 0;
         }
     }
@@ -706,9 +713,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 (PORT_COMPARE(flow->in_port.odp_port, >=, MAX_PORTS)) {
         return EINVAL;
     }
 
@@ -896,7 +901,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;
@@ -946,7 +951,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) {
@@ -1041,11 +1046,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);
@@ -1132,7 +1139,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..0b616b0 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 OVSP_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 OVSP_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 = OVSP_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 = OVSP_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 OVSP_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 3c12984..431e586 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 0fdf4ef..a9b9fb3 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -57,6 +57,12 @@ BUILD_ASSERT_DECL(FLOW_NW_FRAG_LATER == NX_IP_FRAG_LATER);
 #define FLOW_TNL_F_CSUM (1 << 1)
 #define FLOW_TNL_F_KEY (1 << 2)
 
+/* Cast both left and right values to 'uint32_t' using the OVS_FORCE attribute
+ * macro. Then, compare using the provided rational operator. */
+#define PORT_COMPARE(L_OPERAND, OPERATOR, R_OPERAND)     \
+    (((OVS_FORCE uint32_t) L_OPERAND) OPERATOR		 \
+     ((OVS_FORCE uint32_t) R_OPERAND))
+
 const char *flow_tun_flag_to_string(uint32_t flags);
 
 struct flow_tnl {
@@ -68,6 +74,13 @@ 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. */
+    ofp11_port_t ofp11_port;   /* For the OpenFlow-1.1 or above protocols. */
+    uint32_t     port32;       /* For using in arithmetic opertions */
+};
+
 /*
 * A flow in the network.
 *
@@ -82,14 +95,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 +133,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 +182,128 @@ flow_hash(const struct flow *flow, uint32_t basis)
     return hash_words((const uint32_t *) flow, sizeof *flow / 4, basis);
 }
 
+/* ofp/odp port related utility functions. */
+static inline ovs_be16 ofp_htons(ofp_port_t ofp_port);
+static inline ovs_be32 odp_htonl(odp_port_t odp_port);
+static inline ovs_be32 ofp11_htonl(ofp11_port_t ofp11_port);
+static inline ofp_port_t ofp_ntohs(ovs_be16 netshort);
+static inline odp_port_t odp_ntohl(ovs_be32 netlong);
+static inline ofp11_port_t ofp11_ntohl(ovs_be32 netlong);
+
+static inline uint32_t hash_ofp_port(ofp_port_t ofp_port,
+                                     uint32_t basis);
+static inline uint32_t hash_odp_port(odp_port_t odp_port_t,
+                                     uint32_t basis);
+static inline uint32_t hash_ofp11_port(ofp11_port_t ofp11_port,
+                                       uint32_t basis);
+
+static inline void ofp_port_increment(ofp_port_t *ofp_portp,
+                                      uint16_t incr);
+static inline void odp_port_increment(odp_port_t *odp_portp,
+                                      uint32_t incr);
+
+static inline int ofp11_port_to_ofp_port(ofp11_port_t ofp11_port,
+                                         ofp_port_t *ofp_portp);
+static inline void ofp_port_to_ofp11_port(ofp_port_t ofp_port,
+                                          ofp11_port_t *ofp11_portp);
+
+static inline ovs_be16
+ofp_htons(ofp_port_t ofp_port)
+{
+    return htons((OVS_FORCE uint16_t) ofp_port);
+}
+
+static inline ovs_be32
+odp_htonl(odp_port_t odp_port)
+{
+    return htonl((OVS_FORCE uint32_t) odp_port);
+}
+
+static inline ovs_be32
+ofp11_htonl(ofp11_port_t ofp11_port)
+{
+    return htonl((OVS_FORCE uint32_t) ofp11_port);
+}
+
+static inline ofp_port_t
+ofp_ntohs(ovs_be16 netshort)
+{
+    return (OVS_FORCE ofp_port_t) ntohs(netshort);
+}
+
+static inline odp_port_t
+odp_ntohl(ovs_be32 netlong)
+{
+    return (OVS_FORCE odp_port_t) ntohl(netlong);
+}
+
+static inline ofp11_port_t
+ofp11_ntohl(ovs_be32 netlong)
+{
+    return (OVS_FORCE ofp11_port_t) ntohl(netlong);
+}
+
+static inline uint32_t
+hash_ofp_port(ofp_port_t ofp_port, uint32_t basis)
+{
+    return hash_int((OVS_FORCE uint16_t) ofp_port, basis);
+}
+
+static inline uint32_t
+hash_odp_port(odp_port_t odp_port, uint32_t basis)
+{
+    return hash_int((OVS_FORCE uint32_t) odp_port, basis);
+}
+
+static inline uint32_t
+hash_ofp11_port(ofp11_port_t ofp11_port, uint32_t basis)
+{
+    return hash_int((OVS_FORCE uint32_t) ofp11_port, basis);
+}
+
+static inline void
+ofp_port_increment(ofp_port_t *ofp_portp, uint16_t incr)
+{
+    *ofp_portp = (OVS_FORCE ofp_port_t) ((OVS_FORCE uint16_t) *ofp_portp
+                                         + incr);
+}
+
+static inline void
+odp_port_increment(odp_port_t *odp_portp, uint32_t incr)
+{
+    *odp_portp = (OVS_FORCE odp_port_t) ((OVS_FORCE uint32_t) *odp_portp
+                                         + incr);
+}
+
+/* Convert ofp11_port to ofp_port. Return 0 on success and set *ofp_portp
+ * to the corresponding ofp_port number. Return -1 on failure. */
+static inline int
+ofp11_port_to_ofp_port(ofp11_port_t ofp11_port, ofp_port_t *ofp_portp)
+{
+    if (PORT_COMPARE(ofp11_port, <, OFPP_MAX)) {
+        *ofp_portp = (OVS_FORCE ofp_port_t) ofp11_port;
+    } else if (PORT_COMPARE(ofp11_port, >=, OFPP11_MAX)) {
+        *ofp_portp = (OVS_FORCE ofp_port_t)((OVS_FORCE uint32_t)ofp11_port
+                                            - OFPP11_OFFSET);
+    } else {
+        return -1;
+    }
+    return 0;
+}
+
+/* Convert ofp_port to ofp11_port. This function is always successful and sets
+ * *ofp11_portp to the corresponding ofp11_port number. */
+static inline void
+ofp_port_to_ofp11_port(ofp_port_t ofp_port, ofp11_port_t *ofp11_portp)
+{
+    if (PORT_COMPARE(ofp_port, <, OFPP_MAX)) {
+        *ofp11_portp = (OVS_FORCE ofp11_port_t) ofp_port;
+    } else {
+        *ofp11_portp = (OVS_FORCE ofp11_port_t) ((OVS_FORCE uint32_t)ofp_port
+                                                 + OFPP11_OFFSET);
+    }
+}
+
 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 ab403be..964c06c 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 = ofp_ntohs(value.be16[7]);
 
-                if (port < OFPP_MAX
+                if (PORT_COMPARE(port, <, 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..94c4267 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_ofp_port(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_ofp_port(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
+               || PORT_COMPARE(out_port, >=, 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 666b00f..f01479a 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 54bc4c2..4d7149e 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 = ofp_htons(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, 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;
@@ -1388,13 +1387,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 = 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;
     }
 
@@ -1595,8 +1594,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:
@@ -2013,7 +2012,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(ofp_ntohs(value->be16));
         break;
 
     case MFF_IPV6_LABEL:
@@ -2204,12 +2203,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 = ofp_htons(port);
         *maskp = htons(UINT16_MAX);
         return NULL;
     }
@@ -2220,7 +2219,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)) {
@@ -2476,7 +2475,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;
@@ -2484,7 +2483,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(ofp_ntohs(value->be16), s);
             break;
         }
         /* fall through */
diff --git a/lib/meta-flow.h b/lib/meta-flow.h
index a85a193..dc54899 100644
--- a/lib/meta-flow.h
+++ b/lib/meta-flow.h
@@ -276,7 +276,7 @@ struct mf_field {
     uint32_t nxm_header;        /* An NXM_* (or OXM_*) constant. */
     const char *nxm_name;       /* The nxm_header constant's name. */
     uint32_t oxm_header;        /* An OXM_* (or NXM_*) constant. */
-    const char *oxm_name;	    /* The oxm_header constant's name */
+    const char *oxm_name;       /* The oxm_header constant's name */
 };
 
 /* The representation of a field's value. */
diff --git a/lib/nx-match.c b/lib/nx-match.c
index e111000..9a8fbef 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, ofp_htons(in_port));
         }
     }
 
diff --git a/lib/odp-util.c b/lib/odp-util.c
index cc8b1dd..1e65756 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -1558,7 +1558,7 @@ ovs_to_odp_frag(uint8_t nw_frag)
  * 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;
@@ -1576,7 +1576,8 @@ odp_flow_key_from_flow(struct ofpbuf *buf, const struct flow *flow,
     }
 
     if (odp_in_port != OVSP_NONE) {
-        nl_msg_put_u32(buf, OVS_KEY_ATTR_IN_PORT, odp_in_port);
+        nl_msg_put_u32(buf, OVS_KEY_ATTR_IN_PORT,
+                       (OVS_FORCE uint32_t) odp_in_port);
     }
 
     eth_key = nl_msg_put_unspec_uninit(buf, OVS_KEY_ATTR_ETHERNET,
@@ -2098,10 +2099,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
+        = (OVS_FORCE odp_port_t) nl_attr_get_u32(attrs[OVS_KEY_ATTR_IN_PORT]);
         expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_IN_PORT;
     } else {
-        flow->in_port = OVSP_NONE;
+        flow->in_port.odp_port = OVSP_NONE;
     }
 
     /* Ethernet header. */
diff --git a/lib/odp-util.h b/lib/odp-util.h
index 6213418..307ac76 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -33,7 +33,7 @@ struct nlattr;
 struct ofpbuf;
 struct simap;
 
-#define OVSP_NONE UINT32_MAX
+#define OVSP_NONE ((OVS_FORCE odp_port_t) UINT32_MAX)
 
 void format_odp_actions(struct ds *, const struct nlattr *odp_actions,
                         size_t actions_len);
@@ -95,7 +95,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 58d0098..77cee33 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 = 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 = ofp_ntohs(oae->port);
     enqueue->queue = ntohl(oae->queue_id);
-    if (enqueue->port >= OFPP_MAX && enqueue->port != OFPP_IN_PORT
+    if (PORT_COMPARE(enqueue->port, >=, 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 = 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 = 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 (PORT_COMPARE(enqueue->port, >=, 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 = ofp_htons(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 = ofp_htons(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 = ofp_htons(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 (PORT_COMPARE(port, <, 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 9a74bcc..8aa943e 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..09a8856 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 = (OVS_FORCE ofp_port_t) 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 = (OVS_FORCE ofp_port_t) 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 = (OVS_FORCE ofp_port_t) 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 0a9917a..6c534b6 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) {
@@ -202,10 +202,10 @@ 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;
+    ofp_port_t ap = a->port_no;
+    ofp_port_t bp = b->port_no;
 
-    return ap < bp ? -1 : ap > bp;
+    return PORT_COMPARE(ap, <, bp) ? -1 : PORT_COMPARE(ap, >, bp);
 }
 
 static void
@@ -583,7 +583,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;
@@ -663,7 +663,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));
+                    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,
@@ -1160,7 +1160,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);
@@ -1198,7 +1198,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 (PORT_COMPARE(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 cc2dc36..dd6655d 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 = 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 = ofp_htons(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 = 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 = 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 = ofp_htons(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 = ofp_htons(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 = 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 = 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 = ofp_htons(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 = ofp_htons(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 = 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 = ofp_htons(pin->fmd.in_port);
         opi->reason = pin->reason;
         opi->buffer_id = htonl(pin->buffer_id);
 
@@ -2730,7 +2730,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 = ofp_ntohs(opo->in_port);
 
         error = ofpacts_pull_openflow10(&b, ntohs(opo->actions_len), ofpacts);
         if (error) {
@@ -2740,7 +2740,8 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po,
         NOT_REACHED();
     }
 
-    if (po->in_port >= OFPP_MAX && po->in_port != OFPP_LOCAL
+    if (PORT_COMPARE(po->in_port, >=, 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);
@@ -2827,7 +2828,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 = 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);
 
@@ -2895,7 +2896,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 = ofp_htons(pp->port_no);
     memcpy(opp->hw_addr, pp->hw_addr, ETH_ADDR_LEN);
     ovs_strlcpy(opp->name, pp->name, OFP_MAX_PORT_NAME_LEN);
 
@@ -3305,7 +3306,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 = 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;
@@ -3347,7 +3348,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 = ofp_htons(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);
@@ -3683,7 +3684,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 = ofp_ntohs(nfmr->out_port);
     rq->table_id = nfmr->table_id;
 
     return nx_pull_match(msg, ntohs(nfmr->match_len), &rq->match, NULL, NULL);
@@ -3708,7 +3709,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 = ofp_htons(rq->out_port);
     nfmr->match_len = htons(match_len);
     nfmr->table_id = rq->table_id;
 }
@@ -3916,7 +3917,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 = ofp_htons(po->in_port);
         opo->actions_len = htons(msg->size - actions_ofs);
         break;
     }
@@ -4035,22 +4036,20 @@ 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);
+    ofp11_port_t ofp11_port_h = ofp11_ntohl(ofp11_port);
+    int error;
 
-    if (ofp11_port_h < OFPP_MAX) {
-        *ofp10_port = ofp11_port_h;
-        return 0;
-    } else if (ofp11_port_h >= OFPP11_MAX) {
-        *ofp10_port = ofp11_port_h - OFPP11_OFFSET;
+    error = ofp11_port_to_ofp_port(ofp11_port_h, ofp10_port);
+    if (!error) {
         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);
+                     "range 0 through %u or 0x%"PRIx32" through 0x%"PRIx32,
+                     ofp11_port_h, (OVS_FORCE uint32_t) OFPP_MAX - 1,
+                     OFPP11_MAX, UINT32_MAX);
         return OFPERR_OFPBAC_BAD_OUT_PORT;
     }
 }
@@ -4060,18 +4059,19 @@ 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);
+    ofp11_port_t ofp11_port;
+
+    ofp_port_to_ofp11_port(ofp10_port, &ofp11_port);
+    return ofp11_htonl(ofp11_port);
 }
 
 /* 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:
@@ -4085,7 +4085,7 @@ ofputil_check_output_port(uint16_t port, int max_ports)
         return 0;
 
     default:
-        if (port < max_ports) {
+        if (PORT_COMPARE(port, <, max_ports)) {
             return 0;
         }
         return OFPERR_OFPBAC_BAD_OUT_PORT;
@@ -4121,46 +4121,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 (PORT_COMPARE(port32, <, OFPP_MAX)) {
+            /* Pass. */
+        } else if (PORT_COMPARE(port32, <, 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 (PORT_COMPARE(port32, <=, OFPP_LAST_RESV)) {
             struct ds msg;
 
             ds_init(&msg);
-            ofputil_format_port(port32, &msg);
+            ofputil_format_port((OVS_FORCE ofp_port_t) 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 (PORT_COMPARE(port32, <, 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, (OVS_FORCE uint32_t) OFPP11_MAX, UINT32_MAX);
             return false;
         } else {
-            *portp = port32 - OFPP11_OFFSET;
-            return true;
+            port32 -= OFPP11_OFFSET;
         }
+
+        *portp = (OVS_FORCE ofp_port_t) 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},
@@ -4183,7 +4179,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;
 
@@ -4524,7 +4520,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;
 
@@ -4533,7 +4529,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 = ofp_htons(port);
         break;
     }
     case OFP11_VERSION:
@@ -4556,7 +4552,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 = ofp_htons(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));
@@ -4640,7 +4636,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 = 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));
@@ -4780,7 +4776,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:
@@ -4792,7 +4788,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 = ofp_ntohs(psr10->port_no);
         return 0;
     }
 
@@ -4819,7 +4815,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 = 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;
@@ -4857,8 +4853,8 @@ ofputil_encode_queue_stats_request(enum ofp_version ofp_version,
         request = ofpraw_alloc(OFPRAW_OFPST10_QUEUE_REQUEST, ofp_version, 0);
         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);
+        req->port_no = ofp_htons(oqsr->port_no == OFPP_ANY
+                                 ? OFPP_ALL : oqsr->port_no);
         req->queue_id = htonl(oqsr->queue_id);
         break;
     }
@@ -4888,7 +4884,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 = 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));
@@ -4993,7 +4989,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 = ofp_htons(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 010c34d..c1d7f53 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -31,12 +31,12 @@
 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. */
@@ -218,7 +218,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. */
@@ -240,7 +240,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;
 };
 
@@ -346,7 +346,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. */
 };
@@ -386,7 +386,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;
@@ -494,7 +494,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;
@@ -531,7 +531,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;
 };
@@ -673,7 +673,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,
@@ -687,23 +687,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;
 };
 
@@ -715,7 +715,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/sflow.h b/lib/sflow.h
index 0d1f2b9..58288b1 100644
--- a/lib/sflow.h
+++ b/lib/sflow.h
@@ -8,6 +8,8 @@
 #ifndef SFLOW_H
 #define SFLOW_H 1
 
+#include "flow.h"
+
 typedef enum {
     SFL_DSCLASS_IFINDEX = 0,
     SFL_DSCLASS_VLAN = 1,
diff --git a/lib/sflow_api.h b/lib/sflow_api.h
index 3cc060b..a5fa78d 100644
--- a/lib/sflow_api.h
+++ b/lib/sflow_api.h
@@ -153,7 +153,7 @@ typedef struct _SFLPoller {
     struct _SFLAgent *agent; /* pointer to my agent */
     void *magic;             /* ptr to pass back in getCountersFn() */
     getCountersFn_t getCountersFn;
-    u_int32_t bridgePort; /* port number local to bridge */
+    odp_port_t bridgePort; /* port number local to bridge */
     /* private fields */
     SFLReceiver *myReceiver;
     time_t countersCountdown;
@@ -279,8 +279,8 @@ void sfl_agent_set_agentSubId(SFLAgent *agent, u_int32_t subId);
 
 /* The poller may need a separate number to reference the local bridge port
    to get counters if it is not the same as the global ifIndex */
-void sfl_poller_set_bridgePort(SFLPoller *poller, u_int32_t port_no);
-u_int32_t sfl_poller_get_bridgePort(SFLPoller *poller);
+void sfl_poller_set_bridgePort(SFLPoller *poller, odp_port_t port_no);
+odp_port_t sfl_poller_get_bridgePort(SFLPoller *poller);
 
 /* call this to indicate a discontinuity with a counter like samplePool so that the
    sflow collector will ignore the next delta */
diff --git a/lib/sflow_poller.c b/lib/sflow_poller.c
index d2e4155..e0c122f 100644
--- a/lib/sflow_poller.c
+++ b/lib/sflow_poller.c
@@ -104,11 +104,11 @@ void sfl_poller_set_sFlowCpInterval(SFLPoller *poller, u_int32_t sFlowCpInterval
   to get counters if it is not the same as the global ifIndex.
 */
 
-void sfl_poller_set_bridgePort(SFLPoller *poller, u_int32_t port_no) {
+void sfl_poller_set_bridgePort(SFLPoller *poller, odp_port_t port_no) {
     poller->bridgePort = port_no;
 }
 
-u_int32_t sfl_poller_get_bridgePort(SFLPoller *poller) {
+odp_port_t sfl_poller_get_bridgePort(SFLPoller *poller) {
     return poller->bridgePort;
 }
 
diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
index 1a1ab6c..effd058 100644
--- a/ofproto/connmgr.c
+++ b/ofproto/connmgr.c
@@ -1038,7 +1038,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);
 }
@@ -1644,7 +1644,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 506f9c7..2a60ee5 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..d83624b 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_u32(a) == (OVS_FORCE uint32_t) 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..c4894e2 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
+            | ((OVS_FORCE uint16_t) expired->flow.in_port.ofp_port & 0x1ff));
+        nf_rec->output = htons(iface
+            | ((OVS_FORCE uint16_t) 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 = ofp_htons(expired->flow.in_port.ofp_port);
+        nf_rec->output = ofp_htons(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..5e0290d 100644
--- a/ofproto/netflow.h
+++ b/ofproto/netflow.h
@@ -38,11 +38,11 @@ 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 ((OVS_FORCE ofp_port_t) \
+                      ((OVS_FORCE uint16_t) OFPP_NONE - 1))
+#define NF_OUT_DROP  ((OVS_FORCE ofp_port_t) \
+                      ((OVS_FORCE uint16_t) OFPP_NONE - 2))
 
 struct netflow_flow {
     long long int last_expired;   /* Time this flow last timed out. */
@@ -51,7 +51,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..d5a9524 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_odp_port(odp_port, 0),
+                                      &ds->ports) {
         if (dsp->odp_port == odp_port) {
             return dsp;
         }
@@ -343,7 +344,7 @@ dpif_sflow_add_poller(struct dpif_sflow *ds, struct dpif_sflow_port *dsp)
 
 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_odp_port(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.c b/ofproto/ofproto-dpif.c
index a9d2ddd..df3ba2a 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -189,7 +189,7 @@ static void bundle_del_port(struct ofport_dpif *);
 static void bundle_run(struct ofbundle *);
 static void bundle_wait(struct ofbundle *);
 static struct ofbundle *lookup_input_bundle(const struct ofproto_dpif *,
-                                            uint16_t in_port, bool warn,
+                                            ofp_port_t in_port, bool warn,
                                             struct ofport_dpif **in_ofportp);
 
 /* A controller may use OFPP_NONE as the ingress port to indicate that
@@ -232,7 +232,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];
@@ -327,7 +327,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. */
 };
@@ -343,7 +343,7 @@ static void xlate_actions(struct xlate_in *, struct xlate_out *);
 
 static void xlate_actions_for_side_effects(struct xlate_in *);
 
-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 size_t put_userspace_action(const struct ofproto_dpif *,
@@ -513,7 +513,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. */
@@ -536,7 +536,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;
 };
 
@@ -559,22 +559,22 @@ 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 uint16_t vsp_realdev_to_vlandev(const struct ofproto_dpif *,
-                                       uint16_t realdev_ofp_port,
-                                       ovs_be16 vlan_tci);
+static ofp_port_t vsp_realdev_to_vlandev(const struct ofproto_dpif *,
+                                         ofp_port_t realdev,
+                                         ovs_be16 vlan_tci);
 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 uint32_t ofp_port_to_odp_port(const struct ofproto_dpif *,
-                                     uint16_t ofp_port);
-static uint16_t odp_port_to_ofp_port(const struct ofproto_dpif *,
-                                     uint32_t odp_port);
+static odp_port_t ofp_port_to_odp_port(const struct ofproto_dpif *,
+                                       ofp_port_t ofp_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)
@@ -659,7 +659,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);
 
 struct avg_subfacet_rates {
     double add_rate;     /* Moving average of new flows created per minute. */
@@ -677,13 +677,13 @@ struct ofproto_dpif {
     /* Special OpenFlow rules. */
     struct rule_dpif *miss_rule; /* Sends flow table misses to controller. */
     struct rule_dpif *no_packet_in_rule; /* Drops flow table misses. */
-    struct rule_dpif *drop_frags_rule; /* Used in OFPC_FRAG_DROP mode. */
+    struct rule_dpif *drop_frags_rule;   /* Used in OFPC_FRAG_DROP mode. */
 
     /* Bridging. */
     struct netflow *netflow;
     struct dpif_sflow *sflow;
     struct dpif_ipfix *ipfix;
-    struct hmap bundles;        /* Contains "struct ofbundle"s. */
+    struct hmap bundles;                 /* Contains "struct ofbundle"s. */
     struct mac_learning *ml;
     struct ofmirror *mirrors[MAX_MIRRORS];
     bool has_mirrors;
@@ -780,9 +780,9 @@ ofproto_dpif_cast(const struct ofproto *ofproto)
 }
 
 static struct ofport_dpif *get_ofp_port(const struct ofproto_dpif *,
-                                        uint16_t ofp_port);
+                                        ofp_port_t ofp_port);
 static struct ofport_dpif *get_odp_port(const struct ofproto_dpif *,
-                                        uint32_t odp_port);
+                                        odp_port_t odp_port);
 static void ofproto_trace(struct ofproto_dpif *, const struct flow *,
                           const struct ofpbuf *,
                           const struct initial_vals *, struct ds *);
@@ -805,7 +805,7 @@ static void send_netflow_active_timeouts(struct ofproto_dpif *);
 static int send_packet(const struct ofport_dpif *, struct ofpbuf *packet);
 static size_t compose_sflow_action(const struct ofproto_dpif *,
                                    struct ofpbuf *odp_actions,
-                                   const struct flow *, uint32_t odp_port);
+                                   const struct flow *, odp_port_t odp_port);
 static void compose_ipfix_action(const struct ofproto_dpif *,
                                  struct ofpbuf *odp_actions,
                                  const struct flow *);
@@ -972,17 +972,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 = OVSP_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,
+                                      (OVS_FORCE uint32_t) odp_port);
                             node = simap_find(&backer->tnl_backers, dp_port);
                         }
                     }
                 }
 
-                iter->odp_port = node ? node->data : OVSP_NONE;
+                iter->odp_port = node ? (OVS_FORCE odp_port_t) node->data
+                                        : OVSP_NONE;
                 if (tnl_port_reconfigure(&iter->up, iter->odp_port,
                                          &iter->tnl_port)) {
                     backer->need_revalidate = REV_RECONFIGURE;
@@ -991,7 +993,7 @@ type_run(const char *type)
         }
 
         SIMAP_FOR_EACH (node, &tmp_backers) {
-            dpif_port_del(backer->dpif, node->data);
+            dpif_port_del(backer->dpif, (OVS_FORCE odp_port_t) node->data);
         }
         simap_destroy(&tmp_backers);
 
@@ -1237,7 +1239,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
@@ -1348,7 +1350,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;
 
@@ -1358,7 +1360,10 @@ 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_,
+                           (OVS_FORCE ofp_port_t)
+                              MIN((OVS_FORCE int) max_ports,
+                                  (OVS_FORCE int) OFPP_MAX));
 
     ofproto->netflow = NULL;
     ofproto->sflow = NULL;
@@ -1856,7 +1861,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_odp_port(port->odp_port, 0));
     }
     dpif_port_destroy(&dpif_port);
 
@@ -2504,7 +2509,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;
@@ -3147,14 +3152,14 @@ set_mac_table_config(struct ofproto *ofproto_, unsigned int idle_time,
 /* Ports. */
 
 static 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;
 }
 
 static 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;
@@ -3327,7 +3332,7 @@ port_add(struct ofproto *ofproto_, struct netdev *netdev)
     }
 
     if (!dpif_port_exists(ofproto->backer->dpif, dp_port_name)) {
-        uint32_t port_no = UINT32_MAX;
+        odp_port_t port_no = OVSP_NONE;
         int error;
 
         error = dpif_port_add(ofproto->backer->dpif, netdev, &port_no);
@@ -3335,7 +3340,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, (OVS_FORCE uint32_t) port_no);
         }
     }
 
@@ -3348,7 +3354,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);
@@ -3917,7 +3923,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,
                 struct initial_vals *initial_vals)
 {
     const struct ofport_dpif *port;
@@ -3935,13 +3941,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;
     }
@@ -4016,7 +4022,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;
@@ -4055,7 +4061,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);
@@ -4159,7 +4165,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, NULL)
@@ -4697,7 +4703,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);
@@ -4794,7 +4800,8 @@ 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,
+                                (OVS_FORCE odp_port_t) nl_attr_get_u32(a));
             if (port && port->bundle && port->bundle->bond) {
                 bond_account(port->bundle->bond, &facet->flow,
                              vlan_tci_to_vid(vlan_tci), n_bytes);
@@ -5121,7 +5128,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);
         }
@@ -5466,9 +5473,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;
     }
 
@@ -5643,13 +5651,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);
@@ -5713,7 +5723,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,
+                                         OVSP_NONE);
         odp_put_userspace_action(pid, &cookie, sizeof cookie.slow_path, &buf);
     } else {
         put_userspace_action(ofproto, &buf, flow, &cookie,
@@ -5733,7 +5744,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);
 }
@@ -5768,7 +5780,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;
@@ -5803,12 +5815,12 @@ 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;
     }
 
@@ -5847,7 +5859,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;
     }
 
@@ -5902,7 +5914,7 @@ fix_sflow_action(struct xlate_ctx *ctx)
 }
 
 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);
@@ -5910,7 +5922,7 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
     uint32_t flow_skb_mark;
     uint8_t flow_nw_tos;
     struct priority_to_dscp *pdscp;
-    uint32_t out_port, odp_port;
+    odp_port_t out_port, odp_port;
 
     /* If 'struct flow' gets additional metadata, we'll need to zero it out
      * before traversing a patch port. */
@@ -5946,25 +5958,26 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
         }
 
         ctx->ofproto = ofproto_dpif_cast(peer->up.ofproto);
-        ctx->xin->flow.in_port = peer->up.ofp_port;
+        ctx->xin->flow.in_port.ofp_port = peer->up.ofp_port;
         ctx->xin->flow.metadata = htonll(0);
         memset(&ctx->xin->flow.tunnel, 0, sizeof ctx->xin->flow.tunnel);
         memset(ctx->xin->flow.regs, 0, sizeof ctx->xin->flow.regs);
 
-        in_port = get_ofp_port(ctx->ofproto, ctx->xin->flow.in_port);
+        in_port = get_ofp_port(ctx->ofproto, ctx->xin->flow.in_port.ofp_port);
         special = process_special(ctx->ofproto, &ctx->xin->flow, in_port,
                                   ctx->xin->packet);
         if (special) {
             ctx->xout->slow = special;
         } else if (!in_port || may_receive(in_port, ctx)) {
             if (!in_port || stp_forward_in_state(in_port->stp_state)) {
-                xlate_table_action(ctx, ctx->xin->flow.in_port, 0, true);
+                xlate_table_action(ctx, ctx->xin->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, ctx->xin->flow.in_port, 0, true);
+                xlate_table_action(ctx, ctx->xin->flow.in_port.ofp_port, 0, true);
                 ctx->base_flow = old_base_flow;
                 ctx->xout->odp_actions.size = old_size;
             }
@@ -6014,7 +6027,7 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
                                  &ctx->xout->odp_actions);
         ctx->xin->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,
                                               ctx->xin->flow.vlan_tci);
@@ -6028,7 +6041,8 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port,
     }
     commit_odp_actions(&ctx->xin->flow, &ctx->base_flow,
                        &ctx->xout->odp_actions);
-    nl_msg_put_u32(&ctx->xout->odp_actions, OVS_ACTION_ATTR_OUTPUT, out_port);
+    nl_msg_put_u32(&ctx->xout->odp_actions,
+                   OVS_ACTION_ATTR_OUTPUT, (OVS_FORCE uint32_t) out_port);
 
     ctx->sflow_odp_port = odp_port;
     ctx->sflow_n_outputs++;
@@ -6042,7 +6056,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);
 }
@@ -6091,24 +6105,24 @@ 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__(ctx->ofproto, &ctx->xin->flow, table_id);
 
         tag_the_flow(ctx, rule);
 
         /* Restore the original input port.  Otherwise OFPP_NORMAL and
          * OFPP_IN_PORT will have surprising behavior. */
-        ctx->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);
 
@@ -6136,12 +6150,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;
@@ -6158,9 +6172,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;
         }
 
@@ -6313,18 +6327,19 @@ execute_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);
@@ -6342,7 +6357,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");
@@ -6366,7 +6381,8 @@ xlate_output_reg_action(struct xlate_ctx *ctx,
 {
     uint64_t port = mf_get_subfield(&or->src, &ctx->xin->flow);
     if (port <= UINT16_MAX) {
-        xlate_output_action(ctx, port, or->max_len, false);
+        xlate_output_action(ctx, (OVS_FORCE ofp_port_t) port,
+                            or->max_len, false);
     }
 }
 
@@ -6374,7 +6390,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;
@@ -6390,8 +6406,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;
     }
 
@@ -6424,7 +6440,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;
@@ -6449,12 +6465,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, slave_enabled_cb,
                           ctx->ofproto);
     if (bundle->dst.field) {
-        nxm_reg_load(&bundle->dst, port, &ctx->xin->flow);
+        nxm_reg_load(&bundle->dst, (OVS_FORCE uint16_t) port, &ctx->xin->flow);
     } else {
         xlate_output_action(ctx, port, 0, false);
     }
@@ -6965,7 +6981,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
         }
     }
 
-    in_port = get_ofp_port(ctx.ofproto, ctx.xin->flow.in_port);
+    in_port = get_ofp_port(ctx.ofproto, ctx.xin->flow.in_port.ofp_port);
     special = process_special(ctx.ofproto, &ctx.xin->flow, in_port,
                               ctx.xin->packet);
     if (special) {
@@ -6974,7 +6990,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
         static struct vlog_rate_limit trace_rl = VLOG_RATE_LIMIT_INIT(1, 1);
         struct initial_vals initial_vals;
         size_t sample_actions_len;
-        uint32_t local_odp_port;
+        odp_port_t local_odp_port;
 
         initial_vals.vlan_tci = ctx.base_flow.vlan_tci;
 
@@ -7235,7 +7251,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;
@@ -7271,7 +7287,8 @@ 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,
+                              (OVS_FORCE odp_port_t) nl_attr_get_u32(a));
         if (ofport && ofport->bundle) {
             mirrors |= ofport->bundle->dst_mirrors;
         }
@@ -7396,7 +7413,7 @@ update_learning_table(struct ofproto_dpif *ofproto,
 }
 
 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;
@@ -7506,7 +7523,8 @@ xlate_normal(struct xlate_ctx *ctx)
 
     ctx->xout->has_normal = true;
 
-    in_bundle = lookup_input_bundle(ctx->ofproto, ctx->xin->flow.in_port,
+    in_bundle = lookup_input_bundle(ctx->ofproto,
+                                    ctx->xin->flow.in_port.ofp_port,
                                     ctx->xin->packet != NULL, &in_port);
     if (!in_bundle) {
         xlate_report(ctx, "no input bundle, dropping");
@@ -7724,7 +7742,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);
 
@@ -8059,6 +8078,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);
@@ -8067,7 +8089,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);
             initial_vals.vlan_tci = flow.vlan_tci;
         }
     }
@@ -8311,7 +8333,7 @@ show_dp_format(const struct ofproto_dpif *ofproto, struct ds *ds)
         struct ofport *ofport = node->data;
         const char *name = netdev_get_name(ofport->netdev);
         const char *type = netdev_get_type(ofport->netdev);
-        uint32_t odp_port;
+        odp_port_t odp_port;
 
         ds_put_format(ds, "\t%s %u/", name, ofport->ofp_port);
 
@@ -8513,7 +8535,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_);
@@ -8545,9 +8567,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((OVS_FORCE uint16_t) realdev_ofp_port, vid);
 }
 
 /* Returns the OFP port number of the Linux VLAN device that corresponds to
@@ -8557,9 +8579,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. */
-static uint16_t
+static 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);
@@ -8578,11 +8600,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_ofp_port(vlandev_ofp_port, 0),
                              &ofproto->vlandev_map) {
         if (vsp->vlandev_ofp_port == vlandev_ofp_port) {
             return vsp;
@@ -8601,9 +8624,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;
@@ -8628,17 +8651,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;
 }
@@ -8662,7 +8685,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);
 
@@ -8673,7 +8696,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_ofp_port(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;
@@ -8686,20 +8709,20 @@ vsp_add(struct ofport_dpif *port, uint16_t realdev_ofp_port, int vid)
     }
 }
 
-static uint32_t
-ofp_port_to_odp_port(const struct ofproto_dpif *ofproto, uint16_t ofp_port)
+static 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;
 }
 
 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_odp_port(odp_port, 0),
                              &backer->odp_to_ofport_map) {
         if (port->odp_port == odp_port) {
             return port;
@@ -8709,8 +8732,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-provider.h b/ofproto/ofproto-provider.h
index db0d589..7bc92be 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -65,8 +65,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;
@@ -243,12 +243,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 *);
 
@@ -689,7 +689,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,
@@ -1315,7 +1315,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 3788c2f..658931c 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -448,7 +448,8 @@ 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((OVS_FORCE uint16_t)
+                                            ofproto->max_ports);
     bitmap_set1(ofproto->ofp_port_ids, 0);
 
     /* Check that hidden tables, if any, are at the end. */
@@ -497,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(PORT_COMPARE(max_ports, <=, OFPP_MAX));
     ofproto->max_ports = max_ports;
 }
 
@@ -709,7 +710,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);
@@ -730,7 +731,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);
@@ -755,7 +756,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)
 {
@@ -776,7 +777,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) {
@@ -791,7 +792,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;
@@ -820,7 +821,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;
@@ -848,7 +849,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);
@@ -862,7 +863,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
@@ -1499,16 +1500,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,
+                  (OVS_FORCE uint16_t) ofp_port);
         update_port(ofproto, netdev_name);
     }
     if (ofp_portp) {
@@ -1544,7 +1546,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>";
@@ -1681,26 +1683,30 @@ 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;
+    ofp_port_t end_port_no = ofproto->alloc_port_no;
 
-    ofp_port = simap_get(&ofproto->ofp_requests, netdev_name);
+    ofp_port = (OVS_FORCE ofp_port_t) 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 (PORT_COMPARE(ofp_port, >=, ofproto->max_ports)
+        || bitmap_is_set(ofproto->ofp_port_ids,
+                         (OVS_FORCE uint16_t) ofp_port)) {
         /* 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) {
+            ofp_port_increment(&(ofproto->alloc_port_no), 1);
+            if (PORT_COMPARE(ofproto->alloc_port_no,
+                           >=, ofproto->max_ports)) {
                 ofproto->alloc_port_no = 0;
             }
             if (!bitmap_is_set(ofproto->ofp_port_ids,
-                               ofproto->alloc_port_no)) {
+                   (OVS_FORCE uint16_t) ofproto->alloc_port_no)) {
                 ofp_port = ofproto->alloc_port_no;
                 break;
             }
@@ -1709,15 +1715,15 @@ alloc_ofp_port(struct ofproto *ofproto, const char *netdev_name)
             }
         }
     }
-    bitmap_set1(ofproto->ofp_port_ids, ofp_port);
+    bitmap_set1(ofproto->ofp_port_ids, (OVS_FORCE uint16_t) 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 (PORT_COMPARE(ofp_port, <, ofproto->max_ports)) {
+        bitmap_set0(ofproto->ofp_port_ids, (OVS_FORCE uint16_t) ofp_port);
     }
 }
 
@@ -1808,7 +1814,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_ofp_port(ofport->ofp_port, 0));
     shash_add(&p->port_by_name, netdev_name, ofport);
 
     update_mtu(p, ofport);
@@ -1884,7 +1891,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) {
@@ -1928,12 +1935,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_ofp_port(ofp_port, 0),
+                             &ofproto->ports) {
         if (port->ofp_port == ofp_port) {
             return port;
         }
@@ -1970,6 +1978,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)) {
@@ -2031,7 +2040,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,
+                          (OVS_FORCE uint16_t) iface_hint->ofp_port);
             }
 
             netdev = ofport_open(p, &ofproto_port, &pp);
@@ -2155,7 +2165,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));
@@ -2164,7 +2174,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;
@@ -2193,13 +2203,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);
 }
 
@@ -2360,6 +2372,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);
@@ -2375,7 +2388,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 (PORT_COMPARE(po.in_port, >=, p->max_ports)
+        && PORT_COMPARE(po.in_port, <, OFPP_MAX)) {
         error = OFPERR_OFPBRC_BAD_PORT;
         goto exit_free_ofpacts;
     }
@@ -2393,7 +2407,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,
@@ -2581,7 +2596,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);
@@ -2717,7 +2732,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;
@@ -2768,7 +2783,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;
@@ -2925,7 +2940,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);
@@ -4249,7 +4264,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);
@@ -5002,8 +5017,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 18241e7..90da2a0 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..95f9ca5 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_ofp_port(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 df28df3..a0e5f3d 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;
@@ -212,7 +212,7 @@ tnl_port_receive(const struct flow *flow)
  * '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
  * shouldn't occur. */
-uint32_t
+odp_port_t
 tnl_port_send(const struct tnl_port *tnl_port, struct flow *flow)
 {
     const struct netdev_tunnel_config *cfg;
diff --git a/ofproto/tunnel.h b/ofproto/tunnel.h
index 34c1133..828a4f0 100644
--- a/ofproto/tunnel.h
+++ b/ofproto/tunnel.h
@@ -31,14 +31,14 @@
 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 *);
+odp_port_t tnl_port_send(const struct tnl_port *, struct flow *);
 
 /* 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 f5b24b4..488e7f3 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] = (OVS_FORCE uint32_t) OFPP_NONE;
     }
 
     /* Cycles through each possible liveness permutation for the given
@@ -186,11 +186,11 @@ 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;
 
-            old_slave_id = flow->regs[0];
+            old_slave_id = (OVS_FORCE ofp_port_t) flow->regs[0];
             ofp_port = bundle_execute(bundle, flow, slave_enabled_cb, &sg);
-            flow->regs[0] = ofp_port;
+            flow->regs[0] = (OVS_FORCE uint32_t) ofp_port;
 
             if (ofp_port != OFPP_NONE) {
                 slave_lookup(&sg, ofp_port)->flow_count++;
diff --git a/tests/test-classifier.c b/tests/test-classifier.c
index 18dee86..6e8b6d8 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[] = { (OVS_FORCE ofp_port_t) 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..1e7e8a3 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 = (OVS_FORCE ofp_port_t) 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..f801d7e 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 = OVSP_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 = (OVS_FORCE odp_port_t) 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 != (OVS_FORCE odp_port_t) 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 = (OVS_FORCE odp_port_t) 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..0d037a9 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, uint32_t port_no,
                        struct ofputil_phy_port *pp, bool *trunc)
 {
     struct ofputil_switch_features features;
@@ -671,7 +671,7 @@ fetch_port_by_features(const char *vconn_name,
 
     while (!ofputil_pull_phy_port(oh->version, &b, pp)) {
         if (port_no != UINT_MAX
-            ? port_no == pp->port_no
+            ? port_no == (OVS_FORCE uint32_t) pp->port_no
             : !strcmp(pp->name, port_name)) {
             found = true;
             goto exit;
@@ -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, uint32_t port_no,
                     struct ofputil_phy_port *pp)
 {
     struct ofpbuf *request;
@@ -729,8 +729,9 @@ 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 != UINT_MAX
+                    ? port_no == (OVS_FORCE uint32_t) pp->port_no
+                    : !strcmp(pp->name, port_name)) {
                     found = true;
                     break;
                 }
@@ -754,7 +755,7 @@ static void
 fetch_ofputil_phy_port(const char *vconn_name, const char *port_name,
                        struct ofputil_phy_port *pp)
 {
-    unsigned int port_no;
+    uint32_t port_no;
     bool found;
     bool trunc;
 
@@ -779,10 +780,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 +1490,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 f5c4202..0988ef4 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. */
@@ -246,7 +246,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 *,
@@ -256,9 +257,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 *);
@@ -266,7 +267,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.)
  *
@@ -1268,13 +1269,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_ofp_port(ofp_port, 0));
     iface_set_ofport(iface->cfg, ofp_port);
 }
 
@@ -1309,7 +1311,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) {
@@ -1412,7 +1414,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;
@@ -1440,7 +1442,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) {
@@ -1476,7 +1478,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;
@@ -1487,6 +1489,7 @@ iface_create(struct bridge *br, struct if_cfg *if_cfg, uint16_t ofp_port)
     int error;
     bool ok = true;
 
+    VLOG_INFO("iface_create ofp_port: %u", ofp_port);
     /* Do the bits that can fail up front.
      *
      * It's a bit dangerous to call bridge_run_fast() here as ofproto's
@@ -1538,7 +1541,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);
@@ -3299,7 +3302,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 = (OVS_FORCE int) iface->ofp_port;
     }
 
     if (priority <= 0 || priority > UINT16_MAX) {
@@ -3487,12 +3490,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_ofp_port(ofp_port, 0),
+                             &br->ifaces) {
         if (iface->ofp_port == ofp_port) {
             return iface;
         }
@@ -3528,10 +3532,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 : (OVS_FORCE uint16_t) ofport;
     if (if_cfg && !ovsdb_idl_row_is_synthetic(&if_cfg->header_)) {
         ovsrec_interface_set_ofport(if_cfg, &port_, 1);
     }
@@ -3717,11 +3721,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 ? (OVS_FORCE ofp_port_t) *cfg->ofport
+                                      : OFPP_NONE;
+    return cfg->n_ofport_request ? (OVS_FORCE ofp_port_t) *cfg->ofport_request
+                                 : ofport;
 }
 
 
@@ -4099,7 +4105,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