util: Suppress build assertions when building with sparse.
[openvswitch] / ofproto / ofproto.c
index 39e2b30e1ddad90e7b108ca864292c6f321393c8..bc900dadff928f9a3e12e8b6072a48f2223c95b9 100644 (file)
@@ -101,7 +101,7 @@ struct rule;
 struct ofport {
     struct hmap_node hmap_node; /* In struct ofproto's "ports" hmap. */
     struct netdev *netdev;
-    struct ofp_phy_port opp;    /* In host byte order. */
+    struct ofp_phy_port opp;
     uint16_t odp_port;
     struct cfm *cfm;            /* Connectivity Fault Management, if any. */
 };
@@ -268,6 +268,7 @@ static void facet_flush_stats(struct ofproto *, struct facet *);
 
 static void facet_make_actions(struct ofproto *, struct facet *,
                                const struct ofpbuf *packet);
+static void facet_reset_dp_stats(struct facet *, struct dpif_flow_stats *);
 static void facet_update_stats(struct ofproto *, struct facet *,
                                const struct dpif_flow_stats *);
 static void facet_push_stats(struct ofproto *, struct facet *);
@@ -938,27 +939,20 @@ bool
 ofproto_port_is_floodable(struct ofproto *ofproto, uint16_t odp_port)
 {
     struct ofport *ofport = get_port(ofproto, odp_port);
-    return ofport && !(ofport->opp.config & OFPPC_NO_FLOOD);
+    return ofport && !(ofport->opp.config & htonl(OFPPC_NO_FLOOD));
 }
 
-/* Sends 'packet' out of port 'port_no' within 'p'.  If 'vlan_tci' is zero the
- * packet will not have any 802.1Q hader; if it is nonzero, then the packet
- * will be sent with the VLAN TCI specified by 'vlan_tci & ~VLAN_CFI'.
+/* Sends 'packet' out of port 'port_no' within 'p'.
  *
  * Returns 0 if successful, otherwise a positive errno value. */
 int
 ofproto_send_packet(struct ofproto *ofproto,
-                    uint32_t port_no, uint16_t vlan_tci,
-                    const struct ofpbuf *packet)
+                    uint32_t port_no, const struct ofpbuf *packet)
 {
     struct ofpbuf odp_actions;
     int error;
 
     ofpbuf_init(&odp_actions, 32);
-    if (vlan_tci != 0) {
-        nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_SET_DL_TCI,
-                       ntohs(vlan_tci & ~VLAN_CFI));
-    }
     nl_msg_put_u32(&odp_actions, ODP_ACTION_ATTR_OUTPUT, port_no);
     error = dpif_execute(ofproto->dpif, odp_actions.data, odp_actions.size,
                          packet);
@@ -1062,10 +1056,11 @@ reinit_ports(struct ofproto *p)
 }
 
 /* Opens and returns a netdev for 'dpif_port', or a null pointer if the netdev
- * cannot be opened.  On success, also fills in 'opp', in *HOST* byte order. */
+ * cannot be opened.  On success, also fills in 'opp'. */
 static struct netdev *
 ofport_open(const struct dpif_port *dpif_port, struct ofp_phy_port *opp)
 {
+    uint32_t curr, advertised, supported, peer;
     struct netdev_options netdev_options;
     enum netdev_flags flags;
     struct netdev *netdev;
@@ -1086,14 +1081,18 @@ ofport_open(const struct dpif_port *dpif_port, struct ofp_phy_port *opp)
     }
 
     netdev_get_flags(netdev, &flags);
+    netdev_get_features(netdev, &curr, &advertised, &supported, &peer);
 
-    opp->port_no = odp_port_to_ofp_port(dpif_port->port_no);
+    opp->port_no = htons(odp_port_to_ofp_port(dpif_port->port_no));
     netdev_get_etheraddr(netdev, opp->hw_addr);
     ovs_strzcpy(opp->name, dpif_port->name, sizeof opp->name);
