Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'virtio_udp_tunnel_08_07_2025' of https://github.com/pabeni/linux-devel

Paolo Abeni says:

====================
virtio: introduce GSO over UDP tunnel

Some virtualized deployments use UDP tunnel pervasively and are impacted
negatively by the lack of GSO support for such kind of traffic in the
virtual NIC driver.

The virtio_net specification recently introduced support for GSO over
UDP tunnel, this series updates the virtio implementation to support
such a feature.

Currently the kernel virtio support limits the feature space to 64,
while the virtio specification allows for a larger number of features.
Specifically the GSO-over-UDP-tunnel-related virtio features use bits
65-69.

The first four patches in this series rework the virtio and vhost
feature support to cope with up to 128 bits. The limit is set by
a define and could be easily raised in future, as needed.

This implementation choice is aimed at keeping the code churn as
limited as possible. For the same reason, only the virtio_net driver is
reworked to leverage the extended feature space; all other
virtio/vhost drivers are unaffected, but could be upgraded to support
the extended features space in a later time.

The last four patches bring in the actual GSO over UDP tunnel support.
As per specification, some additional fields are introduced into the
virtio net header to support the new offload. The presence of such
fields depends on the negotiated features.

New helpers are introduced to convert the UDP-tunneled skb metadata to
an extended virtio net header and vice versa. Such helpers are used by
the tun and virtio_net driver to cope with the newly supported offloads.

Tested with basic stream transfer with all the possible permutations of
host kernel/qemu/guest kernel with/without GSO over UDP tunnel support.
====================

Link: https://patch.msgid.link/cover.1751874094.git.pabeni@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+796 -170
+49 -9
drivers/net/tun.c
··· 186 186 struct net_device *dev; 187 187 netdev_features_t set_features; 188 188 #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \ 189 - NETIF_F_TSO6 | NETIF_F_GSO_UDP_L4) 189 + NETIF_F_TSO6 | NETIF_F_GSO_UDP_L4 | \ 190 + NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM) 190 191 191 192 int align; 192 193 int vnet_hdr_sz; ··· 926 925 dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | 927 926 TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX | 928 927 NETIF_F_HW_VLAN_STAG_TX; 928 + dev->hw_enc_features = dev->hw_features; 929 929 dev->features = dev->hw_features; 930 930 dev->vlan_features = dev->features & 931 931 ~(NETIF_F_HW_VLAN_CTAG_TX | ··· 1700 1698 struct sk_buff *skb; 1701 1699 size_t total_len = iov_iter_count(from); 1702 1700 size_t len = total_len, align = tun->align, linear; 1703 - struct virtio_net_hdr gso = { 0 }; 1701 + struct virtio_net_hdr_v1_hash_tunnel hdr; 1702 + struct virtio_net_hdr *gso; 1704 1703 int good_linear; 1705 1704 int copylen; 1706 1705 int hdr_len = 0; ··· 1711 1708 int skb_xdp = 1; 1712 1709 bool frags = tun_napi_frags_enabled(tfile); 1713 1710 enum skb_drop_reason drop_reason = SKB_DROP_REASON_NOT_SPECIFIED; 1711 + netdev_features_t features = 0; 1712 + 1713 + /* 1714 + * Keep it easy and always zero the whole buffer, even if the 1715 + * tunnel-related field will be touched only when the feature 1716 + * is enabled and the hdr size id compatible. 1717 + */ 1718 + memset(&hdr, 0, sizeof(hdr)); 1719 + gso = (struct virtio_net_hdr *)&hdr; 1714 1720 1715 1721 if (!(tun->flags & IFF_NO_PI)) { 1716 1722 if (len < sizeof(pi)) ··· 1733 1721 if (tun->flags & IFF_VNET_HDR) { 1734 1722 int vnet_hdr_sz = READ_ONCE(tun->vnet_hdr_sz); 1735 1723 1736 - hdr_len = tun_vnet_hdr_get(vnet_hdr_sz, tun->flags, from, &gso); 1724 + features = tun_vnet_hdr_guest_features(vnet_hdr_sz); 1725 + hdr_len = __tun_vnet_hdr_get(vnet_hdr_sz, tun->flags, 1726 + features, from, gso); 1737 1727 if (hdr_len < 0) 1738 1728 return hdr_len; 1739 1729 ··· 1769 1755 * (e.g gso or jumbo packet), we will do it at after 1770 1756 * skb was created with generic XDP routine. 1771 1757 */ 1772 - skb = tun_build_skb(tun, tfile, from, &gso, len, &skb_xdp); 1758 + skb = tun_build_skb(tun, tfile, from, gso, len, &skb_xdp); 1773 1759 err = PTR_ERR_OR_ZERO(skb); 1774 1760 if (err) 1775 1761 goto drop; ··· 1813 1799 } 1814 1800 } 1815 1801 1816 - if (tun_vnet_hdr_to_skb(tun->flags, skb, &gso)) { 1802 + if (tun_vnet_hdr_tnl_to_skb(tun->flags, features, skb, &hdr)) { 1817 1803 atomic_long_inc(&tun->rx_frame_errors); 1818 1804 err = -EINVAL; 1819 1805 goto free_skb; ··· 2064 2050 } 2065 2051 2066 2052 if (vnet_hdr_sz) { 2067 - struct virtio_net_hdr gso; 2053 + struct virtio_net_hdr_v1_hash_tunnel hdr; 2054 + struct virtio_net_hdr *gso; 2068 2055 2069 - ret = tun_vnet_hdr_from_skb(tun->flags, tun->dev, skb, &gso); 2056 + ret = tun_vnet_hdr_tnl_from_skb(tun->flags, tun->dev, skb, 2057 + &hdr); 2070 2058 if (ret) 2071 2059 return ret; 2072 2060 2073 - ret = tun_vnet_hdr_put(vnet_hdr_sz, iter, &gso); 2061 + /* 2062 + * Drop the packet if the configured header size is too small 2063 + * WRT the enabled offloads. 2064 + */ 2065 + gso = (struct virtio_net_hdr *)&hdr; 2066 + ret = __tun_vnet_hdr_put(vnet_hdr_sz, tun->dev->features, 2067 + iter, gso); 2074 2068 if (ret) 2075 2069 return ret; 2076 2070 } ··· 2379 2357 { 2380 2358 unsigned int datasize = xdp->data_end - xdp->data; 2381 2359 struct virtio_net_hdr *gso = xdp->data_hard_start; 2360 + struct virtio_net_hdr_v1_hash_tunnel *tnl_hdr; 2382 2361 struct bpf_prog *xdp_prog; 2383 2362 struct sk_buff *skb = NULL; 2384 2363 struct sk_buff_head *queue; 2364 + netdev_features_t features; 2385 2365 u32 rxhash = 0, act; 2386 2366 int buflen = xdp->frame_sz; 2387 2367 int metasize = 0; ··· 2449 2425 if (metasize > 0) 2450 2426 skb_metadata_set(skb, metasize); 2451 2427 2452 - if (tun_vnet_hdr_to_skb(tun->flags, skb, gso)) { 2428 + features = tun_vnet_hdr_guest_features(READ_ONCE(tun->vnet_hdr_sz)); 2429 + tnl_hdr = (struct virtio_net_hdr_v1_hash_tunnel *)gso; 2430 + if (tun_vnet_hdr_tnl_to_skb(tun->flags, features, skb, tnl_hdr)) { 2453 2431 atomic_long_inc(&tun->rx_frame_errors); 2454 2432 kfree_skb(skb); 2455 2433 ret = -EINVAL; ··· 2837 2811 2838 2812 } 2839 2813 2814 + #define PLAIN_GSO (NETIF_F_GSO_UDP_L4 | NETIF_F_TSO | NETIF_F_TSO6) 2815 + 2840 2816 /* This is like a cut-down ethtool ops, except done via tun fd so no 2841 2817 * privs required. */ 2842 2818 static int set_offload(struct tun_struct *tun, unsigned long arg) ··· 2867 2839 if (arg & TUN_F_USO4 && arg & TUN_F_USO6) { 2868 2840 features |= NETIF_F_GSO_UDP_L4; 2869 2841 arg &= ~(TUN_F_USO4 | TUN_F_USO6); 2842 + } 2843 + 2844 + /* 2845 + * Tunnel offload is allowed only if some plain offload is 2846 + * available, too. 2847 + */ 2848 + if (features & PLAIN_GSO && arg & TUN_F_UDP_TUNNEL_GSO) { 2849 + features |= NETIF_F_GSO_UDP_TUNNEL; 2850 + if (arg & TUN_F_UDP_TUNNEL_GSO_CSUM) 2851 + features |= NETIF_F_GSO_UDP_TUNNEL_CSUM; 2852 + arg &= ~(TUN_F_UDP_TUNNEL_GSO | 2853 + TUN_F_UDP_TUNNEL_GSO_CSUM); 2870 2854 } 2871 2855 } 2872 2856
+98 -15
drivers/net/tun_vnet.h
··· 6 6 #define TUN_VNET_LE 0x80000000 7 7 #define TUN_VNET_BE 0x40000000 8 8 9 + #define TUN_VNET_TNL_SIZE sizeof(struct virtio_net_hdr_v1_hash_tunnel) 10 + 9 11 static inline bool tun_vnet_legacy_is_little_endian(unsigned int flags) 10 12 { 11 13 bool be = IS_ENABLED(CONFIG_TUN_VNET_CROSS_LE) && ··· 109 107 } 110 108 } 111 109 112 - static inline int tun_vnet_hdr_get(int sz, unsigned int flags, 113 - struct iov_iter *from, 114 - struct virtio_net_hdr *hdr) 110 + static inline unsigned int tun_vnet_parse_size(netdev_features_t features) 115 111 { 112 + if (!(features & NETIF_F_GSO_UDP_TUNNEL)) 113 + return sizeof(struct virtio_net_hdr); 114 + 115 + return TUN_VNET_TNL_SIZE; 116 + } 117 + 118 + static inline int __tun_vnet_hdr_get(int sz, unsigned int flags, 119 + netdev_features_t features, 120 + struct iov_iter *from, 121 + struct virtio_net_hdr *hdr) 122 + { 123 + unsigned int parsed_size = tun_vnet_parse_size(features); 116 124 u16 hdr_len; 117 125 118 126 if (iov_iter_count(from) < sz) 119 127 return -EINVAL; 120 128 121 - if (!copy_from_iter_full(hdr, sizeof(*hdr), from)) 129 + if (!copy_from_iter_full(hdr, parsed_size, from)) 122 130 return -EFAULT; 123 131 124 132 hdr_len = tun_vnet16_to_cpu(flags, hdr->hdr_len); ··· 141 129 if (hdr_len > iov_iter_count(from)) 142 130 return -EINVAL; 143 131 144 - iov_iter_advance(from, sz - sizeof(*hdr)); 132 + iov_iter_advance(from, sz - parsed_size); 145 133 146 134 return hdr_len; 135 + } 136 + 137 + static inline int tun_vnet_hdr_get(int sz, unsigned int flags, 138 + struct iov_iter *from, 139 + struct virtio_net_hdr *hdr) 140 + { 141 + return __tun_vnet_hdr_get(sz, flags, 0, from, hdr); 142 + } 143 + 144 + static inline int __tun_vnet_hdr_put(int sz, netdev_features_t features, 145 + struct iov_iter *iter, 146 + const struct virtio_net_hdr *hdr) 147 + { 148 + unsigned int parsed_size = tun_vnet_parse_size(features); 149 + 150 + if (unlikely(iov_iter_count(iter) < sz)) 151 + return -EINVAL; 152 + 153 + if (unlikely(copy_to_iter(hdr, parsed_size, iter) != parsed_size)) 154 + return -EFAULT; 155 + 156 + if (iov_iter_zero(sz - parsed_size, iter) != sz - parsed_size) 157 + return -EFAULT; 158 + 159 + return 0; 147 160 } 148 161 149 162 static inline int tun_vnet_hdr_put(int sz, struct iov_iter *iter, 150 163 const struct virtio_net_hdr *hdr) 151 164 { 152 - if (unlikely(iov_iter_count(iter) < sz)) 153 - return -EINVAL; 154 - 155 - if (unlikely(copy_to_iter(hdr, sizeof(*hdr), iter) != sizeof(*hdr))) 156 - return -EFAULT; 157 - 158 - if (iov_iter_zero(sz - sizeof(*hdr), iter) != sz - sizeof(*hdr)) 159 - return -EFAULT; 160 - 161 - return 0; 165 + return __tun_vnet_hdr_put(sz, 0, iter, hdr); 162 166 } 163 167 164 168 static inline int tun_vnet_hdr_to_skb(unsigned int flags, struct sk_buff *skb, 165 169 const struct virtio_net_hdr *hdr) 166 170 { 167 171 return virtio_net_hdr_to_skb(skb, hdr, tun_vnet_is_little_endian(flags)); 172 + } 173 + 174 + /* 175 + * Tun is not aware of the negotiated guest features, guess them from the 176 + * virtio net hdr size 177 + */ 178 + static inline netdev_features_t tun_vnet_hdr_guest_features(int vnet_hdr_sz) 179 + { 180 + if (vnet_hdr_sz >= TUN_VNET_TNL_SIZE) 181 + return NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM; 182 + return 0; 183 + } 184 + 185 + static inline int 186 + tun_vnet_hdr_tnl_to_skb(unsigned int flags, netdev_features_t features, 187 + struct sk_buff *skb, 188 + const struct virtio_net_hdr_v1_hash_tunnel *hdr) 189 + { 190 + return virtio_net_hdr_tnl_to_skb(skb, hdr, 191 + features & NETIF_F_GSO_UDP_TUNNEL, 192 + features & NETIF_F_GSO_UDP_TUNNEL_CSUM, 193 + tun_vnet_is_little_endian(flags)); 168 194 } 169 195 170 196 static inline int tun_vnet_hdr_from_skb(unsigned int flags, ··· 225 175 DUMP_PREFIX_NONE, 226 176 16, 1, skb->head, 227 177 min(tun_vnet16_to_cpu(flags, hdr->hdr_len), 64), true); 178 + } 179 + WARN_ON_ONCE(1); 180 + return -EINVAL; 181 + } 182 + 183 + return 0; 184 + } 185 + 186 + static inline int 187 + tun_vnet_hdr_tnl_from_skb(unsigned int flags, 188 + const struct net_device *dev, 189 + const struct sk_buff *skb, 190 + struct virtio_net_hdr_v1_hash_tunnel *tnl_hdr) 191 + { 192 + bool has_tnl_offload = !!(dev->features & NETIF_F_GSO_UDP_TUNNEL); 193 + int vlan_hlen = skb_vlan_tag_present(skb) ? VLAN_HLEN : 0; 194 + 195 + if (virtio_net_hdr_tnl_from_skb(skb, tnl_hdr, has_tnl_offload, 196 + tun_vnet_is_little_endian(flags), 197 + vlan_hlen)) { 198 + struct virtio_net_hdr_v1 *hdr = &tnl_hdr->hash_hdr.hdr; 199 + struct skb_shared_info *sinfo = skb_shinfo(skb); 200 + 201 + if (net_ratelimit()) { 202 + int hdr_len = tun_vnet16_to_cpu(flags, hdr->hdr_len); 203 + 204 + netdev_err(dev, "unexpected GSO type: 0x%x, gso_size %d, hdr_len %d\n", 205 + sinfo->gso_type, 206 + tun_vnet16_to_cpu(flags, hdr->gso_size), 207 + tun_vnet16_to_cpu(flags, hdr->hdr_len)); 208 + print_hex_dump(KERN_ERR, "tun: ", DUMP_PREFIX_NONE, 209 + 16, 1, skb->head, min(hdr_len, 64), 210 + true); 228 211 } 229 212 WARN_ON_ONCE(1); 230 213 return -EINVAL;
+87 -23
drivers/net/virtio_net.c
··· 35 35 module_param(gso, bool, 0444); 36 36 module_param(napi_tx, bool, 0644); 37 37 38 + #define VIRTIO_OFFLOAD_MAP_MIN 46 39 + #define VIRTIO_OFFLOAD_MAP_MAX 47 40 + #define VIRTIO_FEATURES_MAP_MIN 65 41 + #define VIRTIO_O2F_DELTA (VIRTIO_FEATURES_MAP_MIN - \ 42 + VIRTIO_OFFLOAD_MAP_MIN) 43 + 44 + static bool virtio_is_mapped_offload(unsigned int obit) 45 + { 46 + return obit >= VIRTIO_OFFLOAD_MAP_MIN && 47 + obit <= VIRTIO_OFFLOAD_MAP_MAX; 48 + } 49 + 50 + static unsigned int virtio_offload_to_feature(unsigned int obit) 51 + { 52 + return virtio_is_mapped_offload(obit) ? obit + VIRTIO_O2F_DELTA : obit; 53 + } 54 + 38 55 /* FIXME: MTU in config. */ 39 56 #define GOOD_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) 40 57 #define GOOD_COPY_LEN 128 ··· 79 62 VIRTIO_NET_F_GUEST_CSUM, 80 63 VIRTIO_NET_F_GUEST_USO4, 81 64 VIRTIO_NET_F_GUEST_USO6, 82 - VIRTIO_NET_F_GUEST_HDRLEN 65 + VIRTIO_NET_F_GUEST_HDRLEN, 66 + VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_MAPPED, 67 + VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_CSUM_MAPPED, 83 68 }; 84 69 85 70 #define GUEST_OFFLOAD_GRO_HW_MASK ((1ULL << VIRTIO_NET_F_GUEST_TSO4) | \ 86 - (1ULL << VIRTIO_NET_F_GUEST_TSO6) | \ 87 - (1ULL << VIRTIO_NET_F_GUEST_ECN) | \ 88 - (1ULL << VIRTIO_NET_F_GUEST_UFO) | \ 89 - (1ULL << VIRTIO_NET_F_GUEST_USO4) | \ 90 - (1ULL << VIRTIO_NET_F_GUEST_USO6)) 71 + (1ULL << VIRTIO_NET_F_GUEST_TSO6) | \ 72 + (1ULL << VIRTIO_NET_F_GUEST_ECN) | \ 73 + (1ULL << VIRTIO_NET_F_GUEST_UFO) | \ 74 + (1ULL << VIRTIO_NET_F_GUEST_USO4) | \ 75 + (1ULL << VIRTIO_NET_F_GUEST_USO6) | \ 76 + (1ULL << VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_MAPPED) | \ 77 + (1ULL << VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_CSUM_MAPPED)) 91 78 92 79 struct virtnet_stat_desc { 93 80 char desc[ETH_GSTRING_LEN]; ··· 444 423 /* Work struct for delayed refilling if we run low on memory. */ 445 424 struct delayed_work refill; 446 425 426 + /* UDP tunnel support */ 427 + bool tx_tnl; 428 + 429 + bool rx_tnl; 430 + 431 + bool rx_tnl_csum; 432 + 447 433 /* Is delayed refill enabled? */ 448 434 bool refill_enabled; 449 435 ··· 510 482 struct virtio_net_hdr hdr; 511 483 struct virtio_net_hdr_mrg_rxbuf mrg_hdr; 512 484 struct virtio_net_hdr_v1_hash hash_v1_hdr; 485 + struct virtio_net_hdr_v1_hash_tunnel tnl_hdr; 513 486 }; 514 487 }; 515 488 ··· 2574 2545 if (dev->features & NETIF_F_RXHASH && vi->has_rss_hash_report) 2575 2546 virtio_skb_set_hash(&hdr->hash_v1_hdr, skb); 2576 2547 2577 - if (flags & VIRTIO_NET_HDR_F_DATA_VALID) 2578 - skb->ip_summed = CHECKSUM_UNNECESSARY; 2548 + hdr->hdr.flags = flags; 2549 + if (virtio_net_handle_csum_offload(skb, &hdr->hdr, vi->rx_tnl_csum)) { 2550 + net_warn_ratelimited("%s: bad csum: flags: %x, gso_type: %x rx_tnl_csum %d\n", 2551 + dev->name, hdr->hdr.flags, 2552 + hdr->hdr.gso_type, vi->rx_tnl_csum); 2553 + goto frame_err; 2554 + } 2579 2555 2580 - if (virtio_net_hdr_to_skb(skb, &hdr->hdr, 2581 - virtio_is_little_endian(vi->vdev))) { 2582 - net_warn_ratelimited("%s: bad gso: type: %u, size: %u\n", 2556 + if (virtio_net_hdr_tnl_to_skb(skb, &hdr->tnl_hdr, vi->rx_tnl, 2557 + vi->rx_tnl_csum, 2558 + virtio_is_little_endian(vi->vdev))) { 2559 + net_warn_ratelimited("%s: bad gso: type: %x, size: %u, flags %x tunnel %d tnl csum %d\n", 2583 2560 dev->name, hdr->hdr.gso_type, 2584 - hdr->hdr.gso_size); 2561 + hdr->hdr.gso_size, hdr->hdr.flags, 2562 + vi->rx_tnl, vi->rx_tnl_csum); 2585 2563 goto frame_err; 2586 2564 } 2587 2565 ··· 3300 3264 3301 3265 static int xmit_skb(struct send_queue *sq, struct sk_buff *skb, bool orphan) 3302 3266 { 3303 - struct virtio_net_hdr_mrg_rxbuf *hdr; 3304 3267 const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; 3305 3268 struct virtnet_info *vi = sq->vq->vdev->priv; 3269 + struct virtio_net_hdr_v1_hash_tunnel *hdr; 3306 3270 int num_sg; 3307 3271 unsigned hdr_len = vi->hdr_len; 3308 3272 bool can_push; ··· 3315 3279 /* Even if we can, don't push here yet as this would skew 3316 3280 * csum_start offset below. */ 3317 3281 if (can_push) 3318 - hdr = (struct virtio_net_hdr_mrg_rxbuf *)(skb->data - hdr_len); 3282 + hdr = (struct virtio_net_hdr_v1_hash_tunnel *)(skb->data - 3283 + hdr_len); 3319 3284 else 3320 - hdr = &skb_vnet_common_hdr(skb)->mrg_hdr; 3285 + hdr = &skb_vnet_common_hdr(skb)->tnl_hdr; 3321 3286 3322 - if (virtio_net_hdr_from_skb(skb, &hdr->hdr, 3323 - virtio_is_little_endian(vi->vdev), false, 3324 - 0)) 3287 + if (virtio_net_hdr_tnl_from_skb(skb, hdr, vi->tx_tnl, 3288 + virtio_is_little_endian(vi->vdev), 0)) 3325 3289 return -EPROTO; 3326 3290 3327 3291 if (vi->mergeable_rx_bufs) 3328 - hdr->num_buffers = 0; 3292 + hdr->hash_hdr.hdr.num_buffers = 0; 3329 3293 3330 3294 sg_init_table(sq->sg, skb_shinfo(skb)->nr_frags + (can_push ? 1 : 2)); 3331 3295 if (can_push) { ··· 6820 6784 if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_USO)) 6821 6785 dev->hw_features |= NETIF_F_GSO_UDP_L4; 6822 6786 6787 + if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO)) { 6788 + dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL; 6789 + dev->hw_enc_features = dev->hw_features; 6790 + } 6791 + if (dev->hw_features & NETIF_F_GSO_UDP_TUNNEL && 6792 + virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO_CSUM)) { 6793 + dev->hw_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM; 6794 + dev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL_CSUM; 6795 + } 6796 + 6823 6797 dev->features |= NETIF_F_GSO_ROBUST; 6824 6798 6825 6799 if (gso) 6826 - dev->features |= dev->hw_features & NETIF_F_ALL_TSO; 6800 + dev->features |= dev->hw_features; 6827 6801 /* (!csum && gso) case will be fixed by register_netdev() */ 6828 6802 } 6829 6803 ··· 6926 6880 dev->xdp_metadata_ops = &virtnet_xdp_metadata_ops; 6927 6881 } 6928 6882 6929 - if (vi->has_rss_hash_report) 6883 + if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO) || 6884 + virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO)) 6885 + vi->hdr_len = sizeof(struct virtio_net_hdr_v1_hash_tunnel); 6886 + else if (vi->has_rss_hash_report) 6930 6887 vi->hdr_len = sizeof(struct virtio_net_hdr_v1_hash); 6931 6888 else if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF) || 6932 6889 virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) 6933 6890 vi->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); 6934 6891 else 6935 6892 vi->hdr_len = sizeof(struct virtio_net_hdr); 6893 + 6894 + if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_CSUM)) 6895 + vi->rx_tnl_csum = true; 6896 + if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO)) 6897 + vi->rx_tnl = true; 6898 + if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO)) 6899 + vi->tx_tnl = true; 6936 6900 6937 6901 if (virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT) || 6938 6902 virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) ··· 7118 7062 netif_carrier_on(dev); 7119 7063 } 7120 7064 7121 - for (i = 0; i < ARRAY_SIZE(guest_offloads); i++) 7122 - if (virtio_has_feature(vi->vdev, guest_offloads[i])) 7065 + for (i = 0; i < ARRAY_SIZE(guest_offloads); i++) { 7066 + unsigned int fbit; 7067 + 7068 + fbit = virtio_offload_to_feature(guest_offloads[i]); 7069 + if (virtio_has_feature(vi->vdev, fbit)) 7123 7070 set_bit(guest_offloads[i], &vi->guest_offloads); 7071 + } 7124 7072 vi->guest_offloads_capable = vi->guest_offloads; 7125 7073 7126 7074 rtnl_unlock(); ··· 7254 7194 7255 7195 static unsigned int features[] = { 7256 7196 VIRTNET_FEATURES, 7197 + VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO, 7198 + VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_CSUM, 7199 + VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO, 7200 + VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO_CSUM, 7257 7201 }; 7258 7202 7259 7203 static unsigned int features_legacy[] = {
+75 -20
drivers/vhost/net.c
··· 69 69 70 70 #define VHOST_DMA_IS_DONE(len) ((__force u32)(len) >= (__force u32)VHOST_DMA_DONE_LEN) 71 71 72 - enum { 73 - VHOST_NET_FEATURES = VHOST_FEATURES | 74 - (1ULL << VHOST_NET_F_VIRTIO_NET_HDR) | 75 - (1ULL << VIRTIO_NET_F_MRG_RXBUF) | 76 - (1ULL << VIRTIO_F_ACCESS_PLATFORM) | 77 - (1ULL << VIRTIO_F_RING_RESET) 72 + static const u64 vhost_net_features[VIRTIO_FEATURES_DWORDS] = { 73 + VHOST_FEATURES | 74 + (1ULL << VHOST_NET_F_VIRTIO_NET_HDR) | 75 + (1ULL << VIRTIO_NET_F_MRG_RXBUF) | 76 + (1ULL << VIRTIO_F_ACCESS_PLATFORM) | 77 + (1ULL << VIRTIO_F_RING_RESET), 78 + VIRTIO_BIT(VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO) | 79 + VIRTIO_BIT(VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO), 78 80 }; 79 81 80 82 enum { ··· 1608 1606 return err; 1609 1607 } 1610 1608 1611 - static int vhost_net_set_features(struct vhost_net *n, u64 features) 1609 + static int vhost_net_set_features(struct vhost_net *n, const u64 *features) 1612 1610 { 1613 1611 size_t vhost_hlen, sock_hlen, hdr_len; 1614 1612 int i; 1615 1613 1616 - hdr_len = (features & ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | 1617 - (1ULL << VIRTIO_F_VERSION_1))) ? 1618 - sizeof(struct virtio_net_hdr_mrg_rxbuf) : 1619 - sizeof(struct virtio_net_hdr); 1620 - if (features & (1 << VHOST_NET_F_VIRTIO_NET_HDR)) { 1614 + hdr_len = virtio_features_test_bit(features, VIRTIO_NET_F_MRG_RXBUF) || 1615 + virtio_features_test_bit(features, VIRTIO_F_VERSION_1) ? 1616 + sizeof(struct virtio_net_hdr_mrg_rxbuf) : 1617 + sizeof(struct virtio_net_hdr); 1618 + 1619 + if (virtio_features_test_bit(features, 1620 + VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO) || 1621 + virtio_features_test_bit(features, 1622 + VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO)) 1623 + hdr_len = sizeof(struct virtio_net_hdr_v1_hash_tunnel); 1624 + 1625 + if (virtio_features_test_bit(features, VHOST_NET_F_VIRTIO_NET_HDR)) { 1621 1626 /* vhost provides vnet_hdr */ 1622 1627 vhost_hlen = hdr_len; 1623 1628 sock_hlen = 0; ··· 1634 1625 sock_hlen = hdr_len; 1635 1626 } 1636 1627 mutex_lock(&n->dev.mutex); 1637 - if ((features & (1 << VHOST_F_LOG_ALL)) && 1628 + if (virtio_features_test_bit(features, VHOST_F_LOG_ALL) && 1638 1629 !vhost_log_access_ok(&n->dev)) 1639 1630 goto out_unlock; 1640 1631 1641 - if ((features & (1ULL << VIRTIO_F_ACCESS_PLATFORM))) { 1632 + if (virtio_features_test_bit(features, VIRTIO_F_ACCESS_PLATFORM)) { 1642 1633 if (vhost_init_device_iotlb(&n->dev)) 1643 1634 goto out_unlock; 1644 1635 } 1645 1636 1646 1637 for (i = 0; i < VHOST_NET_VQ_MAX; ++i) { 1647 1638 mutex_lock(&n->vqs[i].vq.mutex); 1648 - n->vqs[i].vq.acked_features = features; 1639 + virtio_features_copy(n->vqs[i].vq.acked_features_array, 1640 + features); 1649 1641 n->vqs[i].vhost_hlen = vhost_hlen; 1650 1642 n->vqs[i].sock_hlen = sock_hlen; 1651 1643 mutex_unlock(&n->vqs[i].vq.mutex); ··· 1683 1673 static long vhost_net_ioctl(struct file *f, unsigned int ioctl, 1684 1674 unsigned long arg) 1685 1675 { 1676 + u64 all_features[VIRTIO_FEATURES_DWORDS]; 1686 1677 struct vhost_net *n = f->private_data; 1687 1678 void __user *argp = (void __user *)arg; 1688 1679 u64 __user *featurep = argp; 1689 1680 struct vhost_vring_file backend; 1690 - u64 features; 1691 - int r; 1681 + u64 features, count, copied; 1682 + int r, i; 1692 1683 1693 1684 switch (ioctl) { 1694 1685 case VHOST_NET_SET_BACKEND: ··· 1697 1686 return -EFAULT; 1698 1687 return vhost_net_set_backend(n, backend.index, backend.fd); 1699 1688 case VHOST_GET_FEATURES: 1700 - features = VHOST_NET_FEATURES; 1689 + features = vhost_net_features[0]; 1701 1690 if (copy_to_user(featurep, &features, sizeof features)) 1702 1691 return -EFAULT; 1703 1692 return 0; 1704 1693 case VHOST_SET_FEATURES: 1705 1694 if (copy_from_user(&features, featurep, sizeof features)) 1706 1695 return -EFAULT; 1707 - if (features & ~VHOST_NET_FEATURES) 1696 + if (features & ~vhost_net_features[0]) 1708 1697 return -EOPNOTSUPP; 1709 - return vhost_net_set_features(n, features); 1698 + 1699 + virtio_features_from_u64(all_features, features); 1700 + return vhost_net_set_features(n, all_features); 1701 + case VHOST_GET_FEATURES_ARRAY: 1702 + if (copy_from_user(&count, featurep, sizeof(count))) 1703 + return -EFAULT; 1704 + 1705 + /* Copy the net features, up to the user-provided buffer size */ 1706 + argp += sizeof(u64); 1707 + copied = min(count, VIRTIO_FEATURES_DWORDS); 1708 + if (copy_to_user(argp, vhost_net_features, 1709 + copied * sizeof(u64))) 1710 + return -EFAULT; 1711 + 1712 + /* Zero the trailing space provided by user-space, if any */ 1713 + if (clear_user(argp, size_mul(count - copied, sizeof(u64)))) 1714 + return -EFAULT; 1715 + return 0; 1716 + case VHOST_SET_FEATURES_ARRAY: 1717 + if (copy_from_user(&count, featurep, sizeof(count))) 1718 + return -EFAULT; 1719 + 1720 + virtio_features_zero(all_features); 1721 + argp += sizeof(u64); 1722 + copied = min(count, VIRTIO_FEATURES_DWORDS); 1723 + if (copy_from_user(all_features, argp, copied * sizeof(u64))) 1724 + return -EFAULT; 1725 + 1726 + /* 1727 + * Any feature specified by user-space above 1728 + * VIRTIO_FEATURES_MAX is not supported by definition. 1729 + */ 1730 + for (i = copied; i < count; ++i) { 1731 + if (copy_from_user(&features, featurep + 1 + i, 1732 + sizeof(features))) 1733 + return -EFAULT; 1734 + if (features) 1735 + return -EOPNOTSUPP; 1736 + } 1737 + 1738 + for (i = 0; i < VIRTIO_FEATURES_DWORDS; i++) 1739 + if (all_features[i] & ~vhost_net_features[i]) 1740 + return -EOPNOTSUPP; 1741 + 1742 + return vhost_net_set_features(n, all_features); 1710 1743 case VHOST_GET_BACKEND_FEATURES: 1711 1744 features = VHOST_NET_BACKEND_FEATURES; 1712 1745 if (copy_to_user(featurep, &features, sizeof(features)))
+1 -1
drivers/vhost/vhost.c
··· 372 372 vq->log_used = false; 373 373 vq->log_addr = -1ull; 374 374 vq->private_data = NULL; 375 - vq->acked_features = 0; 375 + virtio_features_zero(vq->acked_features_array); 376 376 vq->acked_backend_features = 0; 377 377 vq->log_base = NULL; 378 378 vq->error_ctx = NULL;
+2 -2
drivers/vhost/vhost.h
··· 133 133 struct vhost_iotlb *umem; 134 134 struct vhost_iotlb *iotlb; 135 135 void *private_data; 136 - u64 acked_features; 136 + VIRTIO_DECLARE_FEATURES(acked_features); 137 137 u64 acked_backend_features; 138 138 /* Log write descriptors */ 139 139 void __user *log_base; ··· 291 291 292 292 static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit) 293 293 { 294 - return vq->acked_features & (1ULL << bit); 294 + return virtio_features_test_bit(vq->acked_features_array, bit); 295 295 } 296 296 297 297 static inline bool vhost_backend_has_feature(struct vhost_virtqueue *vq, int bit)
+26 -17
drivers/virtio/virtio.c
··· 53 53 54 54 /* We actually represent this as a bitstring, as it could be 55 55 * arbitrary length in future. */ 56 - for (i = 0; i < sizeof(dev->features)*8; i++) 56 + for (i = 0; i < VIRTIO_FEATURES_MAX; i++) 57 57 len += sysfs_emit_at(buf, len, "%c", 58 58 __virtio_test_bit(dev, i) ? '1' : '0'); 59 59 len += sysfs_emit_at(buf, len, "\n"); ··· 272 272 int err, i; 273 273 struct virtio_device *dev = dev_to_virtio(_d); 274 274 struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); 275 - u64 device_features; 276 - u64 driver_features; 275 + u64 device_features[VIRTIO_FEATURES_DWORDS]; 276 + u64 driver_features[VIRTIO_FEATURES_DWORDS]; 277 277 u64 driver_features_legacy; 278 278 279 279 /* We have a driver! */ 280 280 virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER); 281 281 282 282 /* Figure out what features the device supports. */ 283 - device_features = dev->config->get_features(dev); 283 + virtio_get_features(dev, device_features); 284 284 285 285 /* Figure out what features the driver supports. */ 286 - driver_features = 0; 286 + virtio_features_zero(driver_features); 287 287 for (i = 0; i < drv->feature_table_size; i++) { 288 288 unsigned int f = drv->feature_table[i]; 289 - BUG_ON(f >= 64); 290 - driver_features |= (1ULL << f); 289 + if (!WARN_ON_ONCE(f >= VIRTIO_FEATURES_MAX)) 290 + virtio_features_set_bit(driver_features, f); 291 291 } 292 292 293 293 /* Some drivers have a separate feature table for virtio v1.0 */ ··· 295 295 driver_features_legacy = 0; 296 296 for (i = 0; i < drv->feature_table_size_legacy; i++) { 297 297 unsigned int f = drv->feature_table_legacy[i]; 298 - BUG_ON(f >= 64); 299 - driver_features_legacy |= (1ULL << f); 298 + if (!WARN_ON_ONCE(f >= 64)) 299 + driver_features_legacy |= (1ULL << f); 300 300 } 301 301 } else { 302 - driver_features_legacy = driver_features; 302 + driver_features_legacy = driver_features[0]; 303 303 } 304 304 305 - if (device_features & (1ULL << VIRTIO_F_VERSION_1)) 306 - dev->features = driver_features & device_features; 307 - else 308 - dev->features = driver_features_legacy & device_features; 305 + if (virtio_features_test_bit(device_features, VIRTIO_F_VERSION_1)) { 306 + for (i = 0; i < VIRTIO_FEATURES_DWORDS; ++i) 307 + dev->features_array[i] = driver_features[i] & 308 + device_features[i]; 309 + } else { 310 + virtio_features_from_u64(dev->features_array, 311 + driver_features_legacy & 312 + device_features[0]); 313 + } 309 314 310 315 /* When debugging, user may filter some features by hand. */ 311 316 virtio_debug_device_filter_features(dev); 312 317 313 318 /* Transport features always preserved to pass to finalize_features. */ 314 319 for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) 315 - if (device_features & (1ULL << i)) 320 + if (virtio_features_test_bit(device_features, i)) 316 321 __virtio_set_bit(dev, i); 317 322 318 323 err = dev->config->finalize_features(dev); ··· 325 320 goto err; 326 321 327 322 if (drv->validate) { 328 - u64 features = dev->features; 323 + u64 features[VIRTIO_FEATURES_DWORDS]; 329 324 325 + virtio_features_copy(features, dev->features_array); 330 326 err = drv->validate(dev); 331 327 if (err) 332 328 goto err; 333 329 334 330 /* Did validation change any features? Then write them again. */ 335 - if (features != dev->features) { 331 + if (!virtio_features_equal(features, dev->features_array)) { 336 332 err = dev->config->finalize_features(dev); 337 333 if (err) 338 334 goto err; ··· 707 701 708 702 static int virtio_init(void) 709 703 { 704 + BUILD_BUG_ON(offsetof(struct virtio_device, features) != 705 + offsetof(struct virtio_device, features_array[0])); 706 + 710 707 if (bus_register(&virtio_bus) != 0) 711 708 panic("virtio bus registration failed"); 712 709 virtio_debug_init();
+15 -12
drivers/virtio/virtio_debug.c
··· 8 8 9 9 static int virtio_debug_device_features_show(struct seq_file *s, void *data) 10 10 { 11 + u64 device_features[VIRTIO_FEATURES_DWORDS]; 11 12 struct virtio_device *dev = s->private; 12 - u64 device_features; 13 13 unsigned int i; 14 14 15 - device_features = dev->config->get_features(dev); 16 - for (i = 0; i < BITS_PER_LONG_LONG; i++) { 17 - if (device_features & (1ULL << i)) 15 + virtio_get_features(dev, device_features); 16 + for (i = 0; i < VIRTIO_FEATURES_MAX; i++) { 17 + if (virtio_features_test_bit(device_features, i)) 18 18 seq_printf(s, "%u\n", i); 19 19 } 20 20 return 0; ··· 26 26 struct virtio_device *dev = s->private; 27 27 unsigned int i; 28 28 29 - for (i = 0; i < BITS_PER_LONG_LONG; i++) { 30 - if (dev->debugfs_filter_features & (1ULL << i)) 29 + for (i = 0; i < VIRTIO_FEATURES_MAX; i++) { 30 + if (virtio_features_test_bit(dev->debugfs_filter_features, i)) 31 31 seq_printf(s, "%u\n", i); 32 32 } 33 33 return 0; ··· 39 39 struct virtio_device *dev = data; 40 40 41 41 if (val == 1) 42 - dev->debugfs_filter_features = 0; 42 + virtio_features_zero(dev->debugfs_filter_features); 43 43 return 0; 44 44 } 45 45 ··· 50 50 { 51 51 struct virtio_device *dev = data; 52 52 53 - if (val >= BITS_PER_LONG_LONG) 53 + if (val >= VIRTIO_FEATURES_MAX) 54 54 return -EINVAL; 55 - dev->debugfs_filter_features |= BIT_ULL_MASK(val); 55 + 56 + virtio_features_set_bit(dev->debugfs_filter_features, val); 56 57 return 0; 57 58 } 58 59 ··· 64 63 { 65 64 struct virtio_device *dev = data; 66 65 67 - if (val >= BITS_PER_LONG_LONG) 66 + if (val >= VIRTIO_FEATURES_MAX) 68 67 return -EINVAL; 69 - dev->debugfs_filter_features &= ~BIT_ULL_MASK(val); 68 + 69 + virtio_features_clear_bit(dev->debugfs_filter_features, val); 70 70 return 0; 71 71 } 72 72 ··· 93 91 94 92 void virtio_debug_device_filter_features(struct virtio_device *dev) 95 93 { 96 - dev->features &= ~dev->debugfs_filter_features; 94 + virtio_features_andnot(dev->features_array, dev->features_array, 95 + dev->debugfs_filter_features); 97 96 } 98 97 EXPORT_SYMBOL_GPL(virtio_debug_device_filter_features); 99 98
+5 -5
drivers/virtio/virtio_pci_modern.c
··· 22 22 23 23 #define VIRTIO_AVQ_SGS_MAX 4 24 24 25 - static u64 vp_get_features(struct virtio_device *vdev) 25 + static void vp_get_features(struct virtio_device *vdev, u64 *features) 26 26 { 27 27 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 28 28 29 - return vp_modern_get_features(&vp_dev->mdev); 29 + vp_modern_get_extended_features(&vp_dev->mdev, features); 30 30 } 31 31 32 32 static int vp_avq_index(struct virtio_device *vdev, u16 *index, u16 *num) ··· 437 437 if (vp_check_common_size(vdev)) 438 438 return -EINVAL; 439 439 440 - vp_modern_set_features(&vp_dev->mdev, vdev->features); 440 + vp_modern_set_extended_features(&vp_dev->mdev, vdev->features_array); 441 441 442 442 return 0; 443 443 } ··· 1234 1234 .find_vqs = vp_modern_find_vqs, 1235 1235 .del_vqs = vp_del_vqs, 1236 1236 .synchronize_cbs = vp_synchronize_vectors, 1237 - .get_features = vp_get_features, 1237 + .get_extended_features = vp_get_features, 1238 1238 .finalize_features = vp_finalize_features, 1239 1239 .bus_name = vp_bus_name, 1240 1240 .set_vq_affinity = vp_set_vq_affinity, ··· 1254 1254 .find_vqs = vp_modern_find_vqs, 1255 1255 .del_vqs = vp_del_vqs, 1256 1256 .synchronize_cbs = vp_synchronize_vectors, 1257 - .get_features = vp_get_features, 1257 + .get_extended_features = vp_get_features, 1258 1258 .finalize_features = vp_finalize_features, 1259 1259 .bus_name = vp_bus_name, 1260 1260 .set_vq_affinity = vp_set_vq_affinity,
+40 -29
drivers/virtio/virtio_pci_modern_dev.c
··· 388 388 EXPORT_SYMBOL_GPL(vp_modern_remove); 389 389 390 390 /* 391 - * vp_modern_get_features - get features from device 391 + * vp_modern_get_extended_features - get features from device 392 392 * @mdev: the modern virtio-pci device 393 + * @features: the features array to be filled 393 394 * 394 - * Returns the features read from the device 395 + * Fill the specified features array with the features read from the device 395 396 */ 396 - u64 vp_modern_get_features(struct virtio_pci_modern_device *mdev) 397 + void vp_modern_get_extended_features(struct virtio_pci_modern_device *mdev, 398 + u64 *features) 397 399 { 398 400 struct virtio_pci_common_cfg __iomem *cfg = mdev->common; 401 + int i; 399 402 400 - u64 features; 403 + virtio_features_zero(features); 404 + for (i = 0; i < VIRTIO_FEATURES_WORDS; i++) { 405 + u64 cur; 401 406 402 - vp_iowrite32(0, &cfg->device_feature_select); 403 - features = vp_ioread32(&cfg->device_feature); 404 - vp_iowrite32(1, &cfg->device_feature_select); 405 - features |= ((u64)vp_ioread32(&cfg->device_feature) << 32); 406 - 407 - return features; 407 + vp_iowrite32(i, &cfg->device_feature_select); 408 + cur = vp_ioread32(&cfg->device_feature); 409 + features[i >> 1] |= cur << (32 * (i & 1)); 410 + } 408 411 } 409 - EXPORT_SYMBOL_GPL(vp_modern_get_features); 412 + EXPORT_SYMBOL_GPL(vp_modern_get_extended_features); 410 413 411 414 /* 412 415 * vp_modern_get_driver_features - get driver features from device 413 416 * @mdev: the modern virtio-pci device 417 + * @features: the features array to be filled 414 418 * 415 - * Returns the driver features read from the device 419 + * Fill the specified features array with the driver features read from the 420 + * device 416 421 */ 417 - u64 vp_modern_get_driver_features(struct virtio_pci_modern_device *mdev) 422 + void 423 + vp_modern_get_driver_extended_features(struct virtio_pci_modern_device *mdev, 424 + u64 *features) 418 425 { 419 426 struct virtio_pci_common_cfg __iomem *cfg = mdev->common; 427 + int i; 420 428 421 - u64 features; 429 + virtio_features_zero(features); 430 + for (i = 0; i < VIRTIO_FEATURES_WORDS; i++) { 431 + u64 cur; 422 432 423 - vp_iowrite32(0, &cfg->guest_feature_select); 424 - features = vp_ioread32(&cfg->guest_feature); 425 - vp_iowrite32(1, &cfg->guest_feature_select); 426 - features |= ((u64)vp_ioread32(&cfg->guest_feature) << 32); 427 - 428 - return features; 433 + vp_iowrite32(i, &cfg->guest_feature_select); 434 + cur = vp_ioread32(&cfg->guest_feature); 435 + features[i >> 1] |= cur << (32 * (i & 1)); 436 + } 429 437 } 430 - EXPORT_SYMBOL_GPL(vp_modern_get_driver_features); 438 + EXPORT_SYMBOL_GPL(vp_modern_get_driver_extended_features); 431 439 432 440 /* 433 - * vp_modern_set_features - set features to device 441 + * vp_modern_set_extended_features - set features to device 434 442 * @mdev: the modern virtio-pci device 435 443 * @features: the features set to device 436 444 */ 437 - void vp_modern_set_features(struct virtio_pci_modern_device *mdev, 438 - u64 features) 445 + void vp_modern_set_extended_features(struct virtio_pci_modern_device *mdev, 446 + const u64 *features) 439 447 { 440 448 struct virtio_pci_common_cfg __iomem *cfg = mdev->common; 449 + int i; 441 450 442 - vp_iowrite32(0, &cfg->guest_feature_select); 443 - vp_iowrite32((u32)features, &cfg->guest_feature); 444 - vp_iowrite32(1, &cfg->guest_feature_select); 445 - vp_iowrite32(features >> 32, &cfg->guest_feature); 451 + for (i = 0; i < VIRTIO_FEATURES_WORDS; i++) { 452 + u32 cur = features[i >> 1] >> (32 * (i & 1)); 453 + 454 + vp_iowrite32(i, &cfg->guest_feature_select); 455 + vp_iowrite32(cur, &cfg->guest_feature); 456 + } 446 457 } 447 - EXPORT_SYMBOL_GPL(vp_modern_set_features); 458 + EXPORT_SYMBOL_GPL(vp_modern_set_extended_features); 448 459 449 460 /* 450 461 * vp_modern_generation - get the device genreation
+6 -3
include/linux/virtio.h
··· 11 11 #include <linux/gfp.h> 12 12 #include <linux/dma-mapping.h> 13 13 #include <linux/completion.h> 14 + #include <linux/virtio_features.h> 14 15 15 16 /** 16 17 * struct virtqueue - a queue to register buffers for sending or receiving. ··· 142 141 * @config: the configuration ops for this device. 143 142 * @vringh_config: configuration ops for host vrings. 144 143 * @vqs: the list of virtqueues for this device. 145 - * @features: the features supported by both driver and device. 144 + * @features: the 64 lower features supported by both driver and device. 145 + * @features_array: the full features space supported by both driver and 146 + * device. 146 147 * @priv: private pointer for the driver's use. 147 148 * @debugfs_dir: debugfs directory entry. 148 149 * @debugfs_filter_features: features to be filtered set by debugfs. ··· 162 159 const struct virtio_config_ops *config; 163 160 const struct vringh_config_ops *vringh_config; 164 161 struct list_head vqs; 165 - u64 features; 162 + VIRTIO_DECLARE_FEATURES(features); 166 163 void *priv; 167 164 #ifdef CONFIG_VIRTIO_DEBUG 168 165 struct dentry *debugfs_dir; 169 - u64 debugfs_filter_features; 166 + u64 debugfs_filter_features[VIRTIO_FEATURES_DWORDS]; 170 167 #endif 171 168 }; 172 169
+21 -22
include/linux/virtio_config.h
··· 77 77 * vdev: the virtio_device 78 78 * @get_features: get the array of feature bits for this device. 79 79 * vdev: the virtio_device 80 - * Returns the first 64 feature bits (all we currently need). 80 + * Returns the first 64 feature bits. 81 + * @get_extended_features: 82 + * vdev: the virtio_device 83 + * Returns the first VIRTIO_FEATURES_MAX feature bits (all we currently 84 + * need). 81 85 * @finalize_features: confirm what device features we'll be using. 82 86 * vdev: the virtio_device 83 87 * This sends the driver feature bits to the device: it can change ··· 125 121 void (*del_vqs)(struct virtio_device *); 126 122 void (*synchronize_cbs)(struct virtio_device *); 127 123 u64 (*get_features)(struct virtio_device *vdev); 124 + void (*get_extended_features)(struct virtio_device *vdev, 125 + u64 *features); 128 126 int (*finalize_features)(struct virtio_device *vdev); 129 127 const char *(*bus_name)(struct virtio_device *vdev); 130 128 int (*set_vq_affinity)(struct virtqueue *vq, ··· 153 147 static inline bool __virtio_test_bit(const struct virtio_device *vdev, 154 148 unsigned int fbit) 155 149 { 156 - /* Did you forget to fix assumptions on max features? */ 157 - if (__builtin_constant_p(fbit)) 158 - BUILD_BUG_ON(fbit >= 64); 159 - else 160 - BUG_ON(fbit >= 64); 161 - 162 - return vdev->features & BIT_ULL(fbit); 150 + return virtio_features_test_bit(vdev->features_array, fbit); 163 151 } 164 152 165 153 /** ··· 164 164 static inline void __virtio_set_bit(struct virtio_device *vdev, 165 165 unsigned int fbit) 166 166 { 167 - /* Did you forget to fix assumptions on max features? */ 168 - if (__builtin_constant_p(fbit)) 169 - BUILD_BUG_ON(fbit >= 64); 170 - else 171 - BUG_ON(fbit >= 64); 172 - 173 - vdev->features |= BIT_ULL(fbit); 167 + virtio_features_set_bit(vdev->features_array, fbit); 174 168 } 175 169 176 170 /** ··· 175 181 static inline void __virtio_clear_bit(struct virtio_device *vdev, 176 182 unsigned int fbit) 177 183 { 178 - /* Did you forget to fix assumptions on max features? */ 179 - if (__builtin_constant_p(fbit)) 180 - BUILD_BUG_ON(fbit >= 64); 181 - else 182 - BUG_ON(fbit >= 64); 183 - 184 - vdev->features &= ~BIT_ULL(fbit); 184 + virtio_features_clear_bit(vdev->features_array, fbit); 185 185 } 186 186 187 187 /** ··· 190 202 virtio_check_driver_offered_feature(vdev, fbit); 191 203 192 204 return __virtio_test_bit(vdev, fbit); 205 + } 206 + 207 + static inline void virtio_get_features(struct virtio_device *vdev, 208 + u64 *features) 209 + { 210 + if (vdev->config->get_extended_features) { 211 + vdev->config->get_extended_features(vdev, features); 212 + return; 213 + } 214 + 215 + virtio_features_from_u64(features, vdev->config->get_features(vdev)); 193 216 } 194 217 195 218 /**
+88
include/linux/virtio_features.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef _LINUX_VIRTIO_FEATURES_H 3 + #define _LINUX_VIRTIO_FEATURES_H 4 + 5 + #include <linux/bits.h> 6 + 7 + #define VIRTIO_FEATURES_DWORDS 2 8 + #define VIRTIO_FEATURES_MAX (VIRTIO_FEATURES_DWORDS * 64) 9 + #define VIRTIO_FEATURES_WORDS (VIRTIO_FEATURES_DWORDS * 2) 10 + #define VIRTIO_BIT(b) BIT_ULL((b) & 0x3f) 11 + #define VIRTIO_DWORD(b) ((b) >> 6) 12 + #define VIRTIO_DECLARE_FEATURES(name) \ 13 + union { \ 14 + u64 name; \ 15 + u64 name##_array[VIRTIO_FEATURES_DWORDS];\ 16 + } 17 + 18 + static inline bool virtio_features_chk_bit(unsigned int bit) 19 + { 20 + if (__builtin_constant_p(bit)) { 21 + /* 22 + * Don't care returning the correct value: the build 23 + * will fail before any bad features access 24 + */ 25 + BUILD_BUG_ON(bit >= VIRTIO_FEATURES_MAX); 26 + } else { 27 + if (WARN_ON_ONCE(bit >= VIRTIO_FEATURES_MAX)) 28 + return false; 29 + } 30 + return true; 31 + } 32 + 33 + static inline bool virtio_features_test_bit(const u64 *features, 34 + unsigned int bit) 35 + { 36 + return virtio_features_chk_bit(bit) && 37 + !!(features[VIRTIO_DWORD(bit)] & VIRTIO_BIT(bit)); 38 + } 39 + 40 + static inline void virtio_features_set_bit(u64 *features, 41 + unsigned int bit) 42 + { 43 + if (virtio_features_chk_bit(bit)) 44 + features[VIRTIO_DWORD(bit)] |= VIRTIO_BIT(bit); 45 + } 46 + 47 + static inline void virtio_features_clear_bit(u64 *features, 48 + unsigned int bit) 49 + { 50 + if (virtio_features_chk_bit(bit)) 51 + features[VIRTIO_DWORD(bit)] &= ~VIRTIO_BIT(bit); 52 + } 53 + 54 + static inline void virtio_features_zero(u64 *features) 55 + { 56 + memset(features, 0, sizeof(features[0]) * VIRTIO_FEATURES_DWORDS); 57 + } 58 + 59 + static inline void virtio_features_from_u64(u64 *features, u64 from) 60 + { 61 + virtio_features_zero(features); 62 + features[0] = from; 63 + } 64 + 65 + static inline bool virtio_features_equal(const u64 *f1, const u64 *f2) 66 + { 67 + int i; 68 + 69 + for (i = 0; i < VIRTIO_FEATURES_DWORDS; ++i) 70 + if (f1[i] != f2[i]) 71 + return false; 72 + return true; 73 + } 74 + 75 + static inline void virtio_features_copy(u64 *to, const u64 *from) 76 + { 77 + memcpy(to, from, sizeof(to[0]) * VIRTIO_FEATURES_DWORDS); 78 + } 79 + 80 + static inline void virtio_features_andnot(u64 *to, const u64 *f1, const u64 *f2) 81 + { 82 + int i; 83 + 84 + for (i = 0; i < VIRTIO_FEATURES_DWORDS; i++) 85 + to[i] = f1[i] & ~f2[i]; 86 + } 87 + 88 + #endif
+189 -8
include/linux/virtio_net.h
··· 47 47 return 0; 48 48 } 49 49 50 - static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, 51 - const struct virtio_net_hdr *hdr, 52 - bool little_endian) 50 + static inline int __virtio_net_hdr_to_skb(struct sk_buff *skb, 51 + const struct virtio_net_hdr *hdr, 52 + bool little_endian, u8 hdr_gso_type) 53 53 { 54 54 unsigned int nh_min_len = sizeof(struct iphdr); 55 55 unsigned int gso_type = 0; ··· 57 57 unsigned int p_off = 0; 58 58 unsigned int ip_proto; 59 59 60 - if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { 61 - switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { 60 + if (hdr_gso_type != VIRTIO_NET_HDR_GSO_NONE) { 61 + switch (hdr_gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { 62 62 case VIRTIO_NET_HDR_GSO_TCPV4: 63 63 gso_type = SKB_GSO_TCPV4; 64 64 ip_proto = IPPROTO_TCP; ··· 84 84 return -EINVAL; 85 85 } 86 86 87 - if (hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN) 87 + if (hdr_gso_type & VIRTIO_NET_HDR_GSO_ECN) 88 88 gso_type |= SKB_GSO_TCP_ECN; 89 89 90 90 if (hdr->gso_size == 0) ··· 122 122 123 123 if (!protocol) 124 124 virtio_net_hdr_set_proto(skb, hdr); 125 - else if (!virtio_net_hdr_match_proto(protocol, hdr->gso_type)) 125 + else if (!virtio_net_hdr_match_proto(protocol, 126 + hdr_gso_type)) 126 127 return -EINVAL; 127 128 else 128 129 skb->protocol = protocol; ··· 154 153 } 155 154 } 156 155 157 - if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { 156 + if (hdr_gso_type != VIRTIO_NET_HDR_GSO_NONE) { 158 157 u16 gso_size = __virtio16_to_cpu(little_endian, hdr->gso_size); 159 158 unsigned int nh_off = p_off; 160 159 struct skb_shared_info *shinfo = skb_shinfo(skb); ··· 200 199 return 0; 201 200 } 202 201 202 + static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, 203 + const struct virtio_net_hdr *hdr, 204 + bool little_endian) 205 + { 206 + return __virtio_net_hdr_to_skb(skb, hdr, little_endian, hdr->gso_type); 207 + } 208 + 203 209 static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, 204 210 struct virtio_net_hdr *hdr, 205 211 bool little_endian, ··· 247 239 hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID; 248 240 } /* else everything is zero */ 249 241 242 + return 0; 243 + } 244 + 245 + static inline unsigned int virtio_l3min(bool is_ipv6) 246 + { 247 + return is_ipv6 ? sizeof(struct ipv6hdr) : sizeof(struct iphdr); 248 + } 249 + 250 + static inline int 251 + virtio_net_hdr_tnl_to_skb(struct sk_buff *skb, 252 + const struct virtio_net_hdr_v1_hash_tunnel *vhdr, 253 + bool tnl_hdr_negotiated, 254 + bool tnl_csum_negotiated, 255 + bool little_endian) 256 + { 257 + const struct virtio_net_hdr *hdr = (const struct virtio_net_hdr *)vhdr; 258 + unsigned int inner_nh, outer_th, inner_th; 259 + unsigned int inner_l3min, outer_l3min; 260 + u8 gso_inner_type, gso_tunnel_type; 261 + bool outer_isv6, inner_isv6; 262 + int ret; 263 + 264 + gso_tunnel_type = hdr->gso_type & VIRTIO_NET_HDR_GSO_UDP_TUNNEL; 265 + if (!gso_tunnel_type) 266 + return virtio_net_hdr_to_skb(skb, hdr, little_endian); 267 + 268 + /* Tunnel not supported/negotiated, but the hdr asks for it. */ 269 + if (!tnl_hdr_negotiated) 270 + return -EINVAL; 271 + 272 + /* Either ipv4 or ipv6. */ 273 + if (gso_tunnel_type == VIRTIO_NET_HDR_GSO_UDP_TUNNEL) 274 + return -EINVAL; 275 + 276 + /* The UDP tunnel must carry a GSO packet, but no UFO. */ 277 + gso_inner_type = hdr->gso_type & ~(VIRTIO_NET_HDR_GSO_ECN | 278 + VIRTIO_NET_HDR_GSO_UDP_TUNNEL); 279 + if (!gso_inner_type || gso_inner_type == VIRTIO_NET_HDR_GSO_UDP) 280 + return -EINVAL; 281 + 282 + /* Rely on csum being present. */ 283 + if (!(hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM)) 284 + return -EINVAL; 285 + 286 + /* Validate offsets. */ 287 + outer_isv6 = gso_tunnel_type & VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6; 288 + inner_isv6 = gso_inner_type == VIRTIO_NET_HDR_GSO_TCPV6; 289 + inner_l3min = virtio_l3min(inner_isv6); 290 + outer_l3min = ETH_HLEN + virtio_l3min(outer_isv6); 291 + 292 + inner_th = __virtio16_to_cpu(little_endian, hdr->csum_start); 293 + inner_nh = le16_to_cpu(vhdr->inner_nh_offset); 294 + outer_th = le16_to_cpu(vhdr->outer_th_offset); 295 + if (outer_th < outer_l3min || 296 + inner_nh < outer_th + sizeof(struct udphdr) || 297 + inner_th < inner_nh + inner_l3min) 298 + return -EINVAL; 299 + 300 + /* Let the basic parsing deal with plain GSO features. */ 301 + ret = __virtio_net_hdr_to_skb(skb, hdr, true, 302 + hdr->gso_type & ~gso_tunnel_type); 303 + if (ret) 304 + return ret; 305 + 306 + /* In case of USO, the inner protocol is still unknown and 307 + * `inner_isv6` is just a guess, additional parsing is needed. 308 + * The previous validation ensures that accessing an ipv4 inner 309 + * network header is safe. 310 + */ 311 + if (gso_inner_type == VIRTIO_NET_HDR_GSO_UDP_L4) { 312 + struct iphdr *iphdr = (struct iphdr *)(skb->data + inner_nh); 313 + 314 + inner_isv6 = iphdr->version == 6; 315 + inner_l3min = virtio_l3min(inner_isv6); 316 + if (inner_th < inner_nh + inner_l3min) 317 + return -EINVAL; 318 + } 319 + 320 + skb_set_inner_protocol(skb, inner_isv6 ? htons(ETH_P_IPV6) : 321 + htons(ETH_P_IP)); 322 + if (hdr->flags & VIRTIO_NET_HDR_F_UDP_TUNNEL_CSUM) { 323 + if (!tnl_csum_negotiated) 324 + return -EINVAL; 325 + 326 + skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL_CSUM; 327 + } else { 328 + skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; 329 + } 330 + 331 + skb->inner_transport_header = inner_th + skb_headroom(skb); 332 + skb->inner_network_header = inner_nh + skb_headroom(skb); 333 + skb->inner_mac_header = inner_nh + skb_headroom(skb); 334 + skb->transport_header = outer_th + skb_headroom(skb); 335 + skb->encapsulation = 1; 336 + return 0; 337 + } 338 + 339 + /* Checksum-related fields validation for the driver */ 340 + static inline int virtio_net_handle_csum_offload(struct sk_buff *skb, 341 + struct virtio_net_hdr *hdr, 342 + bool tnl_csum_negotiated) 343 + { 344 + if (!(hdr->gso_type & VIRTIO_NET_HDR_GSO_UDP_TUNNEL)) { 345 + if (!(hdr->flags & VIRTIO_NET_HDR_F_DATA_VALID)) 346 + return 0; 347 + 348 + skb->ip_summed = CHECKSUM_UNNECESSARY; 349 + if (!(hdr->flags & VIRTIO_NET_HDR_F_UDP_TUNNEL_CSUM)) 350 + return 0; 351 + 352 + /* tunnel csum packets are invalid when the related 353 + * feature has not been negotiated 354 + */ 355 + if (!tnl_csum_negotiated) 356 + return -EINVAL; 357 + skb->csum_level = 1; 358 + return 0; 359 + } 360 + 361 + /* DATA_VALID is mutually exclusive with NEEDS_CSUM, and GSO 362 + * over UDP tunnel requires the latter 363 + */ 364 + if (hdr->flags & VIRTIO_NET_HDR_F_DATA_VALID) 365 + return -EINVAL; 366 + return 0; 367 + } 368 + 369 + /* 370 + * vlan_hlen always refers to the outermost MAC header. That also 371 + * means it refers to the only MAC header, if the packet does not carry 372 + * any encapsulation. 373 + */ 374 + static inline int 375 + virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb, 376 + struct virtio_net_hdr_v1_hash_tunnel *vhdr, 377 + bool tnl_hdr_negotiated, 378 + bool little_endian, 379 + int vlan_hlen) 380 + { 381 + struct virtio_net_hdr *hdr = (struct virtio_net_hdr *)vhdr; 382 + unsigned int inner_nh, outer_th; 383 + int tnl_gso_type; 384 + int ret; 385 + 386 + tnl_gso_type = skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | 387 + SKB_GSO_UDP_TUNNEL_CSUM); 388 + if (!tnl_gso_type) 389 + return virtio_net_hdr_from_skb(skb, hdr, little_endian, false, 390 + vlan_hlen); 391 + 392 + /* Tunnel support not negotiated but skb ask for it. */ 393 + if (!tnl_hdr_negotiated) 394 + return -EINVAL; 395 + 396 + /* Let the basic parsing deal with plain GSO features. */ 397 + skb_shinfo(skb)->gso_type &= ~tnl_gso_type; 398 + ret = virtio_net_hdr_from_skb(skb, hdr, true, false, vlan_hlen); 399 + skb_shinfo(skb)->gso_type |= tnl_gso_type; 400 + if (ret) 401 + return ret; 402 + 403 + if (skb->protocol == htons(ETH_P_IPV6)) 404 + hdr->gso_type |= VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6; 405 + else 406 + hdr->gso_type |= VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV4; 407 + 408 + if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM) 409 + hdr->flags |= VIRTIO_NET_HDR_F_UDP_TUNNEL_CSUM; 410 + 411 + inner_nh = skb->inner_network_header - skb_headroom(skb); 412 + outer_th = skb->transport_header - skb_headroom(skb); 413 + vhdr->inner_nh_offset = cpu_to_le16(inner_nh); 414 + vhdr->outer_th_offset = cpu_to_le16(outer_th); 250 415 return 0; 251 416 } 252 417
+39 -4
include/linux/virtio_pci_modern.h
··· 3 3 #define _LINUX_VIRTIO_PCI_MODERN_H 4 4 5 5 #include <linux/pci.h> 6 + #include <linux/virtio_config.h> 6 7 #include <linux/virtio_pci.h> 7 8 8 9 /** ··· 96 95 vp_iowrite32(val >> 32, hi); 97 96 } 98 97 99 - u64 vp_modern_get_features(struct virtio_pci_modern_device *mdev); 100 - u64 vp_modern_get_driver_features(struct virtio_pci_modern_device *mdev); 101 - void vp_modern_set_features(struct virtio_pci_modern_device *mdev, 102 - u64 features); 98 + void 99 + vp_modern_get_driver_extended_features(struct virtio_pci_modern_device *mdev, 100 + u64 *features); 101 + void vp_modern_get_extended_features(struct virtio_pci_modern_device *mdev, 102 + u64 *features); 103 + void vp_modern_set_extended_features(struct virtio_pci_modern_device *mdev, 104 + const u64 *features); 105 + 106 + static inline u64 107 + vp_modern_get_features(struct virtio_pci_modern_device *mdev) 108 + { 109 + u64 features_array[VIRTIO_FEATURES_DWORDS]; 110 + 111 + vp_modern_get_extended_features(mdev, features_array); 112 + return features_array[0]; 113 + } 114 + 115 + static inline u64 116 + vp_modern_get_driver_features(struct virtio_pci_modern_device *mdev) 117 + { 118 + u64 features_array[VIRTIO_FEATURES_DWORDS]; 119 + int i; 120 + 121 + vp_modern_get_driver_extended_features(mdev, features_array); 122 + for (i = 1; i < VIRTIO_FEATURES_DWORDS; ++i) 123 + WARN_ON_ONCE(features_array[i]); 124 + return features_array[0]; 125 + } 126 + 127 + static inline void 128 + vp_modern_set_features(struct virtio_pci_modern_device *mdev, u64 features) 129 + { 130 + u64 features_array[VIRTIO_FEATURES_DWORDS]; 131 + 132 + virtio_features_from_u64(features_array, features); 133 + vp_modern_set_extended_features(mdev, features_array); 134 + } 135 + 103 136 u32 vp_modern_generation(struct virtio_pci_modern_device *mdev); 104 137 u8 vp_modern_get_status(struct virtio_pci_modern_device *mdev); 105 138 void vp_modern_set_status(struct virtio_pci_modern_device *mdev,
+9
include/uapi/linux/if_tun.h
··· 93 93 #define TUN_F_USO4 0x20 /* I can handle USO for IPv4 packets */ 94 94 #define TUN_F_USO6 0x40 /* I can handle USO for IPv6 packets */ 95 95 96 + /* I can handle TSO/USO for UDP tunneled packets */ 97 + #define TUN_F_UDP_TUNNEL_GSO 0x080 98 + 99 + /* 100 + * I can handle TSO/USO for UDP tunneled packets requiring csum offload for 101 + * the outer header 102 + */ 103 + #define TUN_F_UDP_TUNNEL_GSO_CSUM 0x100 104 + 96 105 /* Protocol info prepended to the packets (when IFF_NO_PI is not set) */ 97 106 #define TUN_PKT_STRIP 0x0001 98 107 struct tun_pi {
+7
include/uapi/linux/vhost.h
··· 235 235 */ 236 236 #define VHOST_VDPA_GET_VRING_SIZE _IOWR(VHOST_VIRTIO, 0x82, \ 237 237 struct vhost_vring_state) 238 + 239 + /* Extended features manipulation */ 240 + #define VHOST_GET_FEATURES_ARRAY _IOR(VHOST_VIRTIO, 0x83, \ 241 + struct vhost_features_array) 242 + #define VHOST_SET_FEATURES_ARRAY _IOW(VHOST_VIRTIO, 0x83, \ 243 + struct vhost_features_array) 244 + 238 245 #endif
+5
include/uapi/linux/vhost_types.h
··· 110 110 }; 111 111 }; 112 112 113 + struct vhost_features_array { 114 + __u64 count; /* number of entries present in features array */ 115 + __u64 features[] __counted_by(count); 116 + }; 117 + 113 118 struct vhost_memory_region { 114 119 __u64 guest_phys_addr; 115 120 __u64 memory_size; /* bytes */
+33
include/uapi/linux/virtio_net.h
··· 70 70 * with the same MAC. 71 71 */ 72 72 #define VIRTIO_NET_F_SPEED_DUPLEX 63 /* Device set linkspeed and duplex */ 73 + #define VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO 65 /* Driver can receive 74 + * GSO-over-UDP-tunnel packets 75 + */ 76 + #define VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_CSUM 66 /* Driver handles 77 + * GSO-over-UDP-tunnel 78 + * packets with partial csum 79 + * for the outer header 80 + */ 81 + #define VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO 67 /* Device can receive 82 + * GSO-over-UDP-tunnel packets 83 + */ 84 + #define VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO_CSUM 68 /* Device handles 85 + * GSO-over-UDP-tunnel 86 + * packets with partial csum 87 + * for the outer header 88 + */ 89 + 90 + /* Offloads bits corresponding to VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO{,_CSUM} 91 + * features 92 + */ 93 + #define VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_MAPPED 46 94 + #define VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_CSUM_MAPPED 47 73 95 74 96 #ifndef VIRTIO_NET_NO_LEGACY 75 97 #define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */ ··· 153 131 #define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /* Use csum_start, csum_offset */ 154 132 #define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */ 155 133 #define VIRTIO_NET_HDR_F_RSC_INFO 4 /* rsc info in csum_ fields */ 134 + #define VIRTIO_NET_HDR_F_UDP_TUNNEL_CSUM 8 /* UDP tunnel csum offload */ 156 135 __u8 flags; 157 136 #define VIRTIO_NET_HDR_GSO_NONE 0 /* Not a GSO frame */ 158 137 #define VIRTIO_NET_HDR_GSO_TCPV4 1 /* GSO frame, IPv4 TCP (TSO) */ 159 138 #define VIRTIO_NET_HDR_GSO_UDP 3 /* GSO frame, IPv4 UDP (UFO) */ 160 139 #define VIRTIO_NET_HDR_GSO_TCPV6 4 /* GSO frame, IPv6 TCP */ 161 140 #define VIRTIO_NET_HDR_GSO_UDP_L4 5 /* GSO frame, IPv4& IPv6 UDP (USO) */ 141 + #define VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV4 0x20 /* UDPv4 tunnel present */ 142 + #define VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6 0x40 /* UDPv6 tunnel present */ 143 + #define VIRTIO_NET_HDR_GSO_UDP_TUNNEL (VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV4 | \ 144 + VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6) 162 145 #define VIRTIO_NET_HDR_GSO_ECN 0x80 /* TCP has ECN set */ 163 146 __u8 gso_type; 164 147 __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ ··· 206 179 #define VIRTIO_NET_HASH_REPORT_UDPv6_EX 9 207 180 __le16 hash_report; 208 181 __le16 padding; 182 + }; 183 + 184 + struct virtio_net_hdr_v1_hash_tunnel { 185 + struct virtio_net_hdr_v1_hash hash_hdr; 186 + __le16 outer_th_offset; 187 + __le16 inner_nh_offset; 209 188 }; 210 189 211 190 #ifndef VIRTIO_NET_NO_LEGACY
+1
scripts/lib/kdoc/kdoc_parser.py
··· 666 666 (KernRe(r'(?:__)?DECLARE_FLEX_ARRAY\s*\(' + args_pattern + r',\s*' + args_pattern + r'\)', re.S), r'\1 \2[]'), 667 667 (KernRe(r'DEFINE_DMA_UNMAP_ADDR\s*\(' + args_pattern + r'\)', re.S), r'dma_addr_t \1'), 668 668 (KernRe(r'DEFINE_DMA_UNMAP_LEN\s*\(' + args_pattern + r'\)', re.S), r'__u32 \1'), 669 + (KernRe(r'VIRTIO_DECLARE_FEATURES\s*\(' + args_pattern + r'\)', re.S), r'u64 \1; u64 \1_array[VIRTIO_FEATURES_DWORDS]'), 669 670 ] 670 671 671 672 # Regexes here are guaranteed to have the end limiter matching