History

net: accept UFOv6 packages in virtio_net_hdr_to_skb

Skb with skb->protocol 0 at the time of virtio_net_hdr_to_skb may have a protocol inferred from virtio_net_hdr with virtio_net_hdr_set_proto. Unlike TCP, UDP does not have separate types for IPv4 and IPv6. Type VIRTIO_NET_HDR_GSO_UDP is guessed to be IPv4/UDP. As of the below commit, UFOv6 packets are dropped due to not matching the protocol as obtained from dev_parse_header_protocol. Invert the test to take that L2 protocol field as starting point and pass both UFOv4 and UFOv6 for VIRTIO_NET_HDR_GSO_UDP.

Willem de Bruijn committed 4 years ago

Commit 7e5cced1 parent a9725e11 file · +20 −2Browse files

Unified · Split

include/linux/virtio_net.h+20−2
@@ -7,6 +7,21 @@ · 6 unmodified lines
7#include <uapi/linux/udp.h>7#include <uapi/linux/udp.h>
8#include <uapi/linux/virtio_net.h>8#include <uapi/linux/virtio_net.h>
9 9
10static inline bool virtio_net_hdr_match_proto(__be16 protocol, __u8 gso_type)
11{
12 switch (gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
13 case VIRTIO_NET_HDR_GSO_TCPV4:
14 return protocol == cpu_to_be16(ETH_P_IP);
15 case VIRTIO_NET_HDR_GSO_TCPV6:
16 return protocol == cpu_to_be16(ETH_P_IPV6);
17 case VIRTIO_NET_HDR_GSO_UDP:
18 return protocol == cpu_to_be16(ETH_P_IP) ||
19 protocol == cpu_to_be16(ETH_P_IPV6);
20 default:
21 return false;
22 }
23}
24
10static inline int virtio_net_hdr_set_proto(struct sk_buff *skb,25static inline int virtio_net_hdr_set_proto(struct sk_buff *skb,
11 const struct virtio_net_hdr *hdr)26 const struct virtio_net_hdr *hdr)
12{27{
@@ -88,9 +103,12 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, · 75 unmodified lines
88 if (!skb->protocol) {103 if (!skb->protocol) {
89 __be16 protocol = dev_parse_header_protocol(skb);104 __be16 protocol = dev_parse_header_protocol(skb);
90 105
91 virtio_net_hdr_set_proto(skb, hdr);106 if (!protocol)
92 if (protocol && protocol != skb->protocol)107 virtio_net_hdr_set_proto(skb, hdr);
108 else if (!virtio_net_hdr_match_proto(protocol, hdr->gso_type))
93 return -EINVAL;109 return -EINVAL;
110 else
111 skb->protocol = protocol;
94 }112 }
95retry:113retry:
96 if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys,114 if (!skb_flow_dissect_flow_keys_basic(NULL, skb, &keys,