aboutsummaryrefslogtreecommitdiffstats
path: root/net/packet/af_packet.c
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2013-03-25 16:19:57 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-26 12:44:43 -0400
commitc1aad275b0293d2b1905ec95a945422262470684 (patch)
tree68ce7c931434840a46bffd1e9db5cb20c0feb7cd /net/packet/af_packet.c
parent38502af77e07b5d6650b9ff99a0b482d86366592 (diff)
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>
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r--net/packet/af_packet.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index bd0d14c97d41..83fdd0a87eb6 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -88,6 +88,7 @@
88#include <linux/virtio_net.h> 88#include <linux/virtio_net.h>
89#include <linux/errqueue.h> 89#include <linux/errqueue.h>
90#include <linux/net_tstamp.h> 90#include <linux/net_tstamp.h>
91#include <net/flow_keys.h>
91 92
92#ifdef CONFIG_INET 93#ifdef CONFIG_INET
93#include <net/inet_common.h> 94#include <net/inet_common.h>
@@ -1412,6 +1413,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
1412 __be16 proto = 0; 1413 __be16 proto = 0;
1413 int err; 1414 int err;
1414 int extra_len = 0; 1415 int extra_len = 0;
1416 struct flow_keys keys;
1415 1417
1416 /* 1418 /*
1417 * Get and verify the address. 1419 * Get and verify the address.
@@ -1512,6 +1514,11 @@ retry:
1512 if (unlikely(extra_len == 4)) 1514 if (unlikely(extra_len == 4))
1513 skb->no_fcs = 1; 1515 skb->no_fcs = 1;
1514 1516
1517 if (skb_flow_dissect(skb, &keys))
1518 skb_set_transport_header(skb, keys.thoff);
1519 else
1520 skb_reset_transport_header(skb);
1521
1515 dev_queue_xmit(skb); 1522 dev_queue_xmit(skb);
1516 rcu_read_unlock(); 1523 rcu_read_unlock();
1517 return len; 1524 return len;
@@ -1918,6 +1925,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
1918 struct page *page; 1925 struct page *page;
1919 void *data; 1926 void *data;
1920 int err; 1927 int err;
1928 struct flow_keys keys;
1921 1929
1922 ph.raw = frame; 1930 ph.raw = frame;
1923 1931
@@ -1943,6 +1951,11 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
1943 skb_reserve(skb, hlen); 1951 skb_reserve(skb, hlen);
1944 skb_reset_network_header(skb); 1952 skb_reset_network_header(skb);
1945 1953
1954 if (skb_flow_dissect(skb, &keys))
1955 skb_set_transport_header(skb, keys.thoff);
1956 else
1957 skb_reset_transport_header(skb);
1958
1946 if (po->tp_tx_has_off) { 1959 if (po->tp_tx_has_off) {
1947 int off_min, off_max, off; 1960 int off_min, off_max, off;
1948 off_min = po->tp_hdrlen - sizeof(struct sockaddr_ll); 1961 off_min = po->tp_hdrlen - sizeof(struct sockaddr_ll);
@@ -2199,6 +2212,7 @@ static int packet_snd(struct socket *sock,
2199 unsigned short gso_type = 0; 2212 unsigned short gso_type = 0;
2200 int hlen, tlen; 2213 int hlen, tlen;
2201 int extra_len = 0; 2214 int extra_len = 0;
2215 struct flow_keys keys;
2202 2216
2203 /* 2217 /*
2204 * Get and verify the address. 2218 * Get and verify the address.
@@ -2351,6 +2365,13 @@ static int packet_snd(struct socket *sock,
2351 len += vnet_hdr_len; 2365 len += vnet_hdr_len;
2352 } 2366 }
2353 2367
2368 if (skb->ip_summed == CHECKSUM_PARTIAL)
2369 skb_set_transport_header(skb, skb_checksum_start_offset(skb));
2370 else if (skb_flow_dissect(skb, &keys))
2371 skb_set_transport_header(skb, keys.thoff);
2372 else
2373 skb_set_transport_header(skb, reserve);
2374
2354 if (unlikely(extra_len == 4)) 2375 if (unlikely(extra_len == 4))
2355 skb->no_fcs = 1; 2376 skb->no_fcs = 1;
2356 2377