diff options
author | David S. Miller <davem@davemloft.net> | 2014-01-01 01:23:35 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-01-16 03:28:49 +0400 |
commit | c726095ec74daabd48a9a4ed48d46304601017b4 (patch) | |
tree | 5455a5a161d1230c07e8e1c26b643a0497ab55a8 /net/core | |
parent | 05df3bfbc832046a774fce22654cc55260cd1583 (diff) | |
download | linux-c726095ec74daabd48a9a4ed48d46304601017b4.tar.xz |
vlan: Fix header ops passthru when doing TX VLAN offload.
[ Upstream commit 2205369a314e12fcec4781cc73ac9c08fc2b47de ]
When the vlan code detects that the real device can do TX VLAN offloads
in hardware, it tries to arrange for the real device's header_ops to
be invoked directly.
But it does so illegally, by simply hooking the real device's
header_ops up to the VLAN device.
This doesn't work because we will end up invoking a set of header_ops
routines which expect a device type which matches the real device, but
will see a VLAN device instead.
Fix this by providing a pass-thru set of header_ops which will arrange
to pass the proper real device instead.
To facilitate this add a dev_rebuild_header(). There are
implementations which provide a ->cache and ->create but not a
->rebuild (f.e. PLIP). So we need a helper function just like
dev_hard_header() to avoid crashes.
Use this helper in the one existing place where the
header_ops->rebuild was being invoked, the neighbour code.
With lots of help from Florian Westphal.
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/neighbour.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 0034b611fa5e..49aeab86f317 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1274,7 +1274,7 @@ int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb) if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL, skb->len) < 0 && - dev->header_ops->rebuild(skb)) + dev_rebuild_header(skb)) return 0; return dev_queue_xmit(skb); |