Skip to content

Commit

Permalink
packet: set transport header before doing xmit
Browse files Browse the repository at this point in the history
Set the transport header for 1) some drivers (e.g ixgbe needs l4 header to do
atr) 2) precise packet length estimation (introduced in 1def923) 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 <[email protected]>
Signed-off-by: Jason Wang <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
jasowang authored and davem330 committed Mar 26, 2013
1 parent 38502af commit c1aad27
Showing 1 changed file with 21 additions and 0 deletions.
21 changes: 21 additions & 0 deletions net/packet/af_packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
#include <linux/virtio_net.h>
#include <linux/errqueue.h>
#include <linux/net_tstamp.h>
#include <net/flow_keys.h>

#ifdef CONFIG_INET
#include <net/inet_common.h>
Expand Down Expand Up @@ -1412,6 +1413,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
__be16 proto = 0;
int err;
int extra_len = 0;
struct flow_keys keys;

/*
* Get and verify the address.
Expand Down Expand Up @@ -1512,6 +1514,11 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
if (unlikely(extra_len == 4))
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);
rcu_read_unlock();
return len;
Expand Down Expand Up @@ -1918,6 +1925,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
struct page *page;
void *data;
int err;
struct flow_keys keys;

ph.raw = frame;

Expand All @@ -1943,6 +1951,11 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
skb_reserve(skb, hlen);
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) {
int off_min, off_max, off;
off_min = po->tp_hdrlen - sizeof(struct sockaddr_ll);
Expand Down Expand Up @@ -2199,6 +2212,7 @@ static int packet_snd(struct socket *sock,
unsigned short gso_type = 0;
int hlen, tlen;
int extra_len = 0;
struct flow_keys keys;

/*
* Get and verify the address.
Expand Down Expand Up @@ -2351,6 +2365,13 @@ static int packet_snd(struct socket *sock,
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))
skb->no_fcs = 1;

Expand Down

0 comments on commit c1aad27

Please sign in to comment.