X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=2d42c83b2762987aad5ed447f0c2ae778b569ba4;hb=f80022d9df98d29ee41176a4bc6cb91025da84b8;hp=4293824f0586a1e9c6351443a4022be8ba72eb19;hpb=9cae45dc699f64e85ad68db5f3b2f50758ad6e34;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 4293824f0..2d42c83b2 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -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->up, 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->up, 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,8 +1573,8 @@ port_modified(struct ofport *port_) cfm_set_netdev(port->cfm, port->up.netdev); } - if (port->tnl_port && tnl_port_reconfigure(&port->up, 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; } @@ -2471,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)); } } @@ -2510,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); @@ -3059,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 @@ -3475,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; @@ -3586,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); } @@ -3641,7 +3648,7 @@ ofproto_receive(const struct dpif_backer *backer, struct ofpbuf *packet, } port = (tnl_port_should_receive(flow) - ? ofport_dpif_cast(tnl_port_receive(flow)) + ? tnl_port_receive(flow) : odp_port_to_ofport(backer, flow->in_port.odp_port)); flow->in_port.ofp_port = port ? port->up.ofp_port : OFPP_NONE; if (!port) { @@ -4839,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); } @@ -5063,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, @@ -5413,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++; @@ -5911,7 +5920,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[], { const struct dpif_backer *backer; struct ofproto_dpif *ofproto; - struct ofpbuf odp_key; + struct ofpbuf odp_key, odp_mask; struct ofpbuf *packet; struct ds result; struct flow flow; @@ -5921,6 +5930,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[], backer = NULL; ds_init(&result); ofpbuf_init(&odp_key, 0); + ofpbuf_init(&odp_mask, 0); /* Handle "-generate" or a hex string as the last argument. */ if (!strcmp(argv[argc - 1], "-generate")) { @@ -5941,7 +5951,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[], * bridge is specified. If function odp_flow_key_from_string() * returns 0, the flow is a odp_flow. If function * parse_ofp_exact_flow() returns 0, the flow is a br_flow. */ - if (!odp_flow_from_string(argv[argc - 1], NULL, &odp_key, NULL)) { + if (!odp_flow_from_string(argv[argc - 1], NULL, &odp_key, &odp_mask)) { /* If the odp_flow is the second argument, * the datapath name is the first argument. */ if (argc == 3) { @@ -6021,6 +6031,7 @@ exit: ds_destroy(&result); ofpbuf_delete(packet); ofpbuf_uninit(&odp_key); + ofpbuf_uninit(&odp_mask); } void @@ -6385,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[], @@ -6498,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); } /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.)