struct ofport_dpif;
struct ofproto_dpif;
+struct flow_miss;
struct rule_dpif {
struct rule up;
* 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,
return error;
}
\f
+static const char *
+port_open_type(const char *datapath_type, const char *port_type)
+{
+ return dpif_port_open_type(datapath_type, port_type);
+}
+
/* Type functions. */
static int
{
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_);
ovs_be16 initial_tci;
struct list packets;
enum dpif_upcall_type upcall_type;
+ uint32_t odp_in_port;
};
struct flow_miss_op {
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];
enum odp_key_fitness fitness;
struct ofproto_dpif *ofproto;
struct ofport_dpif *port;
+ uint32_t odp_in_port;
struct flow flow;
uint32_t hash;
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,
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. */
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++;
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;
}
}
/* 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 {
? 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;
}
{
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);
}
struct flow flow;
int error;
- flow_extract(packet, 0, NULL, 0, &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) {
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);
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 {
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,
enumerate_types,
enumerate_names,
del,
+ port_open_type,
type_run,
type_run_fast,
type_wait,