ofproto-dpif: avoid losing track of kernel flows upon reinstallation
authorAndy Zhou <azhou@nicira.com>
Sat, 3 Aug 2013 03:22:17 +0000 (20:22 -0700)
committerBen Pfaff <blp@nicira.com>
Sat, 3 Aug 2013 07:16:33 +0000 (00:16 -0700)
This commit fixes a problem whereby userspace can lose track of a
flow installed in the kernel, instead believing that the flow is
not installed.  The most visible consequence of this bug was a
message in the ovs-vswitchd log warning about an unexpected flow
in the kernel.  Other possible consequences included loss of
statistics and failure to updates actions when the OpenFlow flow
table changed.

The problem arose in the following scenario.  Suppose userspace
sets up a kernel flow due to an arriving packet.  Before kernel
flow setup completes, another packet for that flow arrives.  The
kernel sends the new packet to userspace after userspace has
completed processing the batch of packets that set up the flow.
Userspace then attempts to reinstall the kernel flow.  This fails
with EEXIST, so userspace then marked the flow as not-installed,
even though it was successfully installed before and remains
installed.  The next time userspace dumped the kernel flow
table to gather statistics, it would complain about an unexpected
flow and delete it.

In practice, we have seen these messages with netperf TCP_CRR tests and
UDP stream tests.

This patch fixes the problem by changing userspace so that, once
it successfully installs a flow in the kernel, it will not reinstall
it when it sees another packet for the flow in userspace.  This
has the downside that, if something goes wrong and a flow
disappears from the kernel (e.g. ovs-dpctl del-flows), then userspace
won't reinstall it (until it tries to delete it).  (This is in fact
the reason why until now userspace reinstalled flows it knew it
already installed.)

Some more background may be warranted.  There are two EEXIST error
cases:

       1. A subfacet was installed successfully in a previous (recent)
          batch.  Now we've attempted to reinstall exactly the same
          subfacet in this batch.

       2. A subfacet was installed successfully in a previous (recent)
          batch or earlier in the current batch.  We've attempted to
          install a subfacet for an overlapping megaflow.

Before megaflows, installation errors were ignored completely.
Since megaflows were introduced, they have been handled by
considering on any installation error that the given subfacet is
not installed.  This works well for case #2 but causes case #1 to
yield unexpected flows, as described at the top of the commit
message.

This commit adds the wrinkle that we never try to reinstall
exactly the same subfacet that we know we installed successfully
earlier (and haven't deleted) unless its actions change.  This
ought to work just as well for case #2, and avoids the problem
with case #1.

Prepared with assistance from Ethan.

Signed-off-by: Andy Zhou <azhou@nicira.com>
[blp@nicira.com rewrote the commit message]
Signed-off-by: Ben Pfaff <blp@nicira.com>
ofproto/ofproto-dpif.c

index 9064809..f3f87f0 100644 (file)
@@ -3817,7 +3817,7 @@ handle_flow_miss_with_facet(struct flow_miss *miss, struct facet *facet,
         subfacet_update_stats(subfacet, stats);
     }
 
-    if (miss->upcall_type == DPIF_UC_MISS || subfacet->path != want_path) {
+    if (subfacet->path != want_path) {
         struct flow_miss_op *op = &ops[(*n_ops)++];
         struct dpif_flow_put *put = &op->dpif_op.u.flow_put;