diff options
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 15 | ||||
| -rw-r--r-- | drivers/net/tap.c | 4 | ||||
| -rw-r--r-- | drivers/net/tun.c | 4 | ||||
| -rw-r--r-- | drivers/net/xen-netback/netback.c | 15 | ||||
| -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 | ||||
| -rw-r--r-- | net/ethernet/eth.c | 13 | ||||
| -rw-r--r-- | net/packet/af_packet.c | 26 |
10 files changed, 56 insertions, 39 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index c1334a8ac8f3..e7aae45a01f8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | |||
| @@ -148,12 +148,8 @@ static inline int mlx5e_skb_l2_header_offset(struct sk_buff *skb) | |||
| 148 | 148 | ||
| 149 | static inline int mlx5e_skb_l3_header_offset(struct sk_buff *skb) | 149 | static inline int mlx5e_skb_l3_header_offset(struct sk_buff *skb) |
| 150 | { | 150 | { |
| 151 | struct flow_keys keys; | ||
| 152 | |||
| 153 | if (skb_transport_header_was_set(skb)) | 151 | if (skb_transport_header_was_set(skb)) |
| 154 | return skb_transport_offset(skb); | 152 | return skb_transport_offset(skb); |
| 155 | else if (skb_flow_dissect_flow_keys(skb, &keys, 0)) | ||
| 156 | return keys.control.thoff; | ||
| 157 | else | 153 | else |
| 158 | return mlx5e_skb_l2_header_offset(skb); | 154 | return mlx5e_skb_l2_header_offset(skb); |
| 159 | } | 155 | } |
| @@ -172,15 +168,8 @@ static inline u16 mlx5e_calc_min_inline(enum mlx5_inline_modes mode, | |||
| 172 | hlen += VLAN_HLEN; | 168 | hlen += VLAN_HLEN; |
| 173 | break; | 169 | break; |
| 174 | case MLX5_INLINE_MODE_IP: | 170 | case MLX5_INLINE_MODE_IP: |
| 175 | /* When transport header is set to zero, it means no transport | 171 | hlen = mlx5e_skb_l3_header_offset(skb); |
| 176 | * header. When transport header is set to 0xff's, it means | 172 | break; |
| 177 | * transport header wasn't set. | ||
| 178 | */ | ||
| 179 | if (skb_transport_offset(skb)) { | ||
| 180 | hlen = mlx5e_skb_l3_header_offset(skb); | ||
| 181 | break; | ||
| 182 | } | ||
| 183 | /* fall through */ | ||
| 184 | case MLX5_INLINE_MODE_L2: | 173 | case MLX5_INLINE_MODE_L2: |
| 185 | default: | 174 | default: |
| 186 | hlen = mlx5e_skb_l2_header_offset(skb); | 175 | hlen = mlx5e_skb_l2_header_offset(skb); |
diff --git a/drivers/net/tap.c b/drivers/net/tap.c index c0b52e48f0e6..2ea9b4976f4a 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c | |||
| @@ -712,7 +712,7 @@ static ssize_t tap_get_user(struct tap_queue *q, void *msg_control, | |||
| 712 | goto err_kfree; | 712 | goto err_kfree; |
| 713 | } | 713 | } |
| 714 | 714 | ||
| 715 | skb_probe_transport_header(skb, ETH_HLEN); | 715 | skb_probe_transport_header(skb); |
| 716 | 716 | ||
| 717 | /* Move network header to the right position for VLAN tagged packets */ | 717 | /* Move network header to the right position for VLAN tagged packets */ |
| 718 | if ((skb->protocol == htons(ETH_P_8021Q) || | 718 | if ((skb->protocol == htons(ETH_P_8021Q) || |
| @@ -1187,7 +1187,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp) | |||
| 1187 | tap = rcu_dereference(q->tap); | 1187 | tap = rcu_dereference(q->tap); |
| 1188 | if (tap) { | 1188 | if (tap) { |
| 1189 | skb->dev = tap->dev; | 1189 | skb->dev = tap->dev; |
| 1190 | skb_probe_transport_header(skb, ETH_HLEN); | 1190 | skb_probe_transport_header(skb); |
| 1191 | dev_queue_xmit(skb); | 1191 | dev_queue_xmit(skb); |
| 1192 | } else { | 1192 | } else { |
| 1193 | kfree_skb(skb); | 1193 | kfree_skb(skb); |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index fed298c0cb39..80bff1b4ec17 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
| @@ -1929,7 +1929,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
| 1929 | } | 1929 | } |
| 1930 | 1930 | ||
| 1931 | skb_reset_network_header(skb); | 1931 | skb_reset_network_header(skb); |
| 1932 | skb_probe_transport_header(skb, 0); | 1932 | skb_probe_transport_header(skb); |
| 1933 | 1933 | ||
| 1934 | if (skb_xdp) { | 1934 | if (skb_xdp) { |
| 1935 | struct bpf_prog *xdp_prog; | 1935 | struct bpf_prog *xdp_prog; |
| @@ -2482,7 +2482,7 @@ build: | |||
| 2482 | 2482 | ||
| 2483 | skb->protocol = eth_type_trans(skb, tun->dev); | 2483 | skb->protocol = eth_type_trans(skb, tun->dev); |
| 2484 | skb_reset_network_header(skb); | 2484 | skb_reset_network_header(skb); |
| 2485 | skb_probe_transport_header(skb, 0); | 2485 | skb_probe_transport_header(skb); |
| 2486 | 2486 | ||
| 2487 | if (skb_xdp) { | 2487 | if (skb_xdp) { |
| 2488 | err = do_xdp_generic(xdp_prog, skb); | 2488 | err = do_xdp_generic(xdp_prog, skb); |
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 80aae3a32c2a..c801a832851c 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
| @@ -1169,15 +1169,24 @@ static int xenvif_tx_submit(struct xenvif_queue *queue) | |||
| 1169 | continue; | 1169 | continue; |
| 1170 | } | 1170 | } |
| 1171 | 1171 | ||
| 1172 | skb_probe_transport_header(skb, 0); | 1172 | skb_probe_transport_header(skb); |
| 1173 | 1173 | ||
| 1174 | /* If the packet is GSO then we will have just set up the | 1174 | /* If the packet is GSO then we will have just set up the |
| 1175 | * transport header offset in checksum_setup so it's now | 1175 | * transport header offset in checksum_setup so it's now |
| 1176 | * straightforward to calculate gso_segs. | 1176 | * straightforward to calculate gso_segs. |
| 1177 | */ | 1177 | */ |
| 1178 | if (skb_is_gso(skb)) { | 1178 | if (skb_is_gso(skb)) { |
| 1179 | int mss = skb_shinfo(skb)->gso_size; | 1179 | int mss, hdrlen; |
| 1180 | int hdrlen = skb_transport_header(skb) - | 1180 | |
| 1181 | /* GSO implies having the L4 header. */ | ||
| 1182 | WARN_ON_ONCE(!skb_transport_header_was_set(skb)); | ||
| 1183 | if (unlikely(!skb_transport_header_was_set(skb))) { | ||
| 1184 | kfree_skb(skb); | ||
| 1185 | continue; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | mss = skb_shinfo(skb)->gso_size; | ||
| 1189 | hdrlen = skb_transport_header(skb) - | ||
| 1181 | skb_mac_header(skb) + | 1190 | skb_mac_header(skb) + |
| 1182 | tcp_hdrlen(skb); | 1191 | tcp_hdrlen(skb); |
| 1183 | 1192 | ||
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 | } |
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 4c520110b04f..f7a3d7a171c7 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
| @@ -265,6 +265,18 @@ void eth_header_cache_update(struct hh_cache *hh, | |||
| 265 | EXPORT_SYMBOL(eth_header_cache_update); | 265 | EXPORT_SYMBOL(eth_header_cache_update); |
| 266 | 266 | ||
| 267 | /** | 267 | /** |
| 268 | * eth_header_parser_protocol - extract protocol from L2 header | ||
| 269 | * @skb: packet to extract protocol from | ||
| 270 | */ | ||
| 271 | __be16 eth_header_parse_protocol(const struct sk_buff *skb) | ||
| 272 | { | ||
| 273 | const struct ethhdr *eth = eth_hdr(skb); | ||
| 274 | |||
| 275 | return eth->h_proto; | ||
| 276 | } | ||
| 277 | EXPORT_SYMBOL(eth_header_parse_protocol); | ||
| 278 | |||
| 279 | /** | ||
| 268 | * eth_prepare_mac_addr_change - prepare for mac change | 280 | * eth_prepare_mac_addr_change - prepare for mac change |
| 269 | * @dev: network device | 281 | * @dev: network device |
| 270 | * @p: socket address | 282 | * @p: socket address |
| @@ -346,6 +358,7 @@ const struct header_ops eth_header_ops ____cacheline_aligned = { | |||
| 346 | .parse = eth_header_parse, | 358 | .parse = eth_header_parse, |
| 347 | .cache = eth_header_cache, | 359 | .cache = eth_header_cache, |
| 348 | .cache_update = eth_header_cache_update, | 360 | .cache_update = eth_header_cache_update, |
| 361 | .parse_protocol = eth_header_parse_protocol, | ||
| 349 | }; | 362 | }; |
| 350 | 363 | ||
| 351 | /** | 364 | /** |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 1cd1d83a4be0..8376bc1c1508 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -1850,6 +1850,15 @@ oom: | |||
| 1850 | return 0; | 1850 | return 0; |
| 1851 | } | 1851 | } |
| 1852 | 1852 | ||
| 1853 | static void packet_parse_headers(struct sk_buff *skb, struct socket *sock) | ||
| 1854 | { | ||
| 1855 | if (!skb->protocol && sock->type == SOCK_RAW) { | ||
| 1856 | skb_reset_mac_header(skb); | ||
| 1857 | skb->protocol = dev_parse_header_protocol(skb); | ||
| 1858 | } | ||
| 1859 | |||
| 1860 | skb_probe_transport_header(skb); | ||
| 1861 | } | ||
| 1853 | 1862 | ||
| 1854 | /* | 1863 | /* |
| 1855 | * Output a raw packet to a device layer. This bypasses all the other | 1864 | * Output a raw packet to a device layer. This bypasses all the other |
| @@ -1970,7 +1979,7 @@ retry: | |||
| 1970 | if (unlikely(extra_len == 4)) | 1979 | if (unlikely(extra_len == 4)) |
| 1971 | skb->no_fcs = 1; | 1980 | skb->no_fcs = 1; |
| 1972 | 1981 | ||
| 1973 | skb_probe_transport_header(skb, 0); | 1982 | packet_parse_headers(skb, sock); |
| 1974 | 1983 | ||
| 1975 | dev_queue_xmit(skb); | 1984 | dev_queue_xmit(skb); |
| 1976 | rcu_read_unlock(); | 1985 | rcu_read_unlock(); |
| @@ -2404,15 +2413,6 @@ static void tpacket_destruct_skb(struct sk_buff *skb) | |||
| 2404 | sock_wfree(skb); | 2413 | sock_wfree(skb); |
| 2405 | } | 2414 | } |
| 2406 | 2415 | ||
| 2407 | static void tpacket_set_protocol(const struct net_device *dev, | ||
| 2408 | struct sk_buff *skb) | ||
| 2409 | { | ||
| 2410 | if (dev->type == ARPHRD_ETHER) { | ||
| 2411 | skb_reset_mac_header(skb); | ||
| 2412 | skb->protocol = eth_hdr(skb)->h_proto; | ||
| 2413 | } | ||
| 2414 | } | ||
| 2415 | |||
| 2416 | static int __packet_snd_vnet_parse(struct virtio_net_hdr *vnet_hdr, size_t len) | 2416 | static int __packet_snd_vnet_parse(struct virtio_net_hdr *vnet_hdr, size_t len) |
| 2417 | { | 2417 | { |
| 2418 | if ((vnet_hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && | 2418 | if ((vnet_hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && |
| @@ -2483,8 +2483,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
| 2483 | return err; | 2483 | return err; |
| 2484 | if (!dev_validate_header(dev, skb->data, hdrlen)) | 2484 | if (!dev_validate_header(dev, skb->data, hdrlen)) |
| 2485 | return -EINVAL; | 2485 | return -EINVAL; |
| 2486 | if (!skb->protocol) | ||
| 2487 | tpacket_set_protocol(dev, skb); | ||
| 2488 | 2486 | ||
| 2489 | data += hdrlen; | 2487 | data += hdrlen; |
| 2490 | to_write -= hdrlen; | 2488 | to_write -= hdrlen; |
| @@ -2519,7 +2517,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
| 2519 | len = ((to_write > len_max) ? len_max : to_write); | 2517 | len = ((to_write > len_max) ? len_max : to_write); |
| 2520 | } | 2518 | } |
| 2521 | 2519 | ||
| 2522 | skb_probe_transport_header(skb, 0); | 2520 | packet_parse_headers(skb, sock); |
| 2523 | 2521 | ||
| 2524 | return tp_len; | 2522 | return tp_len; |
| 2525 | } | 2523 | } |
| @@ -2925,7 +2923,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) | |||
| 2925 | virtio_net_hdr_set_proto(skb, &vnet_hdr); | 2923 | virtio_net_hdr_set_proto(skb, &vnet_hdr); |
| 2926 | } | 2924 | } |
| 2927 | 2925 | ||
| 2928 | skb_probe_transport_header(skb, reserve); | 2926 | packet_parse_headers(skb, sock); |
| 2929 | 2927 | ||
| 2930 | if (unlikely(extra_len == 4)) | 2928 | if (unlikely(extra_len == 4)) |
| 2931 | skb->no_fcs = 1; | 2929 | skb->no_fcs = 1; |
