diff options
| author | David S. Miller <davem@davemloft.net> | 2019-02-22 15:55:32 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2019-02-22 15:55:32 -0500 |
| commit | d29d1c4957d4dde1a7578b10f2a2d1fae39bd47a (patch) | |
| tree | b41c5aa5786c702502de08f1560751c51170156e /include/linux | |
| parent | 5328b633c9b3c3af38bec8cb70120658c0866e0a (diff) | |
| parent | 41f5f63cd17530d9eddaf99a71f5d069afd787d8 (diff) | |
Merge branch 'AF_PACKET-transport_offset-fix'
Maxim Mikityanskiy says:
====================
AF_PACKET transport_offset fix
This patch series contains the implementation of the RFC that was posted
on this mailing list previously:
https://www.spinics.net/lists/netdev/msg541709.html
It fixes having incorrect skb->transport_header values in cases when
dissect fails. Having correct values set by the kernel fixes mlx5
operation and allows to remove some unnecessary code flows in mlx5.
v2 changes:
- Rebase against the fresh net-next.
- Don't return bool from skb_probe_transport_header (and don't rename
the function).
- WARN_ON_ONCE and error path in case of GSO without the L4 header.
====================
Acked-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/etherdevice.h | 1 | ||||
| -rw-r--r-- | include/linux/netdevice.h | 10 | ||||
| -rw-r--r-- | include/linux/skbuff.h | 5 | ||||
| -rw-r--r-- | include/linux/virtio_net.h | 2 |
4 files changed, 13 insertions, 5 deletions
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index 2c0af7b00715..e2f3b21cd72a 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h | |||
| @@ -44,6 +44,7 @@ int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, | |||
| 44 | __be16 type); | 44 | __be16 type); |
| 45 | void eth_header_cache_update(struct hh_cache *hh, const struct net_device *dev, | 45 | void eth_header_cache_update(struct hh_cache *hh, const struct net_device *dev, |
| 46 | const unsigned char *haddr); | 46 | const unsigned char *haddr); |
| 47 | __be16 eth_header_parse_protocol(const struct sk_buff *skb); | ||
| 47 | int eth_prepare_mac_addr_change(struct net_device *dev, void *p); | 48 | int eth_prepare_mac_addr_change(struct net_device *dev, void *p); |
| 48 | void eth_commit_mac_addr_change(struct net_device *dev, void *p); | 49 | void eth_commit_mac_addr_change(struct net_device *dev, void *p); |
| 49 | int eth_mac_addr(struct net_device *dev, void *p); | 50 | int eth_mac_addr(struct net_device *dev, void *p); |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index aab4d9f6613d..6997f62cb6a0 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
| @@ -274,6 +274,7 @@ struct header_ops { | |||
| 274 | const struct net_device *dev, | 274 | const struct net_device *dev, |
| 275 | const unsigned char *haddr); | 275 | const unsigned char *haddr); |
| 276 | bool (*validate)(const char *ll_header, unsigned int len); | 276 | bool (*validate)(const char *ll_header, unsigned int len); |
| 277 | __be16 (*parse_protocol)(const struct sk_buff *skb); | ||
| 277 | }; | 278 | }; |
| 278 | 279 | ||
| 279 | /* These flag bits are private to the generic network queueing | 280 | /* These flag bits are private to the generic network queueing |
| @@ -2939,6 +2940,15 @@ static inline int dev_parse_header(const struct sk_buff *skb, | |||
| 2939 | return dev->header_ops->parse(skb, haddr); | 2940 | return dev->header_ops->parse(skb, haddr); |
| 2940 | } | 2941 | } |
| 2941 | 2942 | ||
| 2943 | static inline __be16 dev_parse_header_protocol(const struct sk_buff *skb) | ||
| 2944 | { | ||
| 2945 | const struct net_device *dev = skb->dev; | ||
| 2946 | |||
| 2947 | if (!dev->header_ops || !dev->header_ops->parse_protocol) | ||
| 2948 | return 0; | ||
| 2949 | return dev->header_ops->parse_protocol(skb); | ||
| 2950 | } | ||
| 2951 | |||
| 2942 | /* ll_header must have at least hard_header_len allocated */ | 2952 | /* ll_header must have at least hard_header_len allocated */ |
| 2943 | static inline bool dev_validate_header(const struct net_device *dev, | 2953 | static inline bool dev_validate_header(const struct net_device *dev, |
| 2944 | char *ll_header, int len) | 2954 | char *ll_header, int len) |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 2069fb90a559..27beb549ffbe 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
| @@ -2429,8 +2429,7 @@ static inline void skb_pop_mac_header(struct sk_buff *skb) | |||
| 2429 | skb->mac_header = skb->network_header; | 2429 | skb->mac_header = skb->network_header; |
| 2430 | } | 2430 | } |
| 2431 | 2431 | ||
| 2432 | static inline void skb_probe_transport_header(struct sk_buff *skb, | 2432 | static inline void skb_probe_transport_header(struct sk_buff *skb) |
| 2433 | const int offset_hint) | ||
| 2434 | { | 2433 | { |
| 2435 | struct flow_keys_basic keys; | 2434 | struct flow_keys_basic keys; |
| 2436 | 2435 | ||
| @@ -2439,8 +2438,6 @@ static inline void skb_probe_transport_header(struct sk_buff *skb, | |||
| 2439 | 2438 | ||
| 2440 | if (skb_flow_dissect_flow_keys_basic(skb, &keys, NULL, 0, 0, 0, 0)) | 2439 | if (skb_flow_dissect_flow_keys_basic(skb, &keys, NULL, 0, 0, 0, 0)) |
| 2441 | skb_set_transport_header(skb, keys.control.thoff); | 2440 | skb_set_transport_header(skb, keys.control.thoff); |
| 2442 | else if (offset_hint >= 0) | ||
| 2443 | skb_set_transport_header(skb, offset_hint); | ||
| 2444 | } | 2441 | } |
| 2445 | 2442 | ||
| 2446 | static inline void skb_mac_header_rebuild(struct sk_buff *skb) | 2443 | static inline void skb_mac_header_rebuild(struct sk_buff *skb) |
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 71f2394abbf7..6728bf581e98 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h | |||
| @@ -62,7 +62,7 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, | |||
| 62 | * probe and drop if does not match one of the above types. | 62 | * probe and drop if does not match one of the above types. |
| 63 | */ | 63 | */ |
| 64 | if (gso_type) { | 64 | if (gso_type) { |
| 65 | skb_probe_transport_header(skb, -1); | 65 | skb_probe_transport_header(skb); |
| 66 | if (!skb_transport_header_was_set(skb)) | 66 | if (!skb_transport_header_was_set(skb)) |
| 67 | return -EINVAL; | 67 | return -EINVAL; |
| 68 | } | 68 | } |
