Merge branch 'mainstream'
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index 9537172..2d42c83 100644 (file)
@@ -404,6 +404,10 @@ static void update_moving_averages(struct dpif_backer *backer);
  * for debugging the asynchronous flow_mod implementation.) */
 static bool clogged;
 
+/* By default, flows in the datapath are wildcarded (megaflows).  They
+ * may be disabled with the "ovs-appctl dpif/disable-megaflows" command. */
+static bool enable_megaflows = true;
+
 /* All existing ofproto_dpif instances, indexed by ->up.name. */
 static struct hmap all_ofproto_dpifs = HMAP_INITIALIZER(&all_ofproto_dpifs);
 
@@ -571,7 +575,7 @@ type_run(const char *type)
                 char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
                 const char *dp_port;
 
-                if (!iter->tnl_port) {
+                if (!iter->is_tunnel) {
                     continue;
                 }
 
@@ -597,8 +601,8 @@ type_run(const char *type)
                 }
 
                 iter->odp_port = node ? u32_to_odp(node->data) : ODPP_NONE;
-                if (tnl_port_reconfigure(iter, iter->up.netdev, iter->odp_port,
-                                         &iter->tnl_port)) {
+                if (tnl_port_reconfigure(iter, iter->up.netdev,
+                                         iter->odp_port)) {
                     backer->need_revalidate = REV_RECONFIGURE;
                 }
             }
@@ -932,7 +936,7 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp)
     free(backer_name);
     if (error) {
         VLOG_ERR("failed to open datapath of type %s: %s", type,
-                 strerror(error));
+                 ovs_strerror(error));
         free(backer);
         return error;
     }
@@ -979,7 +983,7 @@ open_dpif_backer(const char *type, struct dpif_backer **backerp)
     error = dpif_recv_set(backer->dpif, backer->recv_set_enable);
     if (error) {
         VLOG_ERR("failed to listen on datapath of type %s: %s",
-                 type, strerror(error));
+                 type, ovs_strerror(error));
         close_dpif_backer(backer);
         return error;
     }
@@ -1457,7 +1461,7 @@ port_construct(struct ofport *port_)
     port->may_enable = true;
     port->stp_port = NULL;
     port->stp_state = STP_DISABLED;
-    port->tnl_port = NULL;
+    port->is_tunnel = false;
     port->peer = NULL;
     hmap_init(&port->priorities);
     port->realdev_ofp_port = 0;
@@ -1486,7 +1490,8 @@ port_construct(struct ofport *port_)
     port->odp_port = dpif_port.port_no;
 
     if (netdev_get_tunnel_config(netdev)) {
-        port->tnl_port = tnl_port_add(port, port->up.netdev, port->odp_port);
+        tnl_port_add(port, port->up.netdev, port->odp_port);
+        port->is_tunnel = true;
     } else {
         /* Sanity-check that a mapping doesn't already exist.  This
          * shouldn't happen for non-tunnel ports. */
@@ -1527,7 +1532,7 @@ port_destruct(struct ofport *port_)
          * happens when the ofproto is being destroyed, since the caller
          * assumes that removal of attached ports will happen as part of
          * destruction. */
-        if (!port->tnl_port) {
+        if (!port->is_tunnel) {
             dpif_port_del(ofproto->backer->dpif, port->odp_port);
         }
     }
@@ -1537,11 +1542,11 @@ port_destruct(struct ofport *port_)
         port->peer = NULL;
     }
 
-    if (port->odp_port != ODPP_NONE && !port->tnl_port) {
+    if (port->odp_port != ODPP_NONE && !port->is_tunnel) {
         hmap_remove(&ofproto->backer->odp_to_ofport_map, &port->odp_port_node);
     }
 
-    tnl_port_del(port->tnl_port);
+    tnl_port_del(port);
     sset_find_and_delete(&ofproto->ports, devname);
     sset_find_and_delete(&ofproto->ghost_ports, devname);
     bundle_remove(port_);
@@ -1568,9 +1573,8 @@ port_modified(struct ofport *port_)
         cfm_set_netdev(port->cfm, port->up.netdev);
     }
 
-    if (port->tnl_port && tnl_port_reconfigure(port, port->up.netdev,
-                                               port->odp_port,
-                                               &port->tnl_port)) {
+    if (port->is_tunnel && tnl_port_reconfigure(port, port->up.netdev,
+                                                port->odp_port)) {
         ofproto_dpif_cast(port->up.ofproto)->backer->need_revalidate =
             REV_RECONFIGURE;
     }
@@ -2472,7 +2476,7 @@ send_pdu_cb(void *port_, const void *pdu, size_t pdu_size)
     } else {
         VLOG_ERR_RL(&rl, "port %s: cannot obtain Ethernet address of iface "
                     "%s (%s)", port->bundle->name,
-                    netdev_get_name(port->up.netdev), strerror(error));
+                    netdev_get_name(port->up.netdev), ovs_strerror(error));
     }
 }
 
