macvtap: set transport header before passing skb to lower device
Set the transport header for 1) some drivers (e.g ixgbe) needs l4 header 2)
precise packet length estimation (introduced in 1def9238
) needs l4 header to
compute header length.
For the packets with partial checksum, the patch just set the transport header
to csum_start. Otherwise tries to use skb_flow_dissect() to get l4 offset, if it
fails, just pretend no l4 header.
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:
Родитель
a88b9ce5ad
Коммит
9b4d669bc0
|
@ -21,6 +21,7 @@
|
||||||
#include <net/rtnetlink.h>
|
#include <net/rtnetlink.h>
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
#include <linux/virtio_net.h>
|
#include <linux/virtio_net.h>
|
||||||
|
#include <net/flow_keys.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A macvtap queue is the central object of this driver, it connects
|
* A macvtap queue is the central object of this driver, it connects
|
||||||
|
@ -645,6 +646,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
||||||
int vnet_hdr_len = 0;
|
int vnet_hdr_len = 0;
|
||||||
int copylen = 0;
|
int copylen = 0;
|
||||||
bool zerocopy = false;
|
bool zerocopy = false;
|
||||||
|
struct flow_keys keys;
|
||||||
|
|
||||||
if (q->flags & IFF_VNET_HDR) {
|
if (q->flags & IFF_VNET_HDR) {
|
||||||
vnet_hdr_len = q->vnet_hdr_sz;
|
vnet_hdr_len = q->vnet_hdr_sz;
|
||||||
|
@ -725,6 +727,13 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
|
||||||
goto err_kfree;
|
goto err_kfree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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, ETH_HLEN);
|
||||||
|
|
||||||
rcu_read_lock_bh();
|
rcu_read_lock_bh();
|
||||||
vlan = rcu_dereference_bh(q->vlan);
|
vlan = rcu_dereference_bh(q->vlan);
|
||||||
/* copy skb_ubuf_info for callback when skb has no error */
|
/* copy skb_ubuf_info for callback when skb has no error */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче