The OpenFlow protocol supports port numbers from 0 to 0xff00.
The datapath protocol supports port numbers from 0 to 0x100.
The datapath will reject port numbers in the range 0x100 to 0xff00, but the
secchan was not screening these out.  Thus, attempting to add a flow or
send a packet to one of these ports would result in a kernel EINVAL error,
instead of a more sensible OpenFlow error.  This commit remedies the
situation.
Thanks to Justin for pointing out the issue.
 
 int
 check_ofp_packet_out(const struct ofp_header *oh, struct ofpbuf *data,
-                     int *n_actionsp)
+                     int *n_actionsp, int max_ports)
 {
     const struct ofp_packet_out *opo;
     unsigned int actions_len, n_actions;
 
     n_actions = actions_len / sizeof(union ofp_action);
     error = validate_actions((const union ofp_action *) opo->actions,
-                             n_actions);
+                             n_actions, max_ports);
     if (error) {
         return error;
     }
 }
 
 static int
-check_action_port(int port)
+check_action_port(int port, int max_ports)
 {
     switch (port) {
     case OFPP_IN_PORT:
         return 0;
 
     default:
-        if (port >= 0 && port < OFPP_MAX) {
+        if (port >= 0 && port < max_ports) {
             return 0;
         }
         VLOG_WARN_RL(&bad_ofmsg_rl, "unknown output port %x", port);
 }
 
 static int
-check_action(const union ofp_action *a, unsigned int len)
+check_action(const union ofp_action *a, unsigned int len, int max_ports)
 {
     int error;
 
     switch (a->type) {
     case OFPAT_OUTPUT:
-        error = check_action_port(ntohs(a->output.port));
+        error = check_action_port(ntohs(a->output.port), max_ports);
         if (error) {
             return error;
         }
 }
 
 int
-validate_actions(const union ofp_action *actions, size_t n_actions)
+validate_actions(const union ofp_action *actions, size_t n_actions,
+                 int max_ports)
 {
     const union ofp_action *a;
 
                         n_slots, slots_left);
             return ofp_mkerr(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
         }
-        error = check_action(a, len);
+        error = check_action(a, len, max_ports);
         if (error) {
             return error;
         }
 
                             size_t size, size_t array_elt_size,
                             size_t *n_array_elts);
 int check_ofp_packet_out(const struct ofp_header *, struct ofpbuf *data,
-                         int *n_actions);
+                         int *n_actions, int max_ports);
 
 struct flow_stats_iterator {
     const uint8_t *pos, *end;
                                       const union ofp_action *,
                                       size_t n_actions);
 const union ofp_action *actions_next(struct actions_iterator *);
-int validate_actions(const union ofp_action *, size_t n_actions);
+int validate_actions(const union ofp_action *, size_t n_actions,
+                     int max_ports);
 
 void normalize_match(struct ofp_match *);
 
 
     struct port_array ports;    /* Index is ODP port nr; ofport->opp.port_no is
                                  * OFP port nr. */
     struct shash port_by_name;
+    uint32_t max_ports;
 
     /* Configuration. */
     struct switch_status *switch_status;
                struct ofproto **ofprotop)
 {
     struct dpifmon *dpifmon;
+    struct odp_stats stats;
     struct ofproto *p;
     struct dpif dpif;
     int error;
         VLOG_ERR("failed to open datapath %s: %s", datapath, strerror(error));
         return error;
     }
+    error = dpif_get_dp_stats(&dpif, &stats);
+    if (error) {
+        VLOG_ERR("failed to obtain stats for datapath %s: %s",
+                 datapath, strerror(error));
+        dpif_close(&dpif);
+        return error;
+    }
     error = dpif_set_listen_mask(&dpif, ODPL_MISS | ODPL_ACTION);
     if (error) {
         VLOG_ERR("failed to listen on datapath %s: %s",
     p->dpifmon = dpifmon;
     port_array_init(&p->ports);
     shash_init(&p->port_by_name);
+    p->max_ports = stats.max_ports;
 
     /* Initialize submodules. */
     p->switch_status = switch_status_create(p);
     flow_t flow;
     int error;
 
-    error = check_ofp_packet_out(oh, &payload, &n_actions);
+    error = check_ofp_packet_out(oh, &payload, &n_actions, p->max_ports);
     if (error) {
         return error;
     }
     }
 
     error = validate_actions((const union ofp_action *) ofm->actions,
-                             n_actions);
+                             n_actions, p->max_ports);
     if (error) {
         return error;
     }