mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-08 23:43:58 +00:00
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: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
38502af77e
commit
c1aad275b0
1 changed files with 21 additions and 0 deletions
|
@ -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,
|
||||||
__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 @@ retry:
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue