X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=2d42c83b2762987aad5ed447f0c2ae778b569ba4;hb=f80022d9df98d29ee41176a4bc6cb91025da84b8;hp=c6a7abcc01add9416e400c0dd7f1ceb34d7336a1;hpb=7431e17196fdb1c3189d67e3aeed4adeab4cf479;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index c6a7abcc0..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; } @@ -1045,8 +1049,6 @@ construct(struct ofproto *ofproto_) ofproto_dpif_unixctl_init(); ofproto->has_mirrors = false; - ofproto->has_bundle_action = false; - hmap_init(&ofproto->vlandev_map); hmap_init(&ofproto->realdev_vid_map); @@ -1195,9 +1197,9 @@ destruct(struct ofproto *ofproto_) } netflow_destroy(ofproto->netflow); - dpif_sflow_destroy(ofproto->sflow); + dpif_sflow_unref(ofproto->sflow); hmap_destroy(&ofproto->bundles); - mac_learning_destroy(ofproto->ml); + mac_learning_unref(ofproto->ml); classifier_destroy(&ofproto->facets); @@ -1459,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; @@ -1488,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. */ @@ -1529,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); } } @@ -1539,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_); @@ -1570,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; } @@ -1617,7 +1620,7 @@ set_sflow(struct ofproto *ofproto_, dpif_sflow_set_options(ds, sflow_options); } else { if (ds) { - dpif_sflow_destroy(ds); + dpif_sflow_unref(ds); ofproto->backer->need_revalidate = REV_RECONFIGURE; ofproto->sflow = NULL; } @@ -1644,7 +1647,7 @@ set_ipfix( n_flow_exporters_options); } else { if (di) { - dpif_ipfix_destroy(di); + dpif_ipfix_unref(di); ofproto->ipfix = NULL; } } @@ -1674,7 +1677,7 @@ set_cfm(struct ofport *ofport_, const struct cfm_settings *s) error = EINVAL; } - cfm_destroy(ofport->cfm); + cfm_unref(ofport->cfm); ofport->cfm = NULL; return error; } @@ -2245,8 +2248,8 @@ bundle_destroy(struct ofbundle *bundle) hmap_remove(&ofproto->bundles, &bundle->hmap_node); free(bundle->name); free(bundle->trunks); - lacp_destroy(bundle->lacp); - bond_destroy(bundle->bond); + lacp_unref(bundle->lacp); + bond_unref(bundle->bond); free(bundle); } @@ -2309,7 +2312,7 @@ bundle_set(struct ofproto *ofproto_, void *aux, } lacp_configure(bundle->lacp, s->lacp); } else { - lacp_destroy(bundle->lacp); + lacp_unref(bundle->lacp); bundle->lacp = NULL; } @@ -2420,7 +2423,7 @@ bundle_set(struct ofproto *ofproto_, void *aux, bond_slave_register(bundle->bond, port, port->up.netdev); } } else { - bond_destroy(bundle->bond); + bond_unref(bundle->bond); bundle->bond = NULL; } @@ -2444,7 +2447,7 @@ bundle_remove(struct ofport *port_) if (list_is_empty(&bundle->ports)) { bundle_destroy(bundle); } else if (list_is_short(&bundle->ports)) { - bond_destroy(bundle->bond); + bond_unref(bundle->bond); bundle->bond = NULL; } } @@ -2473,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)); } } @@ -2512,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); @@ -2956,10 +2959,7 @@ port_run(struct ofport_dpif *ofport) if (ofport->may_enable != enable) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto); - - if (ofproto->has_bundle_action) { - ofproto->backer->need_revalidate = REV_PORT_TOGGLED; - } + ofproto->backer->need_revalidate = REV_PORT_TOGGLED; } ofport->may_enable = enable; @@ -3064,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 @@ -3361,6 +3361,15 @@ flow_miss_should_make_facet(struct flow_miss *miss, struct flow_wildcards *wc) struct dpif_backer *backer = miss->ofproto->backer; uint32_t hash; + switch (flow_miss_model) { + case OFPROTO_HANDLE_MISS_AUTO: + break; + case OFPROTO_HANDLE_MISS_WITH_FACETS: + return true; + case OFPROTO_HANDLE_MISS_WITHOUT_FACETS: + return false; + } + if (!backer->governor) { size_t n_subfacets; @@ -3471,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; @@ -3582,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); } @@ -3637,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) { @@ -4835,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); } @@ -5059,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, @@ -5409,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++; @@ -5498,6 +5511,22 @@ update_mirror_stats(struct ofproto_dpif *ofproto, mirror_mask_t mirrors, } } +tag_type +calculate_flow_tag(struct ofproto_dpif *ofproto, const struct flow *flow, + uint8_t table_id, struct rule_dpif *rule) +{ + if (table_id > 0 && table_id < N_TABLES) { + struct table_dpif *table = &ofproto->tables[table_id]; + if (table->other_table) { + return (rule && rule->tag + ? rule->tag + : rule_calculate_tag(flow, &table->other_table->mask, + table->basis)); + } + } + + return 0; +} /* Optimized flow revalidation. * @@ -5891,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; @@ -5901,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")) { @@ -5921,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) { @@ -6001,6 +6031,7 @@ exit: ds_destroy(&result); ofpbuf_delete(packet); ofpbuf_uninit(&odp_key); + ofpbuf_uninit(&odp_mask); } void @@ -6365,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[], @@ -6478,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.) @@ -6810,4 +6887,8 @@ const struct ofproto_class ofproto_dpif_class = { forward_bpdu_changed, set_mac_table_config, set_realdev, + NULL, /* meter_get_features */ + NULL, /* meter_set */ + NULL, /* meter_get */ + NULL, /* meter_del */ };