On Nov 1, 2012, at 11:24 AM, Ben Pfaff <[email protected]> wrote:
>> @@ -47,6 +47,11 @@ v1.9.0 - xx xxx xxxx
>> - The ofproto library is now responsible for assigning OpenFlow port
>> numbers. An ofproto implementation should assign them when
>> port_construct() is called.
>> + - All dpif-based bridges of a particular type share a common
>> + datapath called "ovs-<type>", where "<type>" is the type of dpif.
>
> It seems likely to me that many users aren't really aware of types.
> So perhaps substitute an example, like this:
>> + - All dpif-based bridges of a particular type share a common
>> + datapath called "ovs-<type>", e.g. "ovs-system".
Okay.
> I think that the new #include "svec.h" is not necessary, because this
> version does not use svecs.
Thanks.
> It looks like "dpif-provider.h" is necessary only to access
> ->full_name and ->base_name in struct dpif. I think it would be
> better to use dpif_name() and dpif_base_name() instead, to avoid a
> minor layering violation.
We also need to get the class. I sent out a patch for a new dpif_type()
function to get that information, which you've already approved.
> The update to set_sflow() made me wonder what the dpif_sflow code does
> with the dpif. The answer is that it does nothing with the dpif, it
> just stores away a pointer and never references it again. So it would
> be better to update ofproto-dpif-sflow.c to just remove that parameter
> from dpif_sflow_create(), probably in a preparatory patch.
Okay, I took care of that in a patch you already approved.
> I think that the code in port_dump_next() should be made a little more
> robust. Currently, I believe that if there is some discrepancy
> between ofproto->ports and what is in the kernel datapath (e.g. some
> admin meddling with "ovs-dpctl del-port"), then that discrepancy will
> be returned as an error to the caller, who will interpret it as
> meaning that there are no more ports and thus not call back to find
> out any more. So I think that port_dump_next() probably should have a
> retry loop for when port_query_by_name() fails.
Makes sense. Done.
> update_stats() ends up calling odp_port_to_ofport() twice, once via
> odp_port_to_ofproto_dpif(), once via odp_port_to_ofp_port(). It would
> be more efficient to do this just once, directly. I don't think the
> code would look any worse for it, and perhaps even a little better.
Good point. More on that in the next comment...
> Similarly, odp_port_to_ofproto_dpif() does the same thing, through
> odp_port_to_ofproto_dpif() and ofproto_dpif_vsp_adjust(). This one is
> more important because it is on the flow setup fast path. I think
> that doing this lookup twice is likely to show up in "ovs-benchmark
> rate" results.
As we discussed off-line, I think you meant handle_miss_upcalls(). It looks
like handle_sflow_upcall() is also affected. Making these changes allowed me
to get rid of odp_port_to_ofproto_dpif(), and I think has a couple other
performance-related benefits. Thanks!
Below, you should find an incremental.
--Justin
-=-=-=-=-=-=-=-=-=-
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index ae2c14e..283aea9 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -618,8 +618,8 @@ struct dpif_backer {
/* All existing ofproto_backer instances, indexed by ofproto->up.type. */
static struct shash all_dpif_backers = SHASH_INITIALIZER(&all_dpif_backers);
-static struct ofproto_dpif *
-odp_port_to_ofproto_dpif(const struct dpif *, uint32_t odp_port);
+static struct ofport_dpif *
+odp_port_to_ofport(const struct dpif_backer *, uint32_t odp_port);
struct ofproto_dpif {
struct hmap_node all_ofproto_dpifs_node; /* In 'all_ofproto_dpifs'. */
@@ -703,7 +703,7 @@ static void update_learning_table(struct ofproto_dpif *,
struct ofbundle *);
/* Upcalls. */
#define FLOW_MISS_MAX_BATCH 50
-static int handle_upcalls(struct dpif *, unsigned int max_batch);
+static int handle_upcalls(struct dpif_backer *, unsigned int max_batch);
/* Flow expiration. */
static int expire(struct dpif_backer *);
@@ -881,7 +881,7 @@ type_run_fast(const char *type)
* presumably for real traffic as well. */
work = 0;
while (work < FLOW_MISS_MAX_BATCH) {
- int retval = handle_upcalls(backer->dpif, FLOW_MISS_MAX_BATCH - work);
+ int retval = handle_upcalls(backer, FLOW_MISS_MAX_BATCH - work);
if (retval <= 0) {
return -retval;
}
@@ -2980,13 +2980,17 @@ port_dump_next(const struct ofproto *ofproto_ OVS_UNUSED
struct port_dump_state *state = state_;
struct sset_node *node;
- node = sset_at_position(&ofproto->ports, &state->bucket,
- &state->offset);
- if (!node) {
- return EOF;
+ while ((node = sset_at_position(&ofproto->ports, &state->bucket,
+ &state->offset))) {
+ int error;
+
+ error = port_query_by_name(ofproto_, node->name, port);
+ if (error != ENODEV) {
+ return error;
+ }
}
- return port_query_by_name(ofproto_, node->name, port);
+ return EOF;
}
static int
@@ -3375,7 +3379,8 @@ handle_flow_miss(struct flow_miss *miss, struct flow_miss_
* port, sets flow->vlan_tci correctly for the VLAN of the VLAN splinter
* port, and pushes a VLAN header onto 'packet' (if it is nonnull). The
* caller must have called odp_flow_key_to_flow() and supply 'fitness' and
- * 'flow' from its output.
+ * 'flow' from its output. The 'flow' argument must have had the "in_port"
+ * member converted to the OpenFlow number.
*
* Sets '*initial_tci' to the VLAN TCI with which the packet was really
* received, that is, the actual VLAN TCI extracted by odp_flow_key_to_flow().
@@ -3387,7 +3392,6 @@ ofproto_dpif_vsp_adjust(const struct ofproto_dpif *ofproto
struct flow *flow, ovs_be16 *initial_tci,
struct ofpbuf *packet)
{
- flow->in_port = odp_port_to_ofp_port(ofproto, flow->in_port);
if (fitness == ODP_FIT_ERROR) {
return fitness;
}
@@ -3422,7 +3426,7 @@ ofproto_dpif_vsp_adjust(const struct ofproto_dpif *ofproto
}
static void
-handle_miss_upcalls(struct dpif *dpif, struct dpif_upcall *upcalls,
+handle_miss_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls,
size_t n_upcalls)
{
struct dpif_upcall *upcall;
@@ -3451,12 +3455,13 @@ handle_miss_upcalls(struct dpif *dpif, struct dpif_upcal
struct flow_miss *existing_miss;
enum odp_key_fitness fitness;
struct ofproto_dpif *ofproto;
+ struct ofport_dpif *port;
struct flow flow;
uint32_t hash;
fitness = odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow);
- ofproto = odp_port_to_ofproto_dpif(dpif, flow.in_port);
- if (!ofproto) {
+ port = odp_port_to_ofport(backer, flow.in_port);
+ if (!port) {
/* Received packet on 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
@@ -3465,6 +3470,8 @@ handle_miss_upcalls(struct dpif *dpif, struct dpif_upcall
flow.in_port);
continue;
}
+ ofproto = ofproto_dpif_cast(port->up.ofproto);
+ flow.in_port = port->up.ofp_port;
/* Obtain metadata and check userspace/kernel agreement on flow match,
* then set 'flow''s header pointers. */
@@ -3506,7 +3513,7 @@ handle_miss_upcalls(struct dpif *dpif, struct dpif_upcall
for (i = 0; i < n_ops; i++) {
dpif_ops[i] = &flow_miss_ops[i].dpif_op;
}
- dpif_operate(dpif, dpif_ops, n_ops);
+ dpif_operate(backer->dpif, dpif_ops, n_ops);
/* Free memory and update facets. */
for (i = 0; i < n_ops; i++) {
@@ -3567,22 +3574,31 @@ classify_upcall(const struct dpif_upcall *upcall)
}
static void
-handle_sflow_upcall(struct dpif *dpif, const struct dpif_upcall *upcall)
+handle_sflow_upcall(struct dpif_backer *backer,
+ const struct dpif_upcall *upcall)
{
struct ofproto_dpif *ofproto;
union user_action_cookie cookie;
enum odp_key_fitness fitness;
+ struct ofport_dpif *port;
ovs_be16 initial_tci;
struct flow flow;
uint32_t odp_in_port;
fitness = odp_flow_key_to_flow(upcall->key, upcall->key_len, &flow);
- odp_in_port = flow.in_port;
- ofproto = odp_port_to_ofproto_dpif(dpif, odp_in_port);
- if (!ofproto || !ofproto->sflow) {
+
+ port = odp_port_to_ofport(backer, flow.in_port);
+ if (!port) {
+ return;
+ }
+
+ ofproto = ofproto_dpif_cast(port->up.ofproto);
+ if (!ofproto->sflow) {
return;
}
+ odp_in_port = flow.in_port;
+ flow.in_port = port->up.ofp_port;
fitness = ofproto_dpif_vsp_adjust(ofproto, fitness, &flow,
&initial_tci, upcall->packet);
if (fitness == ODP_FIT_ERROR) {
@@ -3595,7 +3611,7 @@ handle_sflow_upcall(struct dpif *dpif, const struct dpif_u
}
static int
-handle_upcalls(struct dpif *dpif, unsigned int max_batch)
+handle_upcalls(struct dpif_backer *backer, unsigned int max_batch)
{
struct dpif_upcall misses[FLOW_MISS_MAX_BATCH];
struct ofpbuf miss_bufs[FLOW_MISS_MAX_BATCH];
@@ -3614,7 +3630,7 @@ handle_upcalls(struct dpif *dpif, unsigned int max_batch)
ofpbuf_use_stub(buf, miss_buf_stubs[n_misses],
sizeof miss_buf_stubs[n_misses]);
- error = dpif_recv(dpif, upcall, buf);
+ error = dpif_recv(backer->dpif, upcall, buf);
if (error) {
ofpbuf_uninit(buf);
break;
@@ -3627,7 +3643,7 @@ handle_upcalls(struct dpif *dpif, unsigned int max_batch)
break;
case SFLOW_UPCALL:
- handle_sflow_upcall(dpif, upcall);
+ handle_sflow_upcall(backer, upcall);
ofpbuf_uninit(buf);
break;
@@ -3638,7 +3654,7 @@ handle_upcalls(struct dpif *dpif, unsigned int max_batch)
}
/* Handle deferred MISS_UPCALL processing. */
- handle_miss_upcalls(dpif, misses, n_misses);
+ handle_miss_upcalls(backer, misses, n_misses);
for (i = 0; i < n_misses; i++) {
ofpbuf_uninit(&miss_bufs[i]);
}
@@ -3789,6 +3805,7 @@ update_stats(struct dpif_backer *backer)
struct subfacet *subfacet;
enum odp_key_fitness fitness;
struct ofproto_dpif *ofproto;
+ struct ofport_dpif *port;
uint32_t key_hash;
fitness = odp_flow_key_to_flow(key, key_len, &flow);
@@ -3796,8 +3813,8 @@ update_stats(struct dpif_backer *backer)
continue;
}
- ofproto = odp_port_to_ofproto_dpif(backer->dpif, flow.in_port);
- if (!ofproto) {
+ port = odp_port_to_ofport(backer, flow.in_port);
+ 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
@@ -3808,8 +3825,9 @@ update_stats(struct dpif_backer *backer)
continue;
}
+ ofproto = ofproto_dpif_cast(port->up.ofproto);
+ flow.in_port = port->up.ofp_port;
key_hash = odp_flow_key_hash(key, key_len);
- flow.in_port = odp_port_to_ofp_port(ofproto, flow.in_port);
subfacet = subfacet_find(ofproto, key, key_len, key_hash, &flow);
switch (subfacet ? subfacet->path : SF_NOT_INSTALLED) {
@@ -7156,6 +7174,7 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, int argc,
}
fitness = odp_flow_key_to_flow(odp_key.data, odp_key.size, &flow);
+ flow.in_port = odp_port_to_ofp_port(ofproto, flow.in_port);
/* Convert odp_key to flow. */
error = ofproto_dpif_vsp_adjust(ofproto, fitness, &flow,
@@ -7841,25 +7860,6 @@ odp_port_to_ofp_port(const struct ofproto_dpif *ofproto,
}
}
-static struct ofproto_dpif *
-odp_port_to_ofproto_dpif(const struct dpif *dpif, uint32_t odp_port)
-{
- struct dpif_backer *backer;
- struct ofport_dpif *port;
-
- backer = shash_find_data(&all_dpif_backers, dpif_type(dpif));
- if (!backer) {
- return NULL;
- }
-
- port = odp_port_to_ofport(backer, odp_port);
- if (!port) {
- return NULL;
- }
-
- return ofproto_dpif_cast(port->up.ofproto);
-}
-
const struct ofproto_class ofproto_dpif_class = {
init,
enumerate_types,
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev