summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-12-31 22:23:35 +0100
committerDavid S. Miller <davem@davemloft.net>2013-12-31 22:23:35 +0100
commit2205369a314e12fcec4781cc73ac9c08fc2b47de (patch)
tree5daa8338d99f62013631fc9c2ab1a6e6896ef0cd /include
parentMerge tag 'dt-fixes-for-3.13' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff)
downloadlinux-2205369a314e12fcec4781cc73ac9c08fc2b47de.tar.xz
linux-2205369a314e12fcec4781cc73ac9c08fc2b47de.zip
vlan: Fix header ops passthru when doing TX VLAN offload.
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>
Diffstat (limited to 'include')
-rw-r--r--include/linux/netdevice.h9
1 files changed, 9 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d9a550bf3e8e..7514b9c37a39 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1912,6 +1912,15 @@ static inline int dev_parse_header(const struct sk_buff *skb,
return dev->header_ops->parse(skb, haddr);
}
+static inline int dev_rebuild_header(struct sk_buff *skb)
+{
+ const struct net_device *dev = skb->dev;
+
+ if (!dev->header_ops || !dev->header_ops->rebuild)
+ return 0;
+ return dev->header_ops->rebuild(skb);
+}
+
typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);
int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
static inline int unregister_gifconf(unsigned int family)