@@ -2511,7 +2515,7 @@ bundle_send_learning_packets(struct ofbundle *bundle)
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
         VLOG_WARN_RL(&rl, "bond %s: %d errors sending %d gratuitous learning "
                      "packets, last error was: %s",
-                     bundle->name, n_errors, n_packets, strerror(error));
+                     bundle->name, n_errors, n_packets, ovs_strerror(error));
     } else {
         VLOG_DBG("bond %s: sent %d gratuitous learning packets",
                  bundle->name, n_packets);
@@ -3060,7 +3064,7 @@ port_del(struct ofproto *ofproto_, ofp_port_t ofp_port)
     sset_find_and_delete(&ofproto->ghost_ports,
                          netdev_get_name(ofport->up.netdev));
     ofproto->backer->need_revalidate = REV_RECONFIGURE;
-    if (!ofport->tnl_port) {
+    if (!ofport->is_tunnel) {
         error = dpif_port_del(ofproto->backer->dpif, ofport->odp_port);
         if (!error) {
             /* The caller is going to close ofport->up.netdev.  If this is a
@@ -3476,8 +3480,10 @@ handle_flow_miss_with_facet(struct flow_miss *miss, struct facet *facet,
         subfacet->path = want_path;
 
         ofpbuf_use_stack(&op->mask, &op->maskbuf, sizeof op->maskbuf);
-        odp_flow_key_from_mask(&op->mask, &facet->xout.wc.masks,
-                               &miss->flow, UINT32_MAX);
+        if (enable_megaflows) {
+            odp_flow_key_from_mask(&op->mask, &facet->xout.wc.masks,
+                                   &miss->flow, UINT32_MAX);
+        }
 
         op->xout_garbage = false;
         op->dpif_op.type = DPIF_OP_FLOW_PUT;
@@ -3587,8 +3593,8 @@ drop_key_clear(struct dpif_backer *backer)
         if (error && !VLOG_DROP_WARN(&rl)) {
             struct ds ds = DS_EMPTY_INITIALIZER;
             odp_flow_key_format(drop_key->key, drop_key->key_len, &ds);
-            VLOG_WARN("Failed to delete drop key (%s) (%s)", strerror(error),
-                      ds_cstr(&ds));
+            VLOG_WARN("Failed to delete drop key (%s) (%s)",
+                      ovs_strerror(error), ds_cstr(&ds));
             ds_destroy(&ds);
         }
 
@@ -4840,7 +4846,7 @@ facet_push_stats(struct facet *facet, bool may_learn)
         facet->prev_used = facet->used;
 
         in_port = get_ofp_port(ofproto, facet->flow.in_port.ofp_port);
-        if (in_port && in_port->tnl_port) {
+        if (in_port && in_port->is_tunnel) {
             netdev_vport_inc_rx(in_port->up.netdev, &stats);
         }
 
@@ -5064,8 +5070,10 @@ subfacet_install(struct subfacet *subfacet, const struct ofpbuf *odp_actions,
     }
 
     ofpbuf_use_stack(&mask, &maskbuf, sizeof maskbuf);
-    odp_flow_key_from_mask(&mask, &facet->xout.wc.masks,
-                           &facet->flow, UINT32_MAX);
+    if (enable_megaflows) {
+        odp_flow_key_from_mask(&mask, &facet->xout.wc.masks,
+                               &facet->flow, UINT32_MAX);
+    }
 
     ret = dpif_flow_put(subfacet->backer->dpif, flags, subfacet->key,
                         subfacet->key_len,  mask.data, mask.size,
@@ -5414,7 +5422,7 @@ send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
     if (error) {
         VLOG_WARN_RL(&rl, "%s: failed to send packet on port %s (%s)",
                      ofproto->up.name, netdev_get_name(ofport->up.netdev),
-                     strerror(error));
+                     ovs_strerror(error));
     }
 
     ofproto->stats.tx_packets++;
@@ -6388,6 +6396,48 @@ ofproto_unixctl_dpif_dump_megaflows(struct unixctl_conn *conn,
     ds_destroy(&ds);
 }
 
+/* Disable using the megaflows.
+ *
+ * This command is only needed for advanced debugging, so it's not
+ * documented in the man page. */
+static void
+ofproto_unixctl_dpif_disable_megaflows(struct unixctl_conn *conn,
+                                       int argc OVS_UNUSED,
+                                       const char *argv[] OVS_UNUSED,
+                                       void *aux OVS_UNUSED)
+{
+    struct ofproto_dpif *ofproto;
+
+    enable_megaflows = false;
+
+    HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
+        flush(&ofproto->up);
+    }
+
+    unixctl_command_reply(conn, "megaflows disabled");
+}
+
+/* Re-enable using megaflows.
+ *
+ * This command is only needed for advanced debugging, so it's not
+ * documented in the man page. */
+static void
+ofproto_unixctl_dpif_enable_megaflows(struct unixctl_conn *conn,
+                                      int argc OVS_UNUSED,
+                                      const char *argv[] OVS_UNUSED,
+                                      void *aux OVS_UNUSED)
+{
+    struct ofproto_dpif *ofproto;
+
+    enable_megaflows = true;
+
+    HMAP_FOR_EACH (ofproto, all_ofproto_dpifs_node, &all_ofproto_dpifs) {
+        flush(&ofproto->up);
+    }
+
+    unixctl_command_reply(conn, "megaflows enabled");
+}
+
 static void
 ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn,
                                 int argc OVS_UNUSED, const char *argv[],
@@ -6501,6 +6551,10 @@ ofproto_dpif_unixctl_init(void)
                              ofproto_unixctl_dpif_del_flows, NULL);
     unixctl_command_register("dpif/dump-megaflows", "bridge", 1, 1,
                              ofproto_unixctl_dpif_dump_megaflows, NULL);
+    unixctl_command_register("dpif/disable-megaflows", "", 0, 0,
+                             ofproto_unixctl_dpif_disable_megaflows, NULL);
+    unixctl_command_register("dpif/enable-megaflows", "", 0, 0,
+                             ofproto_unixctl_dpif_enable_megaflows, NULL);
 }
 \f
 /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)