* 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);
char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
const char *dp_port;
- if (!iter->tnl_port) {
+ if (!iter->is_tunnel) {
continue;
}
}
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;
}
}
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;
}
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;
}
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;
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. */
* 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);
}
}
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_);
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;
}
} 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));
}
}
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);
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
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;
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);
}
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);
}
}
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,
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++;
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[],
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.)