ofproto: Check overlap, emerg flow cache, and error code sync (OpenFlow 0.9)
[openvswitch] / ofproto / ofproto.c
index ea6a81773bd1824534ee030d1b51a10ad37c4b96..6bdbc73f71a96b2a8a7d670da0a20e0033f44b91 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include "netflow.h"
 #include "odp-util.h"
 #include "ofp-print.h"
+#include "ofproto-sflow.h"
 #include "ofpbuf.h"
 #include "openflow/nicira-ext.h"
 #include "openflow/openflow.h"
-#include "openflow/openflow-mgmt.h"
 #include "openvswitch/datapath-protocol.h"
 #include "packets.h"
 #include "pinsched.h"
 #include "shash.h"
 #include "status.h"
 #include "stp.h"
+#include "stream-ssl.h"
 #include "svec.h"
 #include "tag.h"
 #include "timeval.h"
 #include "unixctl.h"
 #include "vconn.h"
-#include "vconn-ssl.h"
 #include "xtoxll.h"
 
 #define THIS_MODULE VLM_ofproto
 #include "vlog.h"
 
-enum {
-    DP_GROUP_FLOOD = 0,
-    DP_GROUP_ALL = 1
-};
+#include "sflow_api.h"
 
 enum {
     TABLEID_HASH = 0,
@@ -175,7 +172,7 @@ struct ofconn {
 };
 
 static struct ofconn *ofconn_create(struct ofproto *, struct rconn *);
-static void ofconn_destroy(struct ofconn *, struct ofproto *);
+static void ofconn_destroy(struct ofconn *);
 static void ofconn_run(struct ofconn *, struct ofproto *);
 static void ofconn_wait(struct ofconn *);
 static void queue_tx(struct ofpbuf *msg, const struct ofconn *ofconn,
@@ -185,7 +182,6 @@ struct ofproto {
     /* Settings. */
     uint64_t datapath_id;       /* Datapath ID. */
     uint64_t fallback_dpid;     /* Datapath ID if no better choice found. */
-    uint64_t mgmt_id;           /* Management channel identifier. */
     char *manufacturer;         /* Manufacturer. */
     char *hardware;             /* Hardware. */
     char *software;             /* Software version. */
@@ -207,6 +203,7 @@ struct ofproto {
     struct fail_open *fail_open;
     struct pinsched *miss_sched, *action_sched;
     struct netflow *netflow;
+    struct ofproto_sflow *sflow;
 
     /* Flow table. */
     struct classifier cls;
@@ -251,13 +248,15 @@ static void handle_odp_msg(struct ofproto *, struct ofpbuf *);
 static void handle_openflow(struct ofconn *, struct ofproto *,
                             struct ofpbuf *);
 
-static void refresh_port_group(struct ofproto *, unsigned int group);
+static void refresh_port_groups(struct ofproto *);
+
 static void update_port(struct ofproto *, const char *devname);
 static int init_ports(struct ofproto *);
 static void reinit_ports(struct ofproto *);
 
 int
-ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux,
+ofproto_create(const char *datapath, const char *datapath_type,
+               const struct ofhooks *ofhooks, void *aux,
                struct ofproto **ofprotop)
 {
     struct odp_stats stats;
@@ -268,7 +267,7 @@ ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux,
     *ofprotop = NULL;
 
     /* Connect to datapath and start listening for messages. */
-    error = dpif_open(datapath, &dpif);
+    error = dpif_open(datapath, datapath_type, &dpif);
     if (error) {
         VLOG_ERR("failed to open datapath %s: %s", datapath, strerror(error));
         return error;
@@ -280,7 +279,7 @@ ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux,
         dpif_close(dpif);
         return error;
     }
-    error = dpif_recv_set_mask(dpif, ODPL_MISS | ODPL_ACTION);
+    error = dpif_recv_set_mask(dpif, ODPL_MISS | ODPL_ACTION | ODPL_SFLOW);
     if (error) {
         VLOG_ERR("failed to listen on datapath %s: %s",
                  datapath, strerror(error));
@@ -313,6 +312,7 @@ ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux,
     p->fail_open = NULL;
     p->miss_sched = p->action_sched = NULL;
     p->netflow = NULL;
+    p->sflow = NULL;
 
     /* Initialize flow table. */
     classifier_init(&p->cls);
@@ -345,13 +345,6 @@ ofproto_create(const char *datapath, const struct ofhooks *ofhooks, void *aux,
     p->ss_cat = switch_status_register(p->switch_status, "remote",
                                        rconn_status_cb, p->controller->rconn);
 
-    /* Almost done... */
-    error = init_ports(p);
-    if (error) {
-        ofproto_destroy(p);
-        return error;
-    }
-
     /* Pick final datapath ID. */
     p->datapath_id = pick_datapath_id(p);
     VLOG_INFO("using datapath ID %012"PRIx64, p->datapath_id);
@@ -371,12 +364,6 @@ ofproto_set_datapath_id(struct ofproto *p, uint64_t datapath_id)
     }
 }
 
-void
-ofproto_set_mgmt_id(struct ofproto *p, uint64_t mgmt_id)
-{
-    p->mgmt_id = mgmt_id;
-}
-
 void
 ofproto_set_probe_interval(struct ofproto *p, int probe_interval)
 {
@@ -545,6 +532,30 @@ ofproto_set_netflow(struct ofproto *ofproto,
     }
 }
 
+void
+ofproto_set_sflow(struct ofproto *ofproto,
+                  const struct ofproto_sflow_options *oso)
+{
+    struct ofproto_sflow *os = ofproto->sflow;
+    if (oso) {
+        if (!os) {
+            struct ofport *ofport;
+            unsigned int odp_port;
+
+            os = ofproto->sflow = ofproto_sflow_create(ofproto->dpif);
+            refresh_port_groups(ofproto);
+            PORT_ARRAY_FOR_EACH (ofport, &ofproto->ports, odp_port) {
+                ofproto_sflow_add_port(os, odp_port,
+                                       netdev_get_name(ofport->netdev));
+            }
+        }
+        ofproto_sflow_set_options(os, oso);
+    } else {
+        ofproto_sflow_destroy(os);
+        ofproto->sflow = NULL;
+    }
+}
+
 void
 ofproto_set_failure(struct ofproto *ofproto, bool fail_open)
 {
@@ -589,7 +600,7 @@ ofproto_set_rate_limit(struct ofproto *ofproto,
 }
 
 int
-ofproto_set_stp(struct ofproto *ofproto UNUSED, bool enable_stp)
+ofproto_set_stp(struct ofproto *ofproto OVS_UNUSED, bool enable_stp)
 {
     /* XXX */
     if (enable_stp) {
@@ -606,12 +617,6 @@ ofproto_get_datapath_id(const struct ofproto *ofproto)
     return ofproto->datapath_id;
 }
 
-uint64_t
-ofproto_get_mgmt_id(const struct ofproto *ofproto)
-{
-    return ofproto->mgmt_id;
-}
-
 int
 ofproto_get_probe_interval(const struct ofproto *ofproto)
 {
@@ -674,12 +679,15 @@ ofproto_destroy(struct ofproto *p)
         return;
     }
 
+    /* Destroy fail-open early, because it touches the classifier. */
+    ofproto_set_failure(p, false);
+
     ofproto_flush_flows(p);
     classifier_destroy(&p->cls);
 
     LIST_FOR_EACH_SAFE (ofconn, next_ofconn, struct ofconn, node,
                         &p->all_conns) {
-        ofconn_destroy(ofconn, p);
+        ofconn_destroy(ofconn);
     }
 
     dpif_close(p->dpif);
@@ -692,10 +700,10 @@ ofproto_destroy(struct ofproto *p)
     switch_status_destroy(p->switch_status);
     in_band_destroy(p->in_band);
     discovery_destroy(p->discovery);
-    fail_open_destroy(p->fail_open);
     pinsched_destroy(p->miss_sched);
     pinsched_destroy(p->action_sched);
     netflow_destroy(p->netflow);
+    ofproto_sflow_destroy(p->sflow);
 
     switch_status_unregister(p->ss_cat);
 
@@ -743,6 +751,10 @@ ofproto_run1(struct ofproto *p)
     int error;
     int i;
 
+    if (shash_is_empty(&p->port_by_name)) {
+        init_ports(p);
+    }
+
     for (i = 0; i < 50; i++) {
         struct ofpbuf *buf;
         int error;
@@ -845,6 +857,9 @@ ofproto_run1(struct ofproto *p)
     if (p->netflow) {
         netflow_run(p->netflow);
     }
+    if (p->sflow) {
+        ofproto_sflow_run(p->sflow);
+    }
 
     return 0;
 }
@@ -898,6 +913,9 @@ ofproto_wait(struct ofproto *p)
     }
     pinsched_wait(p->miss_sched);
     pinsched_wait(p->action_sched);
+    if (p->sflow) {
+        ofproto_sflow_wait(p->sflow);
+    }
     if (!tag_set_is_empty(&p->revalidate_set)) {
         poll_immediate_wake();
     }
@@ -1038,7 +1056,7 @@ reinit_ports(struct ofproto *p)
     svec_destroy(&devnames);
 }
 
-static void
+static size_t
 refresh_port_group(struct ofproto *p, unsigned int group)
 {
     uint16_t *ports;
@@ -1057,25 +1075,36 @@ refresh_port_group(struct ofproto *p, unsigned int group)
     }
     dpif_port_group_set(p->dpif, group, ports, n_ports);
     free(ports);
+
+    return n_ports;
 }
 
 static void
 refresh_port_groups(struct ofproto *p)
 {
-    refresh_port_group(p, DP_GROUP_FLOOD);
-    refresh_port_group(p, DP_GROUP_ALL);
+    size_t n_flood = refresh_port_group(p, DP_GROUP_FLOOD);
+    size_t n_all = refresh_port_group(p, DP_GROUP_ALL);
+    if (p->sflow) {
+        ofproto_sflow_set_group_sizes(p->sflow, n_flood, n_all);
+    }
 }
 
 static struct ofport *
 make_ofport(const struct odp_port *odp_port)
 {
+    struct netdev_options netdev_options;
     enum netdev_flags flags;
     struct ofport *ofport;
     struct netdev *netdev;
     bool carrier;
     int error;
 
-    error = netdev_open(odp_port->devname, NETDEV_ETH_TYPE_NONE, &netdev);
+    memset(&netdev_options, 0, sizeof netdev_options);
+    netdev_options.name = odp_port->devname;
+    netdev_options.ethertype = NETDEV_ETH_TYPE_NONE;
+    netdev_options.may_open = true;
+
+    error = netdev_open(&netdev_options, &netdev);
     if (error) {
         VLOG_WARN_RL(&rl, "ignoring port %s (%"PRIu16") because netdev %s "
                      "cannot be opened (%s)",
@@ -1162,19 +1191,29 @@ send_port_status(struct ofproto *p, const struct ofport *ofport,
 static void
 ofport_install(struct ofproto *p, struct ofport *ofport)
 {
+    uint16_t odp_port = ofp_port_to_odp_port(ofport->opp.port_no);
+    const char *netdev_name = (const char *) ofport->opp.name;
+
     netdev_monitor_add(p->netdev_monitor, ofport->netdev);
-    port_array_set(&p->ports, ofp_port_to_odp_port(ofport->opp.port_no),
-                   ofport);
-    shash_add(&p->port_by_name, (char *) ofport->opp.name, ofport);
+    port_array_set(&p->ports, odp_port, ofport);
+    shash_add(&p->port_by_name, netdev_name, ofport);
+    if (p->sflow) {
+        ofproto_sflow_add_port(p->sflow, odp_port, netdev_name);
+    }
 }
 
 static void
 ofport_remove(struct ofproto *p, struct ofport *ofport)
 {
+    uint16_t odp_port = ofp_port_to_odp_port(ofport->opp.port_no);
+
     netdev_monitor_remove(p->netdev_monitor, ofport->netdev);
-    port_array_set(&p->ports, ofp_port_to_odp_port(ofport->opp.port_no), NULL);
+    port_array_set(&p->ports, odp_port, NULL);
     shash_delete(&p->port_by_name,
                  shash_find(&p->port_by_name, (char *) ofport->opp.name));
+    if (p->sflow) {
+        ofproto_sflow_del_port(p->sflow, odp_port);
+    }
 }
 
 static void
@@ -1300,7 +1339,7 @@ ofconn_create(struct ofproto *p, struct rconn *rconn)
 }
 
 static void
-ofconn_destroy(struct ofconn *ofconn, struct ofproto *p)
+ofconn_destroy(struct ofconn *ofconn)
 {
     list_remove(&ofconn->node);
     rconn_destroy(ofconn->rconn);
@@ -1334,7 +1373,7 @@ ofconn_run(struct ofconn *ofconn, struct ofproto *p)
     }
 
     if (ofconn != p->controller && !rconn_is_alive(ofconn->rconn)) {
-        ofconn_destroy(ofconn, p);
+        ofconn_destroy(ofconn);
     }
 }
 
@@ -1814,6 +1853,7 @@ handle_features_request(struct ofproto *p, struct ofconn *ofconn,
                          (1u << OFPAT_SET_DL_DST) |
                          (1u << OFPAT_SET_NW_SRC) |
                          (1u << OFPAT_SET_NW_DST) |
+                         (1u << OFPAT_SET_NW_TOS) |
                          (1u << OFPAT_SET_TP_SRC) |
                          (1u << OFPAT_SET_TP_DST));
 
@@ -2131,6 +2171,10 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
         case OFPAT_SET_NW_DST:
             oa = odp_actions_add(ctx->out, ODPAT_SET_NW_DST);
             oa->nw_addr.nw_addr = ia->nw_addr.nw_addr;
+
+        case OFPAT_SET_NW_TOS:
+            oa = odp_actions_add(ctx->out, ODPAT_SET_NW_TOS);
+            oa->nw_tos.nw_tos = ia->nw_tos.nw_tos;
             break;
 
         case OFPAT_SET_TP_SRC:
@@ -2259,7 +2303,7 @@ update_port_config(struct ofproto *p, struct ofport *port,
 #undef REVALIDATE_BITS
     if (mask & OFPPC_NO_FLOOD) {
         port->opp.config ^= OFPPC_NO_FLOOD;
-        refresh_port_group(p, DP_GROUP_FLOOD);
+        refresh_port_groups(p);
     }
     if (mask & OFPPC_NO_PACKET_IN) {
         port->opp.config ^= OFPPC_NO_PACKET_IN;
@@ -2515,7 +2559,7 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_)
     ofs->priority = htons(rule->cr.priority);
     ofs->idle_timeout = htons(rule->idle_timeout);
     ofs->hard_timeout = htons(rule->hard_timeout);
-    memset(ofs->pad2, 0, sizeof ofs->pad2);
+    ofs->pad2 = 0;
     ofs->packet_count = htonll(packet_count);
     ofs->byte_count = htonll(byte_count);
     memcpy(ofs->actions, rule->actions, act_len);
@@ -2540,7 +2584,7 @@ handle_flow_stats_request(struct ofproto *p, struct ofconn *ofconn,
     struct cls_rule target;
 
     if (arg_size != sizeof *fsr) {
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
     fsr = (struct ofp_flow_stats_request *) osr->body;
 
@@ -2648,7 +2692,7 @@ handle_aggregate_stats_request(struct ofproto *p, struct ofconn *ofconn,
     struct ofpbuf *msg;
 
     if (arg_size != sizeof *asr) {
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
     asr = (struct ofp_aggregate_stats_request *) osr->body;
 
@@ -2753,16 +2797,29 @@ add_flow(struct ofproto *p, struct ofconn *ofconn,
     uint16_t in_port;
     int error;
 
+    if (ofm->flags & htons(OFPFF_CHECK_OVERLAP)) {
+        flow_t flow;
+        uint32_t wildcards;
+
+        flow_from_match(&flow, &wildcards, &ofm->match);
+        if (classifier_rule_overlaps(&p->cls, &flow, wildcards,
+                                     ntohs(ofm->priority))) {
+            return ofp_mkerr(OFPET_FLOW_MOD_FAILED, OFPFMFC_OVERLAP);
+        }
+    }
+
     rule = rule_create(p, NULL, (const union ofp_action *) ofm->actions,
                        n_actions, ntohs(ofm->idle_timeout),
                        ntohs(ofm->hard_timeout));
     cls_rule_from_match(&rule->cr, &ofm->match, ntohs(ofm->priority));
 
-    packet = NULL;
     error = 0;
     if (ofm->buffer_id != htonl(UINT32_MAX)) {
         error = pktbuf_retrieve(ofconn->pktbuf, ntohl(ofm->buffer_id),
                                 &packet, &in_port);
+    } else {
+        packet = NULL;
+        in_port = UINT16_MAX;
     }
 
     rule_insert(p, rule, packet, in_port);
@@ -2886,6 +2943,14 @@ handle_flow_mod(struct ofproto *p, struct ofconn *ofconn,
         return error;
     }
 
+    /* We do not support the emergency flow cache.  It will hopefully
+     * get dropped from OpenFlow in the near future. */
+    if (ofm->flags & htons(OFPFF_EMERG)) {
+        /* There isn't a good fit for an error code, so just state that the
+         * flow table is full. */
+        return ofp_mkerr(OFPET_FLOW_MOD_FAILED, OFPFMFC_ALL_TABLES_FULL);
+    }
+
     normalize_match(&ofm->match);
     if (!ofm->match.wildcards) {
         ofm->priority = htons(UINT16_MAX);
@@ -2918,58 +2983,6 @@ handle_flow_mod(struct ofproto *p, struct ofconn *ofconn,
     }
 }
 
-static void
-send_capability_reply(struct ofproto *p, struct ofconn *ofconn, uint32_t xid)
-{
-    struct ofmp_capability_reply *ocr;
-    struct ofpbuf *b;
-    char capabilities[] = "com.nicira.mgmt.manager=false\n";
-
-    ocr = make_openflow_xid(sizeof(*ocr), OFPT_VENDOR, xid, &b);
-    ocr->header.header.vendor = htonl(NX_VENDOR_ID);
-    ocr->header.header.subtype = htonl(NXT_MGMT);
-    ocr->header.type = htons(OFMPT_CAPABILITY_REPLY);
-
-    ocr->format = htonl(OFMPCOF_SIMPLE);
-    ocr->mgmt_id = htonll(p->mgmt_id);
-
-    ofpbuf_put(b, capabilities, strlen(capabilities));
-
-    queue_tx(b, ofconn, ofconn->reply_counter);
-}
-
-static int
-handle_ofmp(struct ofproto *p, struct ofconn *ofconn, 
-            struct ofmp_header *ofmph)
-{
-    size_t msg_len = ntohs(ofmph->header.header.length);
-    if (msg_len < sizeof(*ofmph)) {
-        VLOG_WARN_RL(&rl, "dropping short managment message: %zu\n", msg_len);
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
-    }
-
-    if (ofmph->type == htons(OFMPT_CAPABILITY_REQUEST)) {
-        struct ofmp_capability_request *ofmpcr;
-
-        if (msg_len < sizeof(struct ofmp_capability_request)) {
-            VLOG_WARN_RL(&rl, "dropping short capability request: %zu\n",
-                    msg_len);
-            return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
-        }
-
-        ofmpcr = (struct ofmp_capability_request *)ofmph;
-        if (ofmpcr->format != htonl(OFMPCAF_SIMPLE)) {
-            /* xxx Find a better type than bad subtype */
-            return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE);
-        }
-
-        send_capability_reply(p, ofconn, ofmph->header.header.xid);
-        return 0;
-    } else {
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE);
-    }
-}
-
 static int
 handle_vendor(struct ofproto *p, struct ofconn *ofconn, void *msg)
 {
@@ -2977,13 +2990,13 @@ handle_vendor(struct ofproto *p, struct ofconn *ofconn, void *msg)
     struct nicira_header *nh;
 
     if (ntohs(ovh->header.length) < sizeof(struct ofp_vendor_header)) {
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
     if (ovh->vendor != htonl(NX_VENDOR_ID)) {
         return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_VENDOR);
     }
     if (ntohs(ovh->header.length) < sizeof(struct nicira_header)) {
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LENGTH);
+        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
     }
 
     nh = msg;
@@ -2991,15 +3004,6 @@ handle_vendor(struct ofproto *p, struct ofconn *ofconn, void *msg)
     case NXT_STATUS_REQUEST:
         return switch_status_handle_request(p->switch_status, ofconn->rconn,
                                             msg);
-
-    case NXT_ACT_SET_CONFIG:
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE); /* XXX */
-
-    case NXT_ACT_GET_CONFIG:
-        return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE); /* XXX */
-
-    case NXT_MGMT:
-        return handle_ofmp(p, ofconn, msg);
     }
 
     return ofp_mkerr(OFPET_BAD_REQUEST, OFPBRC_BAD_SUBTYPE);
@@ -3070,7 +3074,7 @@ handle_openflow(struct ofconn *ofconn, struct ofproto *p,
 }
 \f
 static void
-handle_odp_msg(struct ofproto *p, struct ofpbuf *packet)
+handle_odp_miss_msg(struct ofproto *p, struct ofpbuf *packet)
 {
     struct odp_msg *msg = packet->data;
     uint16_t in_port = odp_port_to_ofp_port(msg->port);
@@ -3078,14 +3082,6 @@ handle_odp_msg(struct ofproto *p, struct ofpbuf *packet)
     struct ofpbuf payload;
     flow_t flow;
 
-    /* Handle controller actions. */
-    if (msg->type == _ODPL_ACTION_NR) {
-        COVERAGE_INC(ofproto_ctlr_action);
-        pinsched_send(p->action_sched, in_port, packet,
-                      send_packet_in_action, p);
-        return;
-    }
-
     payload.data = msg + 1;
     payload.size = msg->length - sizeof *msg;
     flow_extract(&payload, msg->port, &flow);
@@ -3155,6 +3151,36 @@ handle_odp_msg(struct ofproto *p, struct ofpbuf *packet)
         ofpbuf_delete(packet);
     }
 }
+
+static void
+handle_odp_msg(struct ofproto *p, struct ofpbuf *packet)
+{
+    struct odp_msg *msg = packet->data;
+
+    switch (msg->type) {
+    case _ODPL_ACTION_NR:
+        COVERAGE_INC(ofproto_ctlr_action);
+        pinsched_send(p->action_sched, odp_port_to_ofp_port(msg->port), packet,
+                      send_packet_in_action, p);
+        break;
+
+    case _ODPL_SFLOW_NR:
+        if (p->sflow) {
+            ofproto_sflow_received(p->sflow, msg);
+        }
+        ofpbuf_delete(packet);
+        break;
+
+    case _ODPL_MISS_NR:
+        handle_odp_miss_msg(p, packet);
+        break;
+
+    default:
+        VLOG_WARN_RL(&rl, "received ODP message of unexpected type %"PRIu32,
+                     msg->type);
+        break;
+    }
+}
 \f
 static void
 revalidate_cb(struct cls_rule *sub_, void *cbdata_)
@@ -3460,10 +3486,7 @@ static uint64_t
 pick_fallback_dpid(void)
 {
     uint8_t ea[ETH_ADDR_LEN];
-    eth_addr_random(ea);
-    ea[0] = 0x00;               /* Set Nicira OUI. */
-    ea[1] = 0x23;
-    ea[2] = 0x20;
+    eth_addr_nicira_random(ea);
     return eth_addr_to_uint64(ea);
 }
 \f