ofproto-dpif: Fix nondeterministic flow revalidation behavior.
authorBen Pfaff <blp@nicira.com>
Fri, 23 Dec 2011 00:48:50 +0000 (16:48 -0800)
committerBen Pfaff <blp@nicira.com>
Thu, 5 Jan 2012 00:13:42 +0000 (16:13 -0800)
commitfadc05164086fb289a8db6f71a80e84ec014bc0d
treeb11cd25f8d6e57737a1c32005befe2f73e2e0ce0
parent9075907cab7a9e91a260b7fae01c8ab24ef76d91
ofproto-dpif: Fix nondeterministic flow revalidation behavior.

SLB bonds are very strange beasts.  It's taken OVS a while to figure out
how they should really work.  Way back in the mists of time, when we were
in the midst of this process, we noticed that the following could happen:

1. Local VM sends a packet to the OVS bridge.
2. OVS bridge learns VM's MAC, forwards packets to SLB bond.
3. Remote switch hasn't learned packet's destination and
   forwards packet back to other interfaces in the SLB bond.

Normally nothing bad happens in this scenario because OVS has already
learned the local port for the VM's MAC in step 2 and the rules for SLB
bonding (this is rule #2 in vswitchd/INTERNALS).  But at the time we were
implementing this, OVS didn't yet use active flows to keep MAC learning
entries alive; only new flows prevented a MAC entry from aging out.  So
in steady state (e.g. just "ping" traffic) OVS would regularly forget MAC
addresses.  If the remote switch also happened to forward a packet back to
one of the SLB bond interfaces, then OVS would learn the VM's address on
the bond, with the result that any traffic coming in from the remote switch
would be black-holed until the VM sent a new packet.  This was not good.

The fix we applied at the time was commit 2416b8ecea (bridge: Eject NORMAL
flows without a learning entry from datapath.) followed by a small
refinement in commit e96a4d8035 (bridge: Feed flow stats into learning
table.).  This fix causes flows that don't have a learning entry to be
ejected from the datapath if revalidation occurs.  This forced the next
packet in the flow to go to userspace, which in turn caused learning to
happen, fixing the problem.

However, this isn't a good solution for several reasons:

* It forces more packets to userspace, which is expensive.

* It doesn't just affect the cases where it helps, those where an
  SLB bond is actually involved.  (This could be fixed, but it is
  not worth it.)

* It means that flow installability becomes nondeterministic.  When
  the first packet shows up for a flow, we install it.  But later
  if we revalidate it, we have to uninstall it.  That doesn't make
  sense; a flow should be either installable or not installable,
  not some weird mix.

Fortunately, the situation has improved since this fix was originally
designed.  First, active flows now keep MAC learning entries alive, since
commit e96a4d8035367 (bridge: Feed flow stats into learning table.)
Second, gratuitous ARP locking, added in commit 7febb9100b (bridge: Filter
some gratuitous ARPs on bond slaves.) means that gratuitous ARPs reflected
on bond slaves don't cause confusion (this is rule #4 in
vswitchd/INTERNALS).

These improvements mean that it is no longer necessary to have this
strange special case at all.  Therefore, this commit removes it.

I found this while investigating reports from code that I added to
occasionally check that flow actions were correct.

Signed-off-by: Ben Pfaff <blp@nicira.com>
ofproto/ofproto-dpif.c