datapath: Fix VLAN insertion behavior on Linux 2.6.27 and 2.6.28.
The behavior of __vlan_put_tag() has changed over time:
- In 2.6.26 and earlier, it adjusted both MAC and network header
pointers. (The latter didn't make any sense.)
- In 2.6.27 and 2.6.28, it did not adjust any header pointers at all.
- In 2.6.29 and later, it adjusts the MAC header pointer only.
The behavior in 2.6.26 and earlier, and in 2.2.29 and later, works OK for
Open vSwitch. The 2.6.27 and 2.6.28 behavior *almost* works OK, with a few
subtle problems. If an action that sets a VLAN tag is followed by an
action that strips a VLAN tag, the "strip" action silently fails. This is
because vlan_pull_tag() in datapath/actions.c sees the encapsulated
protocol, not the 802.1Q protocol, because the MAC header was not adjusted
and does not point to the 802.1Q header. If multiple set-VLAN actions
occur in a single flow, the second and later actions will fail for the same
reason.
This commit fixes the problem by ensuring that __vlan_put_tag() always
behaves as in 2.6.29 and later.
Reported-by: Reid Price <reid@nicira.com>
Bug #2867.