X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif.c;h=d32f6d16374f13a298d30605b9504fa07dac30d5;hb=72e8bf28bb38e8816435c64859fb350215b6a9e6;hp=098a43ee48453f1d123cb1c9c9ca49e271adf2ad;hpb=0958f12880427e4f3ea3fcc758a3ddf681ae6f5d;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 098a43ee4..d32f6d163 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -76,6 +76,7 @@ BUILD_ASSERT_DECL(N_TABLES >= 2 && N_TABLES <= 255); struct ofport_dpif; struct ofproto_dpif; +struct flow_miss; struct rule_dpif { struct rule up; @@ -366,13 +367,18 @@ struct subfacet { * splinters can cause it to differ. This value should be removed when * the VLAN splinters feature is no longer needed. */ ovs_be16 initial_tci; /* Initial VLAN TCI value. */ + + /* Datapath port the packet arrived on. This is needed to remove + * flows for ports that are no longer part of the bridge. Since the + * flow definition only has the OpenFlow port number and the port is + * no longer part of the bridge, we can't determine the datapath port + * number needed to delete the flow from the datapath. */ + uint32_t odp_in_port; }; #define SUBFACET_DESTROY_MAX_BATCH 50 -static struct subfacet *subfacet_create(struct facet *, enum odp_key_fitness, - const struct nlattr *key, - size_t key_len, ovs_be16 initial_tci, +static struct subfacet *subfacet_create(struct facet *, struct flow_miss *miss, long long int now); static struct subfacet *subfacet_find(struct ofproto_dpif *, const struct nlattr *key, size_t key_len, @@ -1538,19 +1544,17 @@ port_destruct(struct ofport *port_) { struct ofport_dpif *port = ofport_dpif_cast(port_); struct ofproto_dpif *ofproto = ofproto_dpif_cast(port->up.ofproto); - struct dpif_port dpif_port; + const char *devname = netdev_get_name(port->up.netdev); - if (!dpif_port_query_by_number(ofproto->backer->dpif, - port->odp_port, &dpif_port)) { + if (dpif_port_exists(ofproto->backer->dpif, devname)) { /* The underlying device is still there, so delete it. This * happens when the ofproto is being destroyed, since the caller * assumes that removal of attached ports will happen as part of * destruction. */ dpif_port_del(ofproto->backer->dpif, port->odp_port); - dpif_port_destroy(&dpif_port); } - sset_find_and_delete(&ofproto->ports, netdev_get_name(port->up.netdev)); + sset_find_and_delete(&ofproto->ports, devname); hmap_remove(&ofproto->backer->odp_to_ofport_map, &port->odp_port_node); ofproto->need_revalidate = REV_RECONFIGURE; bundle_remove(port_); @@ -3064,6 +3068,7 @@ struct flow_miss { ovs_be16 initial_tci; struct list packets; enum dpif_upcall_type upcall_type; + uint32_t odp_in_port; }; struct flow_miss_op { @@ -3283,9 +3288,7 @@ handle_flow_miss_with_facet(struct flow_miss *miss, struct facet *facet, struct subfacet *subfacet; struct ofpbuf *packet; - subfacet = subfacet_create(facet, - miss->key_fitness, miss->key, miss->key_len, - miss->initial_tci, now); + subfacet = subfacet_create(facet, miss, now); LIST_FOR_EACH (packet, list_node, &miss->packets) { struct flow_miss_op *op = &ops[*n_ops]; @@ -3462,6 +3465,7 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls, enum odp_key_fitness fitness; struct ofproto_dpif *ofproto; struct ofport_dpif *port; + uint32_t odp_in_port; struct flow flow; uint32_t hash; @@ -3477,6 +3481,7 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls, continue; } ofproto = ofproto_dpif_cast(port->up.ofproto); + odp_in_port = flow.in_port; flow.in_port = port->up.ofp_port; /* Obtain metadata and check userspace/kernel agreement on flow match, @@ -3486,7 +3491,7 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls, if (miss->key_fitness == ODP_FIT_ERROR) { continue; } - flow_extract(upcall->packet, flow.skb_priority, + flow_extract(upcall->packet, flow.skb_priority, flow.skb_mark, &flow.tunnel, flow.in_port, &miss->flow); /* Add other packets to a to-do list. */ @@ -3498,6 +3503,7 @@ handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls, miss->key = upcall->key; miss->key_len = upcall->key_len; miss->upcall_type = upcall->type; + miss->odp_in_port = odp_in_port; list_init(&miss->packets); n_misses++; @@ -3823,11 +3829,8 @@ update_stats(struct dpif_backer *backer) if (!port) { /* This flow is for a port for which we couldn't associate an * ofproto. This can happen if a port is removed while - * traffic is being received. Print a rate-limited message - * in case it happens frequently. */ - VLOG_INFO_RL(&rl, - "stats update for flow with unassociated port %"PRIu32, - flow.in_port); + * traffic is being received. Ignore this flow, since it + * will get timed out. */ continue; } @@ -4652,21 +4655,26 @@ subfacet_find(struct ofproto_dpif *ofproto, } /* Searches 'facet' (within 'ofproto') for a subfacet with the specified - * 'key_fitness', 'key', and 'key_len'. Returns the existing subfacet if - * there is one, otherwise creates and returns a new subfacet. + * 'key_fitness', 'key', and 'key_len' members in 'miss'. Returns the + * existing subfacet if there is one, otherwise creates and returns a + * new subfacet. * * If the returned subfacet is new, then subfacet->actions will be NULL, in * which case the caller must populate the actions with * subfacet_make_actions(). */ static struct subfacet * -subfacet_create(struct facet *facet, enum odp_key_fitness key_fitness, - const struct nlattr *key, size_t key_len, - ovs_be16 initial_tci, long long int now) +subfacet_create(struct facet *facet, struct flow_miss *miss, + long long int now) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(facet->rule->up.ofproto); - uint32_t key_hash = odp_flow_key_hash(key, key_len); + enum odp_key_fitness key_fitness = miss->key_fitness; + const struct nlattr *key = miss->key; + size_t key_len = miss->key_len; + uint32_t key_hash; struct subfacet *subfacet; + key_hash = odp_flow_key_hash(key, key_len); + if (list_is_empty(&facet->subfacets)) { subfacet = &facet->one_subfacet; } else { @@ -4705,7 +4713,8 @@ subfacet_create(struct facet *facet, enum odp_key_fitness key_fitness, ? SLOW_MATCH : 0); subfacet->path = SF_NOT_INSTALLED; - subfacet->initial_tci = initial_tci; + subfacet->initial_tci = miss->initial_tci; + subfacet->odp_in_port = miss->odp_in_port; return subfacet; } @@ -4780,13 +4789,10 @@ subfacet_get_key(struct subfacet *subfacet, struct odputil_keybuf *keybuf, { if (!subfacet->key) { - struct ofproto_dpif *ofproto; struct flow *flow = &subfacet->facet->flow; ofpbuf_use_stack(key, keybuf, sizeof *keybuf); - ofproto = ofproto_dpif_cast(subfacet->facet->rule->up.ofproto); - odp_flow_key_from_flow(key, flow, - ofp_port_to_odp_port(ofproto, flow->in_port)); + odp_flow_key_from_flow(key, flow, subfacet->odp_in_port); } else { ofpbuf_use_const(key, subfacet->key, subfacet->key_len); } @@ -5176,7 +5182,7 @@ send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet) struct flow flow; int error; - flow_extract(packet, 0, NULL, OFPP_LOCAL, &flow); + flow_extract(packet, 0, 0, NULL, OFPP_LOCAL, &flow); odp_port = vsp_realdev_to_vlandev(ofproto, ofport->odp_port, flow.vlan_tci); if (odp_port != ofport->odp_port) { @@ -7208,15 +7214,17 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[], packet = ofpbuf_new(0); flow_compose(packet, &flow); } - } else if (argc == 6) { - /* ofproto/trace dpname priority tun_id in_port packet */ + } else if (argc == 7) { + /* ofproto/trace dpname priority tun_id in_port mark packet */ const char *priority_s = argv[2]; const char *tun_id_s = argv[3]; const char *in_port_s = argv[4]; - const char *packet_s = argv[5]; + const char *mark_s = argv[5]; + const char *packet_s = argv[6]; uint32_t in_port = atoi(in_port_s); ovs_be64 tun_id = htonll(strtoull(tun_id_s, NULL, 0)); uint32_t priority = atoi(priority_s); + uint32_t mark = atoi(mark_s); const char *msg; msg = eth_from_hex(packet_s, &packet); @@ -7230,7 +7238,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc, const char *argv[], ds_put_cstr(&result, s); free(s); - flow_extract(packet, priority, NULL, in_port, &flow); + flow_extract(packet, priority, mark, NULL, in_port, &flow); flow.tunnel.tun_id = tun_id; initial_tci = flow.vlan_tci; } else { @@ -7625,8 +7633,8 @@ ofproto_dpif_unixctl_init(void) unixctl_command_register( "ofproto/trace", - "bridge {tun_id in_port packet | odp_flow [-generate]}", - 2, 5, ofproto_unixctl_trace, NULL); + "bridge {priority tun_id in_port mark packet | odp_flow [-generate]}", + 2, 6, ofproto_unixctl_trace, NULL); unixctl_command_register("fdb/flush", "[bridge]", 0, 1, ofproto_unixctl_fdb_flush, NULL); unixctl_command_register("fdb/show", "bridge", 1, 1,