Commit c1aad275 authored by Jason Wang's avatar Jason Wang Committed by David S. Miller

packet: set transport header before doing xmit

Set the transport header for 1) some drivers (e.g ixgbe needs l4 header to do
atr) 2) precise packet length estimation (introduced in 1def9238) needs l4
header to compute header length.

So this patch first tries to get l4 header for packet socket through
skb_flow_dissect(), and pretend no l4 header if skb_flow_dissect() fails.

Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: default avatarJason Wang <jasowang@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 38502af7
...@@ -88,6 +88,7 @@ ...@@ -88,6 +88,7 @@
#include <linux/virtio_net.h> #include <linux/virtio_net.h>
#include <linux/errqueue.h> #include <linux/errqueue.h>
#include <linux/net_tstamp.h> #include <linux/net_tstamp.h>
#include <net/flow_keys.h>
#ifdef CONFIG_INET #ifdef CONFIG_INET
#include <net/inet_common.h> #include <net/inet_common.h>
...@@ -1412,6 +1413,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, ...@@ -1412,6 +1413,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
__be16 proto = 0; __be16 proto = 0;
int err; int err;
int extra_len = 0; int extra_len = 0;
struct flow_keys keys;
/* /*
* Get and verify the address. * Get and verify the address.
...@@ -1512,6 +1514,11 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, ...@@ -1512,6 +1514,11 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
if (unlikely(extra_len == 4)) if (unlikely(extra_len == 4))
skb->no_fcs = 1; skb->no_fcs = 1;
if (skb_flow_dissect(skb, &keys))
skb_set_transport_header(skb, keys.thoff);
else
skb_reset_transport_header(skb);
dev_queue_xmit(skb); dev_queue_xmit(skb);
rcu_read_unlock(); rcu_read_unlock();
return len; return len;
...@@ -1918,6 +1925,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, ...@@ -1918,6 +1925,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
struct page *page; struct page *page;
void *data; void *data;
int err; int err;
struct flow_keys keys;
ph.raw = frame; ph.raw = frame;
...@@ -1943,6 +1951,11 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, ...@@ -1943,6 +1951,11 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
skb_reserve(skb, hlen); skb_reserve(skb, hlen);
skb_reset_network_header(skb); skb_reset_network_header(skb);
if (skb_flow_dissect(skb, &keys))
skb_set_transport_header(skb, keys.thoff);
else
skb_reset_transport_header(skb);
if (po->tp_tx_has_off) { if (po->tp_tx_has_off) {
int off_min, off_max, off; int off_min, off_max, off;
off_min = po->tp_hdrlen - sizeof(struct sockaddr_ll); off_min = po->tp_hdrlen - sizeof(struct sockaddr_ll);
...@@ -2199,6 +2212,7 @@ static int packet_snd(struct socket *sock, ...@@ -2199,6 +2212,7 @@ static int packet_snd(struct socket *sock,
unsigned short gso_type = 0; unsigned short gso_type = 0;
int hlen, tlen; int hlen, tlen;
int extra_len = 0; int extra_len = 0;
struct flow_keys keys;
/* /*
* Get and verify the address. * Get and verify the address.
...@@ -2351,6 +2365,13 @@ static int packet_snd(struct socket *sock, ...@@ -2351,6 +2365,13 @@ static int packet_snd(struct socket *sock,
len += vnet_hdr_len; len += vnet_hdr_len;
} }
if (skb->ip_summed == CHECKSUM_PARTIAL)
skb_set_transport_header(skb, skb_checksum_start_offset(skb));
else if (skb_flow_dissect(skb, &keys))
skb_set_transport_header(skb, keys.thoff);
else
skb_set_transport_header(skb, reserve);
if (unlikely(extra_len == 4)) if (unlikely(extra_len == 4))
skb->no_fcs = 1; skb->no_fcs = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment