Blame view
include/linux/virtio_net.h
3.04 KB
b24413180
|
1 |
/* SPDX-License-Identifier: GPL-2.0 */ |
fd2a0437d
|
2 3 4 5 6 |
#ifndef _LINUX_VIRTIO_NET_H #define _LINUX_VIRTIO_NET_H #include <linux/if_vlan.h> #include <uapi/linux/virtio_net.h> |
5150140b4
|
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
static inline int virtio_net_hdr_set_proto(struct sk_buff *skb, const struct virtio_net_hdr *hdr) { switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { case VIRTIO_NET_HDR_GSO_TCPV4: case VIRTIO_NET_HDR_GSO_UDP: skb->protocol = cpu_to_be16(ETH_P_IP); break; case VIRTIO_NET_HDR_GSO_TCPV6: skb->protocol = cpu_to_be16(ETH_P_IPV6); break; default: return -EINVAL; } return 0; } |
fd2a0437d
|
24 25 26 27 |
static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, const struct virtio_net_hdr *hdr, bool little_endian) { |
60335608e
|
28 |
unsigned int gso_type = 0; |
fd2a0437d
|
29 30 31 32 33 34 35 36 37 |
if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { case VIRTIO_NET_HDR_GSO_TCPV4: gso_type = SKB_GSO_TCPV4; break; case VIRTIO_NET_HDR_GSO_TCPV6: gso_type = SKB_GSO_TCPV6; break; |
60335608e
|
38 39 40 |
case VIRTIO_NET_HDR_GSO_UDP: gso_type = SKB_GSO_UDP; break; |
fd2a0437d
|
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
default: return -EINVAL; } if (hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN) gso_type |= SKB_GSO_TCP_ECN; if (hdr->gso_size == 0) return -EINVAL; } if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { u16 start = __virtio16_to_cpu(little_endian, hdr->csum_start); u16 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); if (!skb_partial_csum_set(skb, start, off)) return -EINVAL; } if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { u16 gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size); skb_shinfo(skb)->gso_size = gso_size; skb_shinfo(skb)->gso_type = gso_type; /* Header must be checked, and gso_segs computed. */ skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; skb_shinfo(skb)->gso_segs = 0; } return 0; } static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, struct virtio_net_hdr *hdr, |
6391a4481
|
76 |
bool little_endian, |
5320e035d
|
77 78 |
bool has_data_valid, int vlan_hlen) |
fd2a0437d
|
79 |
{ |
9403cd7cb
|
80 |
memset(hdr, 0, sizeof(*hdr)); /* no info leak */ |
fd2a0437d
|
81 82 83 84 85 86 87 88 89 90 91 92 93 |
if (skb_is_gso(skb)) { struct skb_shared_info *sinfo = skb_shinfo(skb); /* This is a hint as to how much should be linear. */ hdr->hdr_len = __cpu_to_virtio16(little_endian, skb_headlen(skb)); hdr->gso_size = __cpu_to_virtio16(little_endian, sinfo->gso_size); if (sinfo->gso_type & SKB_GSO_TCPV4) hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; else if (sinfo->gso_type & SKB_GSO_TCPV6) hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; |
fd2a0437d
|
94 95 96 97 98 99 100 101 102 |
else return -EINVAL; if (sinfo->gso_type & SKB_GSO_TCP_ECN) hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN; } else hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; if (skb->ip_summed == CHECKSUM_PARTIAL) { hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; |
5320e035d
|
103 104 |
hdr->csum_start = __cpu_to_virtio16(little_endian, skb_checksum_start_offset(skb) + vlan_hlen); |
fd2a0437d
|
105 106 |
hdr->csum_offset = __cpu_to_virtio16(little_endian, skb->csum_offset); |
6391a4481
|
107 108 109 |
} else if (has_data_valid && skb->ip_summed == CHECKSUM_UNNECESSARY) { hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID; |
fd2a0437d
|
110 111 112 113 |
} /* else everything is zero */ return 0; } |
d66016a77
|
114 |
#endif /* _LINUX_VIRTIO_NET_H */ |