-    opp->config = flags & NETDEV_UP ? 0 : OFPPC_PORT_DOWN;
-    opp->state = netdev_get_carrier(netdev) ? 0 : OFPPS_LINK_DOWN;
-    netdev_get_features(netdev, &opp->curr, &opp->advertised,
-                        &opp->supported, &opp->peer);
+    opp->config = flags & NETDEV_UP ? 0 : htonl(OFPPC_PORT_DOWN);
+    opp->state = netdev_get_carrier(netdev) ? 0 : htonl(OFPPS_LINK_DOWN);
+    opp->curr = htonl(curr);
+    opp->advertised = htonl(advertised);
+    opp->supported = htonl(supported);
+    opp->peer = htonl(peer);
+
     return netdev;
 }
 
@@ -1122,7 +1121,7 @@ ofport_equal(const struct ofp_phy_port *a, const struct ofp_phy_port *b)
     BUILD_ASSERT_DECL(sizeof *a == 48); /* Detect ofp_phy_port changes. */
     return (!memcmp(a->hw_addr, b->hw_addr, sizeof a->hw_addr)
             && a->state == b->state
-            && !((a->config ^ b->config) & OFPPC_PORT_DOWN)
+            && !((a->config ^ b->config) & htonl(OFPPC_PORT_DOWN))
             && a->curr == b->curr
             && a->advertised == b->advertised
             && a->supported == b->supported
@@ -1145,7 +1144,7 @@ ofport_install(struct ofproto *p,
     ofport = xmalloc(sizeof *ofport);
     ofport->netdev = netdev;
     ofport->opp = *opp;
-    ofport->odp_port = ofp_port_to_odp_port(opp->port_no);
+    ofport->odp_port = ofp_port_to_odp_port(ntohs(opp->port_no));
     ofport->cfm = NULL;
 
     /* Add port to 'p'. */
@@ -1195,14 +1194,17 @@ ofport_modified(struct ofproto *ofproto, struct ofport *port,
                 struct netdev *netdev, struct ofp_phy_port *opp)
 {
     memcpy(port->opp.hw_addr, opp->hw_addr, ETH_ADDR_LEN);
-    port->opp.config = ((port->opp.config & ~OFPPC_PORT_DOWN)
-                        | (opp->config & OFPPC_PORT_DOWN));
+    port->opp.config = ((port->opp.config & ~htonl(OFPPC_PORT_DOWN))
+                        | (opp->config & htonl(OFPPC_PORT_DOWN)));
     port->opp.state = opp->state;
     port->opp.curr = opp->curr;
     port->opp.advertised = opp->advertised;
     port->opp.supported = opp->supported;
     port->opp.peer = opp->peer;
 
+    netdev_monitor_remove(ofproto->netdev_monitor, port->netdev);
+    netdev_monitor_add(ofproto->netdev_monitor, netdev);
+
     netdev_close(port->netdev);
     port->netdev = netdev;
 
@@ -1223,7 +1225,7 @@ ofport_run(struct ofproto *ofproto, struct ofport *ofport)
             ccm = eth_compose(&packet, eth_addr_ccm, ofport->opp.hw_addr,
                               ETH_TYPE_CFM,  sizeof *ccm);
             cfm_compose_ccm(ofport->cfm, ccm);
-            ofproto_send_packet(ofproto, ofport->odp_port, 0, &packet);
+            ofproto_send_packet(ofproto, ofport->odp_port, &packet);
             ofpbuf_uninit(&packet);
         }
     }
@@ -1629,6 +1631,12 @@ facet_make_actions(struct ofproto *p, struct facet *facet,
     ofpbuf_delete(odp_actions);
 }
 
+/* Updates 'facet''s flow in the datapath setting its actions to 'actions_len'
+ * bytes of actions in 'actions'.  If 'stats' is non-null, statistics counters
+ * in the datapath will be zeroed and 'stats' will be updated with traffic new
+ * since 'facet' was last updated.
+ *
+ * Returns 0 if successful, otherwise a positive errno value.*/
 static int
 facet_put__(struct ofproto *ofproto, struct facet *facet,
             const struct nlattr *actions, size_t actions_len,
@@ -1637,19 +1645,24 @@ facet_put__(struct ofproto *ofproto, struct facet *facet,
     struct odputil_keybuf keybuf;
     enum dpif_flow_put_flags flags;
     struct ofpbuf key;
+    int ret;
 
     flags = DPIF_FP_CREATE | DPIF_FP_MODIFY;
     if (stats) {
         flags |= DPIF_FP_ZERO_STATS;
-        facet->dp_packet_count = 0;
-        facet->dp_byte_count = 0;
     }
 
     ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
     odp_flow_key_from_flow(&key, &facet->flow);
 
-    return dpif_flow_put(ofproto->dpif, flags, key.data, key.size,
-                         actions, actions_len, stats);
+    ret = dpif_flow_put(ofproto->dpif, flags, key.data, key.size,
+                        actions, actions_len, stats);
+
+    if (stats) {
+        facet_reset_dp_stats(facet, stats);
+    }
+
+    return ret;
 }
 
 /* If 'facet' is installable, inserts or re-inserts it into 'p''s datapath.  If
@@ -1693,16 +1706,18 @@ facet_uninstall(struct ofproto *p, struct facet *facet)
         struct odputil_keybuf keybuf;
         struct dpif_flow_stats stats;
         struct ofpbuf key;
+        int error;
 
         ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
         odp_flow_key_from_flow(&key, &facet->flow);
 
-        if (!dpif_flow_del(p->dpif, key.data, key.size, &stats)) {
+        error = dpif_flow_del(p->dpif, key.data, key.size, &stats);
+        facet_reset_dp_stats(facet, &stats);
+        if (!error) {
             facet_update_stats(p, facet, &stats);
         }
+
         facet->installed = false;
-        facet->dp_packet_count = 0;
-        facet->dp_byte_count = 0;
     } else {
         assert(facet->dp_packet_count == 0);
         assert(facet->dp_byte_count == 0);
@@ -1721,6 +1736,24 @@ facet_is_controller_flow(struct facet *facet)
                                       htons(OFPP_CONTROLLER)));
 }
 
+/* Resets 'facet''s datapath statistics counters.  This should be called when
+ * 'facet''s statistics are cleared in the datapath.  If 'stats' is non-null,
+ * it should contain the statistics returned by dpif when 'facet' was reset in
+ * the datapath.  'stats' will be modified to only included statistics new
+ * since 'facet' was last updated. */
+static void
+facet_reset_dp_stats(struct facet *facet, struct dpif_flow_stats *stats)
+{
+    if (stats && facet->dp_packet_count < stats->n_packets
+        && facet->dp_byte_count < stats->n_bytes) {
+        stats->n_packets -= facet->dp_packet_count;
+        stats->n_bytes -= facet->dp_byte_count;
+    }
+
+    facet->dp_packet_count = 0;
+    facet->dp_byte_count = 0;
+}
+
 /* Folds all of 'facet''s statistics into its rule.  Also updates the
  * accounting ofhook and emits a NetFlow expiration if appropriate.  All of
  * 'facet''s statistics in the datapath should have been zeroed and folded into
@@ -1925,7 +1958,7 @@ handle_features_request(struct ofconn *ofconn, const struct ofp_header *oh)
                          (1u << OFPAT_ENQUEUE));
 
     HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
-        hton_ofp_phy_port(ofpbuf_put(buf, &port->opp, sizeof port->opp));
+        ofpbuf_put(buf, &port->opp, sizeof port->opp);
     }
 
     ofconn_send_reply(ofconn, buf);
@@ -1990,7 +2023,7 @@ add_output_action(struct action_xlate_ctx *ctx, uint16_t port)
     const struct ofport *ofport = get_port(ctx->ofproto, port);
 
     if (ofport) {
-        if (ofport->opp.config & OFPPC_NO_FWD) {
+        if (ofport->opp.config & htonl(OFPPC_NO_FWD)) {
             /* Forwarding disabled on port. */
             return;
         }
@@ -2045,7 +2078,7 @@ xlate_table_action(struct action_xlate_ctx *ctx, uint16_t in_port)
 }
 
 static void
-flood_packets(struct ofproto *ofproto, uint16_t odp_in_port, uint32_t mask,
+flood_packets(struct ofproto *ofproto, uint16_t odp_in_port, ovs_be32 mask,
               uint16_t *nf_output_iface, struct ofpbuf *odp_actions)
 {
     struct ofport *ofport;
@@ -2085,11 +2118,11 @@ xlate_output_action__(struct action_xlate_ctx *ctx,
         }
         break;
     case OFPP_FLOOD:
-        flood_packets(ctx->ofproto, ctx->flow.in_port, OFPPC_NO_FLOOD,
+        flood_packets(ctx->ofproto, ctx->flow.in_port, htonl(OFPPC_NO_FLOOD),
                       &ctx->nf_output_iface, ctx->odp_actions);
         break;
     case OFPP_ALL:
-        flood_packets(ctx->ofproto, ctx->flow.in_port, 0,
+        flood_packets(ctx->ofproto, ctx->flow.in_port, htonl(0),
                       &ctx->nf_output_iface, ctx->odp_actions);
         break;
     case OFPP_CONTROLLER:
@@ -2342,9 +2375,10 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
     const struct ofport *port;
 
     port = get_port(ctx->ofproto, ctx->flow.in_port);
-    if (port && port->opp.config & (OFPPC_NO_RECV | OFPPC_NO_RECV_STP) &&
+    if (port && port->opp.config & htonl(OFPPC_NO_RECV | OFPPC_NO_RECV_STP) &&
         port->opp.config & (eth_addr_equals(ctx->flow.dl_dst, eth_addr_stp)
-                            ? OFPPC_NO_RECV_STP : OFPPC_NO_RECV)) {
+                            ? htonl(OFPPC_NO_RECV_STP)
+                            : htonl(OFPPC_NO_RECV))) {
         /* Drop this flow. */
         return;
     }
@@ -2505,7 +2539,7 @@ xlate_actions(struct action_xlate_ctx *ctx,
  *
  * The log message mentions 'msg_type'. */
 static int
-reject_slave_controller(struct ofconn *ofconn, const const char *msg_type)
+reject_slave_controller(struct ofconn *ofconn, const char *msg_type)
 {
     if (ofconn_get_type(ofconn) == OFCONN_PRIMARY
         && ofconn_get_role(ofconn) == NX_ROLE_SLAVE) {
@@ -2586,11 +2620,11 @@ exit:
 
 static void
 update_port_config(struct ofproto *p, struct ofport *port,
-                   uint32_t config, uint32_t mask)
+                   ovs_be32 config, ovs_be32 mask)
 {
     mask &= config ^ port->opp.config;
-    if (mask & OFPPC_PORT_DOWN) {
-        if (config & OFPPC_PORT_DOWN) {
+    if (mask & htonl(OFPPC_PORT_DOWN)) {
+        if (config & htonl(OFPPC_PORT_DOWN)) {
             netdev_turn_flags_off(port->netdev, NETDEV_UP, true);
         } else {
             netdev_turn_flags_on(port->netdev, NETDEV_UP, true);
@@ -2598,14 +2632,14 @@ update_port_config(struct ofproto *p, struct ofport *port,
     }
 #define REVALIDATE_BITS (OFPPC_NO_RECV | OFPPC_NO_RECV_STP |    \
                          OFPPC_NO_FWD | OFPPC_NO_FLOOD)
-    if (mask & REVALIDATE_BITS) {
+    if (mask & htonl(REVALIDATE_BITS)) {
         COVERAGE_INC(ofproto_costly_flags);
-        port->opp.config ^= mask & REVALIDATE_BITS;
+        port->opp.config ^= mask & htonl(REVALIDATE_BITS);
         p->need_revalidate = true;
     }
 #undef REVALIDATE_BITS
-    if (mask & OFPPC_NO_PACKET_IN) {
-        port->opp.config ^= OFPPC_NO_PACKET_IN;
+    if (mask & htonl(OFPPC_NO_PACKET_IN)) {
+        port->opp.config ^= htonl(OFPPC_NO_PACKET_IN);
     }
 }
 
@@ -2628,7 +2662,7 @@ handle_port_mod(struct ofconn *ofconn, const struct ofp_header *oh)
     } else if (memcmp(port->opp.hw_addr, opm->hw_addr, OFP_ETH_ALEN)) {
         return ofp_mkerr(OFPET_PORT_MOD_FAILED, OFPPMFC_BAD_HW_ADDR);
     } else {
-        update_port_config(p, port, ntohl(opm->config), ntohl(opm->mask));
+        update_port_config(p, port, opm->config, opm->mask);
         if (opm->advertise) {
             netdev_set_advertisements(port->netdev, ntohl(opm->advertise));
         }
@@ -2743,8 +2777,7 @@ handle_table_stats_request(struct ofconn *ofconn,
     ots = append_ofp_stats_reply(sizeof *ots, ofconn, &msg);
     memset(ots, 0, sizeof *ots);
     strcpy(ots->name, "classifier");
-    ots->wildcards = (ofconn_get_flow_format(ofconn) == NXFF_OPENFLOW10
-                      ? htonl(OFPFW_ALL) : htonl(OVSFW_ALL));
+    ots->wildcards = htonl(OFPFW_ALL);
     ots->max_entries = htonl(1024 * 1024); /* An arbitrary big number. */
     ots->active_count = htonl(classifier_count(&p->cls));
     put_32aligned_be64(&ots->lookup_count, htonll(0));  /* XXX */
@@ -2767,7 +2800,7 @@ append_port_stat(struct ofport *port, struct ofconn *ofconn,
     netdev_get_stats(port->netdev, &stats);
 
     ops = append_ofp_stats_reply(sizeof *ops, ofconn, msgp);
-    ops->port_no = htons(port->opp.port_no);
+    ops->port_no = port->opp.port_no;
     memset(ops->pad, 0, sizeof ops->pad);
     put_32aligned_be64(&ops->rx_packets, htonll(stats.rx_packets));
     put_32aligned_be64(&ops->tx_packets, htonll(stats.tx_packets));
@@ -2832,7 +2865,6 @@ put_ofp_flow_stats(struct ofconn *ofconn, struct rule *rule,
 {
     struct ofp_flow_stats *ofs;
     uint64_t packet_count, byte_count;
-    ovs_be64 cookie;
     size_t act_len, len;
 
     if (rule_is_hidden(rule) || !rule_has_out_port(rule, out_port)) {
@@ -2848,9 +2880,8 @@ put_ofp_flow_stats(struct ofconn *ofconn, struct rule *rule,
     ofs->length = htons(len);
     ofs->table_id = 0;
     ofs->pad = 0;
-    ofputil_cls_rule_to_match(&rule->cr, ofconn_get_flow_format(ofconn),
-                              &ofs->match, rule->flow_cookie, &cookie);
-    put_32aligned_be64(&ofs->cookie, cookie);
+    ofputil_cls_rule_to_match(&rule->cr, &ofs->match);
+    put_32aligned_be64(&ofs->cookie, rule->flow_cookie);
     calc_flow_duration(rule->created, &ofs->duration_sec, &ofs->duration_nsec);
     ofs->priority = htons(rule->cr.priority);
     ofs->idle_timeout = htons(rule->idle_timeout);
@@ -2892,8 +2923,7 @@ handle_flow_stats_request(struct ofconn *ofconn, const struct ofp_header *oh)
         struct cls_rule target;
         struct rule *rule;
 
-        ofputil_cls_rule_from_match(&fsr->match, 0, NXFF_OPENFLOW10, 0,
-                                    &target);
+        ofputil_cls_rule_from_match(&fsr->match, 0, &target);
         cls_cursor_init(&cursor, &ofproto->cls, &target);
         CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
             put_ofp_flow_stats(ofconn, rule, fsr->out_port, &reply);
@@ -3065,8 +3095,7 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
     struct cls_rule target;
     struct ofpbuf *msg;
 
-    ofputil_cls_rule_from_match(&request->match, 0, NXFF_OPENFLOW10, 0,
-                                &target);
+    ofputil_cls_rule_from_match(&request->match, 0, &target);
 
     msg = start_ofp_stats_reply(oh, sizeof *reply);
     reply = append_ofp_stats_reply(sizeof *reply, ofconn, &msg);
@@ -3123,7 +3152,7 @@ put_queue_stats(struct queue_stats_cbdata *cbdata, uint32_t queue_id,
     struct ofp_queue_stats *reply;
 
     reply = append_ofp_stats_reply(sizeof *reply, cbdata->ofconn, &cbdata->msg);
-    reply->port_no = htons(cbdata->ofport->opp.port_no);
+    reply->port_no = cbdata->ofport->opp.port_no;
     memset(reply->pad, 0, sizeof reply->pad);
     reply->queue_id = htonl(queue_id);
     put_32aligned_be64(&reply->tx_bytes, htonll(stats->tx_bytes));
@@ -3513,7 +3542,7 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
         return error;
     }
 
-    error = ofputil_decode_flow_mod(&fm, oh, ofconn_get_flow_format(ofconn));
+    error = ofputil_decode_flow_mod(&fm, oh);
     if (error) {
         return error;
     }
@@ -3555,19 +3584,6 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
     }
 }
 
-static int
-handle_tun_id_from_cookie(struct ofconn *ofconn, const struct ofp_header *oh)
-{
-    const struct nxt_tun_id_cookie *msg
-        = (const struct nxt_tun_id_cookie *) oh;
-    enum nx_flow_format flow_format;
-
-    flow_format = msg->set ? NXFF_TUN_ID_FROM_COOKIE : NXFF_OPENFLOW10;
-    ofconn_set_flow_format(ofconn, flow_format);
-
-    return 0;
-}
-
 static int
 handle_role_request(struct ofconn *ofconn, const struct ofp_header *oh)
 {
@@ -3608,7 +3624,6 @@ handle_nxt_set_flow_format(struct ofconn *ofconn, const struct ofp_header *oh)
 
     format = ntohl(msg->format);
     if (format == NXFF_OPENFLOW10
-        || format == NXFF_TUN_ID_FROM_COOKIE
         || format == NXFF_NXM) {
         ofconn_set_flow_format(ofconn, format);
         return 0;
@@ -3673,9 +3688,6 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
         return 0;
 
         /* Nicira extension requests. */
-    case OFPUTIL_NXT_TUN_ID_FROM_COOKIE:
-        return handle_tun_id_from_cookie(ofconn, oh);
-
     case OFPUTIL_NXT_ROLE_REQUEST:
         return handle_role_request(ofconn, oh);
 
@@ -3781,7 +3793,7 @@ handle_miss_upcall(struct ofproto *p, struct dpif_upcall *upcall)
     /* Check with in-band control to see if this packet should be sent
      * to the local port regardless of the flow table. */
     if (connmgr_msg_in_hook(p->connmgr, &flow, upcall->packet)) {
-        ofproto_send_packet(p, ODPP_LOCAL, 0, upcall->packet);
+        ofproto_send_packet(p, ODPP_LOCAL, upcall->packet);
     }
 
     facet = facet_lookup_valid(p, &flow);
@@ -3791,7 +3803,7 @@ handle_miss_upcall(struct ofproto *p, struct dpif_upcall *upcall)
             /* Don't send a packet-in if OFPPC_NO_PACKET_IN asserted. */
             struct ofport *port = get_port(p, flow.in_port);
             if (port) {
-                if (port->opp.config & OFPPC_NO_PACKET_IN) {
+                if (port->opp.config & htonl(OFPPC_NO_PACKET_IN)) {
                     COVERAGE_INC(ofproto_no_packet_in);
                     /* XXX install 'drop' flow entry */
                     ofpbuf_delete(upcall->packet);
@@ -4192,13 +4204,6 @@ static void
 send_packet_in(struct ofproto *ofproto, struct dpif_upcall *upcall,
                const struct flow *flow, bool clone)
 {
-    struct ofputil_packet_in pin;
-
-    pin.packet = upcall->packet;
-    pin.in_port = odp_port_to_ofp_port(flow->in_port);
-    pin.reason = upcall->type == DPIF_UC_MISS ? OFPR_NO_MATCH : OFPR_ACTION;
-    pin.buffer_id = 0;          /* not yet known */
-    pin.send_len = upcall->userdata;
     connmgr_send_packet_in(ofproto->connmgr, upcall, flow,
                            clone ? NULL : upcall->packet);
 }
@@ -4434,7 +4439,7 @@ default_normal_ofhook_cb(const struct flow *flow, const struct ofpbuf *packet,
     /* Determine output port. */
     dst_mac = mac_learning_lookup(ofproto->ml, flow->dl_dst, 0, tags);
     if (!dst_mac) {
-        flood_packets(ofproto, flow->in_port, OFPPC_NO_FLOOD,
+        flood_packets(ofproto, flow->in_port, htonl(OFPPC_NO_FLOOD),
                       nf_output_iface, odp_actions);
     } else {
         int out_port = dst_mac->port.i;