blob: cf8ab0f8af728eada8f567b7c9986f3723310835 [file] [log] [blame]
aliguorifbe78f42008-12-17 19:13:11 +00001/*
2 * Virtio Network Device
3 *
4 * Copyright IBM, Corp. 2007
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
11 *
12 */
13
Peter Maydell9b8bfe22016-01-26 18:17:07 +000014#include "qemu/osdep.h"
Jens Freimann9711cd02019-10-29 12:49:04 +010015#include "qemu/atomic.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010016#include "qemu/iov.h"
Markus Armbrusterdb725812019-08-12 07:23:50 +020017#include "qemu/main-loop.h"
Markus Armbruster0b8fa322019-05-23 16:35:07 +020018#include "qemu/module.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010019#include "hw/virtio/virtio.h"
Paolo Bonzini1422e322012-10-24 08:43:34 +020020#include "net/net.h"
Mark McLoughlin7200ac32009-10-22 17:49:03 +010021#include "net/checksum.h"
Mark McLoughlina8ed73f2009-10-22 17:49:05 +010022#include "net/tap.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010023#include "qemu/error-report.h"
24#include "qemu/timer.h"
Jens Freimann9711cd02019-10-29 12:49:04 +010025#include "qemu/option.h"
26#include "qemu/option_int.h"
27#include "qemu/config-file.h"
28#include "qapi/qmp/qdict.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010029#include "hw/virtio/virtio-net.h"
30#include "net/vhost_net.h"
Dr. David Alan Gilbert9d8c6a22019-02-27 13:24:07 +000031#include "net/announce.h"
KONRAD Frederic17ec5a82013-04-11 16:29:57 +020032#include "hw/virtio/virtio-bus.h"
Markus Armbrustere688df62018-02-01 12:18:31 +010033#include "qapi/error.h"
Markus Armbruster9af23982018-02-11 10:36:01 +010034#include "qapi/qapi-events-net.h"
Markus Armbrustera27bd6c2019-08-12 07:23:51 +020035#include "hw/qdev-properties.h"
Jens Freimann9711cd02019-10-29 12:49:04 +010036#include "qapi/qapi-types-migration.h"
37#include "qapi/qapi-events-migration.h"
Rusty Russell1399c602014-06-24 19:42:54 +020038#include "hw/virtio/virtio-access.h"
Juan Quintelaf8d806c2017-04-21 17:39:30 +020039#include "migration/misc.h"
Jason Baron94739392018-03-07 22:25:41 -050040#include "standard-headers/linux/ethtool.h"
Markus Armbruster2f780b62019-08-12 07:23:58 +020041#include "sysemu/sysemu.h"
Dr. David Alan Gilbert9d8c6a22019-02-27 13:24:07 +000042#include "trace.h"
Jens Freimann9711cd02019-10-29 12:49:04 +010043#include "monitor/qdev.h"
44#include "hw/pci/pci.h"
Yuri Benditovich4474e372020-05-08 15:59:29 +030045#include "net_rx_pkt.h"
Cindy Lu108a6482020-07-01 22:55:37 +080046#include "hw/virtio/vhost.h"
Laurent Vivier1b529d92021-12-20 15:53:14 +010047#include "sysemu/qtest.h"
aliguorifbe78f42008-12-17 19:13:11 +000048
Mark McLoughlin0ce0e8f2009-10-22 17:43:50 +010049#define VIRTIO_NET_VM_VERSION 11
aliguorib6503ed2009-02-05 22:36:28 +000050
Alex Williamson4ffb17f2009-06-05 14:47:23 -060051#define MAC_TABLE_ENTRIES 64
aliguorif21c0ed2009-02-05 22:36:32 +000052#define MAX_VLAN (1 << 12) /* Per 802.1Q definition */
aliguori9d6271b2009-02-05 22:36:04 +000053
Michael S. Tsirkin1c0fbfa2016-08-10 17:47:16 +030054/* previously fixed value */
55#define VIRTIO_NET_RX_QUEUE_DEFAULT_SIZE 256
Wei Wang9b02e162017-06-28 10:37:59 +080056#define VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE 256
57
Jason Wang441537f2021-10-20 12:55:57 +080058/* for now, only allow larger queue_pairs; with virtio-1, guest can downsize */
Michael S. Tsirkin1c0fbfa2016-08-10 17:47:16 +030059#define VIRTIO_NET_RX_QUEUE_MIN_SIZE VIRTIO_NET_RX_QUEUE_DEFAULT_SIZE
Wei Wang9b02e162017-06-28 10:37:59 +080060#define VIRTIO_NET_TX_QUEUE_MIN_SIZE VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE
Michael S. Tsirkin1c0fbfa2016-08-10 17:47:16 +030061
Yuri Benditovich2974e912019-01-03 15:12:29 +020062#define VIRTIO_NET_IP4_ADDR_SIZE 8 /* ipv4 saddr + daddr */
63
64#define VIRTIO_NET_TCP_FLAG 0x3F
65#define VIRTIO_NET_TCP_HDR_LENGTH 0xF000
66
67/* IPv4 max payload, 16 bits in the header */
68#define VIRTIO_NET_MAX_IP4_PAYLOAD (65535 - sizeof(struct ip_header))
69#define VIRTIO_NET_MAX_TCP_PAYLOAD 65535
70
71/* header length value in ip header without option */
72#define VIRTIO_NET_IP4_HEADER_LENGTH 5
73
74#define VIRTIO_NET_IP6_ADDR_SIZE 32 /* ipv6 saddr + daddr */
75#define VIRTIO_NET_MAX_IP6_PAYLOAD VIRTIO_NET_MAX_TCP_PAYLOAD
76
77/* Purge coalesced packets timer interval, This value affects the performance
78 a lot, and should be tuned carefully, '300000'(300us) is the recommended
79 value to pass the WHQL test, '50000' can gain 2x netperf throughput with
80 tso/gso/gro 'off'. */
81#define VIRTIO_NET_RSC_DEFAULT_INTERVAL 300000
82
Yuri Benditovich59079022020-05-08 15:59:28 +030083#define VIRTIO_NET_RSS_SUPPORTED_HASHES (VIRTIO_NET_RSS_HASH_TYPE_IPv4 | \
84 VIRTIO_NET_RSS_HASH_TYPE_TCPv4 | \
85 VIRTIO_NET_RSS_HASH_TYPE_UDPv4 | \
86 VIRTIO_NET_RSS_HASH_TYPE_IPv6 | \
87 VIRTIO_NET_RSS_HASH_TYPE_TCPv6 | \
88 VIRTIO_NET_RSS_HASH_TYPE_UDPv6 | \
89 VIRTIO_NET_RSS_HASH_TYPE_IP_EX | \
90 VIRTIO_NET_RSS_HASH_TYPE_TCP_EX | \
91 VIRTIO_NET_RSS_HASH_TYPE_UDP_EX)
92
Philippe Mathieu-Daudéad6461a2021-05-11 12:41:57 +020093static const VirtIOFeature feature_sizes[] = {
Jason Baron127833e2018-03-07 22:25:40 -050094 {.flags = 1ULL << VIRTIO_NET_F_MAC,
Max Reitz5d5b33c2019-10-11 17:27:59 +020095 .end = endof(struct virtio_net_config, mac)},
Jason Baron127833e2018-03-07 22:25:40 -050096 {.flags = 1ULL << VIRTIO_NET_F_STATUS,
Max Reitz5d5b33c2019-10-11 17:27:59 +020097 .end = endof(struct virtio_net_config, status)},
Jason Baron127833e2018-03-07 22:25:40 -050098 {.flags = 1ULL << VIRTIO_NET_F_MQ,
Max Reitz5d5b33c2019-10-11 17:27:59 +020099 .end = endof(struct virtio_net_config, max_virtqueue_pairs)},
Jason Baron127833e2018-03-07 22:25:40 -0500100 {.flags = 1ULL << VIRTIO_NET_F_MTU,
Max Reitz5d5b33c2019-10-11 17:27:59 +0200101 .end = endof(struct virtio_net_config, mtu)},
Jason Baron94739392018-03-07 22:25:41 -0500102 {.flags = 1ULL << VIRTIO_NET_F_SPEED_DUPLEX,
Max Reitz5d5b33c2019-10-11 17:27:59 +0200103 .end = endof(struct virtio_net_config, duplex)},
Yuri Benditoviche22f0602020-05-08 15:59:31 +0300104 {.flags = (1ULL << VIRTIO_NET_F_RSS) | (1ULL << VIRTIO_NET_F_HASH_REPORT),
Yuri Benditovich59079022020-05-08 15:59:28 +0300105 .end = endof(struct virtio_net_config, supported_hash_types)},
Jesse Larrew14f9b662013-02-05 17:47:16 -0600106 {}
107};
108
Jason Wangfed699f2013-01-30 19:12:39 +0800109static VirtIONetQueue *virtio_net_get_subqueue(NetClientState *nc)
Jason Wang0c87e932013-01-30 19:12:38 +0800110{
111 VirtIONet *n = qemu_get_nic_opaque(nc);
112
Jason Wangfed699f2013-01-30 19:12:39 +0800113 return &n->vqs[nc->queue_index];
Jason Wang0c87e932013-01-30 19:12:38 +0800114}
Jason Wangfed699f2013-01-30 19:12:39 +0800115
116static int vq2q(int queue_index)
117{
118 return queue_index / 2;
119}
120
aliguorifbe78f42008-12-17 19:13:11 +0000121/* TODO
122 * - we could suppress RX interrupt if we were so inclined.
123 */
124
aliguori0f03eca2009-02-05 22:36:08 +0000125static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
aliguorifbe78f42008-12-17 19:13:11 +0000126{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +0200127 VirtIONet *n = VIRTIO_NET(vdev);
aliguorifbe78f42008-12-17 19:13:11 +0000128 struct virtio_net_config netcfg;
Jason Wangc546ecf2020-07-25 08:13:17 +0800129 NetClientState *nc = qemu_get_queue(n->nic);
Cindy Lufb592882021-02-26 00:55:06 +0800130 static const MACAddr zero = { .a = { 0, 0, 0, 0, 0, 0 } };
aliguorifbe78f42008-12-17 19:13:11 +0000131
Cindy Lu108a6482020-07-01 22:55:37 +0800132 int ret = 0;
133 memset(&netcfg, 0 , sizeof(struct virtio_net_config));
Rusty Russell1399c602014-06-24 19:42:54 +0200134 virtio_stw_p(vdev, &netcfg.status, n->status);
Jason Wang441537f2021-10-20 12:55:57 +0800135 virtio_stw_p(vdev, &netcfg.max_virtqueue_pairs, n->max_queue_pairs);
Maxime Coquelina93e5992016-12-10 16:30:38 +0100136 virtio_stw_p(vdev, &netcfg.mtu, n->net_conf.mtu);
aliguori79674062009-02-05 22:36:12 +0000137 memcpy(netcfg.mac, n->mac, ETH_ALEN);
Jason Baron94739392018-03-07 22:25:41 -0500138 virtio_stl_p(vdev, &netcfg.speed, n->net_conf.speed);
139 netcfg.duplex = n->net_conf.duplex;
Yuri Benditovich59079022020-05-08 15:59:28 +0300140 netcfg.rss_max_key_size = VIRTIO_NET_RSS_MAX_KEY_SIZE;
141 virtio_stw_p(vdev, &netcfg.rss_max_indirection_table_length,
Yuri Benditoviche22f0602020-05-08 15:59:31 +0300142 virtio_host_has_feature(vdev, VIRTIO_NET_F_RSS) ?
143 VIRTIO_NET_RSS_MAX_TABLE_LEN : 1);
Yuri Benditovich59079022020-05-08 15:59:28 +0300144 virtio_stl_p(vdev, &netcfg.supported_hash_types,
145 VIRTIO_NET_RSS_SUPPORTED_HASHES);
Jesse Larrew14f9b662013-02-05 17:47:16 -0600146 memcpy(config, &netcfg, n->config_size);
Cindy Lu108a6482020-07-01 22:55:37 +0800147
Jason Wangc546ecf2020-07-25 08:13:17 +0800148 /*
149 * Is this VDPA? No peer means not VDPA: there's no way to
150 * disconnect/reconnect a VDPA peer.
151 */
152 if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) {
Cindy Lu108a6482020-07-01 22:55:37 +0800153 ret = vhost_net_get_config(get_vhost_net(nc->peer), (uint8_t *)&netcfg,
Jason Wangc546ecf2020-07-25 08:13:17 +0800154 n->config_size);
155 if (ret != -1) {
Cindy Lufb592882021-02-26 00:55:06 +0800156 /*
157 * Some NIC/kernel combinations present 0 as the mac address. As
158 * that is not a legal address, try to proceed with the
159 * address from the QEMU command line in the hope that the
160 * address has been configured correctly elsewhere - just not
161 * reported by the device.
162 */
163 if (memcmp(&netcfg.mac, &zero, sizeof(zero)) == 0) {
164 info_report("Zero hardware mac address detected. Ignoring.");
165 memcpy(netcfg.mac, n->mac, ETH_ALEN);
166 }
Jason Wangc546ecf2020-07-25 08:13:17 +0800167 memcpy(config, &netcfg, n->config_size);
168 }
Cindy Lu108a6482020-07-01 22:55:37 +0800169 }
aliguorifbe78f42008-12-17 19:13:11 +0000170}
171
aliguori0f03eca2009-02-05 22:36:08 +0000172static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
173{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +0200174 VirtIONet *n = VIRTIO_NET(vdev);
Jesse Larrew14f9b662013-02-05 17:47:16 -0600175 struct virtio_net_config netcfg = {};
Jason Wangc546ecf2020-07-25 08:13:17 +0800176 NetClientState *nc = qemu_get_queue(n->nic);
aliguori0f03eca2009-02-05 22:36:08 +0000177
Jesse Larrew14f9b662013-02-05 17:47:16 -0600178 memcpy(&netcfg, config, n->config_size);
aliguori0f03eca2009-02-05 22:36:08 +0000179
Cornelia Huck95129d62015-08-17 11:48:29 +0200180 if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR) &&
181 !virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1) &&
Amos Kongc1943a32013-01-22 23:44:45 +0800182 memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
aliguori79674062009-02-05 22:36:12 +0000183 memcpy(n->mac, netcfg.mac, ETH_ALEN);
Jason Wangb356f762013-01-30 19:12:22 +0800184 qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
aliguori0f03eca2009-02-05 22:36:08 +0000185 }
Cindy Lu108a6482020-07-01 22:55:37 +0800186
Jason Wangc546ecf2020-07-25 08:13:17 +0800187 /*
188 * Is this VDPA? No peer means not VDPA: there's no way to
189 * disconnect/reconnect a VDPA peer.
190 */
191 if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) {
192 vhost_net_set_config(get_vhost_net(nc->peer),
193 (uint8_t *)&netcfg, 0, n->config_size,
194 VHOST_SET_CONFIG_TYPE_MASTER);
Cindy Lu108a6482020-07-01 22:55:37 +0800195 }
aliguori0f03eca2009-02-05 22:36:08 +0000196}
197
Michael S. Tsirkin783e7702010-11-22 19:52:30 +0200198static bool virtio_net_started(VirtIONet *n, uint8_t status)
Michael S. Tsirkinafbaa7b2010-09-27 18:41:30 +0200199{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +0200200 VirtIODevice *vdev = VIRTIO_DEVICE(n);
Michael S. Tsirkin783e7702010-11-22 19:52:30 +0200201 return (status & VIRTIO_CONFIG_S_DRIVER_OK) &&
KONRAD Frederic17a0ca52013-04-11 16:30:01 +0200202 (n->status & VIRTIO_NET_S_LINK_UP) && vdev->vm_running;
Michael S. Tsirkin783e7702010-11-22 19:52:30 +0200203}
204
Dr. David Alan Gilbertb2c929f2019-02-27 13:24:10 +0000205static void virtio_net_announce_notify(VirtIONet *net)
206{
207 VirtIODevice *vdev = VIRTIO_DEVICE(net);
208 trace_virtio_net_announce_notify();
209
210 net->status |= VIRTIO_NET_S_ANNOUNCE;
211 virtio_notify_config(vdev);
212}
213
Jason Wangf57fcf72014-05-20 14:01:44 +0800214static void virtio_net_announce_timer(void *opaque)
215{
216 VirtIONet *n = opaque;
Dr. David Alan Gilbert9d8c6a22019-02-27 13:24:07 +0000217 trace_virtio_net_announce_timer(n->announce_timer.round);
Jason Wangf57fcf72014-05-20 14:01:44 +0800218
Dr. David Alan Gilbert9d8c6a22019-02-27 13:24:07 +0000219 n->announce_timer.round--;
Dr. David Alan Gilbertb2c929f2019-02-27 13:24:10 +0000220 virtio_net_announce_notify(n);
221}
222
223static void virtio_net_announce(NetClientState *nc)
224{
225 VirtIONet *n = qemu_get_nic_opaque(nc);
226 VirtIODevice *vdev = VIRTIO_DEVICE(n);
227
228 /*
229 * Make sure the virtio migration announcement timer isn't running
230 * If it is, let it trigger announcement so that we do not cause
231 * confusion.
232 */
233 if (n->announce_timer.round) {
234 return;
235 }
236
237 if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
238 virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
239 virtio_net_announce_notify(n);
240 }
Jason Wangf57fcf72014-05-20 14:01:44 +0800241}
242
Michael S. Tsirkin783e7702010-11-22 19:52:30 +0200243static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
244{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +0200245 VirtIODevice *vdev = VIRTIO_DEVICE(n);
Jason Wangb356f762013-01-30 19:12:22 +0800246 NetClientState *nc = qemu_get_queue(n->nic);
Jason Wang441537f2021-10-20 12:55:57 +0800247 int queue_pairs = n->multiqueue ? n->max_queue_pairs : 1;
Jason Wang22288fe2021-10-20 12:55:59 +0800248 int cvq = n->max_ncs - n->max_queue_pairs;
Jason Wangb356f762013-01-30 19:12:22 +0800249
Nikolay Nikolaeved8b4af2014-05-27 15:05:08 +0300250 if (!get_vhost_net(nc->peer)) {
Michael S. Tsirkinafbaa7b2010-09-27 18:41:30 +0200251 return;
252 }
Jason Wangfed699f2013-01-30 19:12:39 +0800253
Radim Krčmář8c1ac472015-02-20 17:06:15 +0100254 if ((virtio_net_started(n, status) && !nc->peer->link_down) ==
255 !!n->vhost_started) {
Michael S. Tsirkinafbaa7b2010-09-27 18:41:30 +0200256 return;
257 }
258 if (!n->vhost_started) {
Michael S. Tsirkin086abc12014-09-04 11:39:17 +0300259 int r, i;
260
Greg Kurz1bfa3162016-02-05 11:43:11 +0100261 if (n->needs_vnet_hdr_swap) {
262 error_report("backend does not support %s vnet headers; "
263 "falling back on userspace virtio",
264 virtio_is_big_endian(vdev) ? "BE" : "LE");
265 return;
266 }
267
Michael S. Tsirkin086abc12014-09-04 11:39:17 +0300268 /* Any packets outstanding? Purge them to avoid touching rings
269 * when vhost is running.
270 */
Jason Wang441537f2021-10-20 12:55:57 +0800271 for (i = 0; i < queue_pairs; i++) {
Michael S. Tsirkin086abc12014-09-04 11:39:17 +0300272 NetClientState *qnc = qemu_get_subqueue(n->nic, i);
273
274 /* Purge both directions: TX and RX. */
275 qemu_net_queue_purge(qnc->peer->incoming_queue, qnc);
276 qemu_net_queue_purge(qnc->incoming_queue, qnc->peer);
277 }
278
Maxime Coquelina93e5992016-12-10 16:30:38 +0100279 if (virtio_has_feature(vdev->guest_features, VIRTIO_NET_F_MTU)) {
280 r = vhost_net_set_mtu(get_vhost_net(nc->peer), n->net_conf.mtu);
281 if (r < 0) {
282 error_report("%uBytes MTU not supported by the backend",
283 n->net_conf.mtu);
284
285 return;
286 }
287 }
288
Michael S. Tsirkin1830b802012-12-25 17:38:59 +0200289 n->vhost_started = 1;
Jason Wang22288fe2021-10-20 12:55:59 +0800290 r = vhost_net_start(vdev, n->nic->ncs, queue_pairs, cvq);
Michael S. Tsirkinafbaa7b2010-09-27 18:41:30 +0200291 if (r < 0) {
Stefan Hajnoczie7b43f72010-11-15 20:44:37 +0000292 error_report("unable to start vhost net: %d: "
293 "falling back on userspace virtio", -r);
Michael S. Tsirkin1830b802012-12-25 17:38:59 +0200294 n->vhost_started = 0;
Michael S. Tsirkinafbaa7b2010-09-27 18:41:30 +0200295 }
296 } else {
Jason Wang22288fe2021-10-20 12:55:59 +0800297 vhost_net_stop(vdev, n->nic->ncs, queue_pairs, cvq);
Michael S. Tsirkinafbaa7b2010-09-27 18:41:30 +0200298 n->vhost_started = 0;
299 }
300}
301
Greg Kurz1bfa3162016-02-05 11:43:11 +0100302static int virtio_net_set_vnet_endian_one(VirtIODevice *vdev,
303 NetClientState *peer,
304 bool enable)
305{
306 if (virtio_is_big_endian(vdev)) {
307 return qemu_set_vnet_be(peer, enable);
308 } else {
309 return qemu_set_vnet_le(peer, enable);
310 }
311}
312
313static bool virtio_net_set_vnet_endian(VirtIODevice *vdev, NetClientState *ncs,
Jason Wang441537f2021-10-20 12:55:57 +0800314 int queue_pairs, bool enable)
Greg Kurz1bfa3162016-02-05 11:43:11 +0100315{
316 int i;
317
Jason Wang441537f2021-10-20 12:55:57 +0800318 for (i = 0; i < queue_pairs; i++) {
Greg Kurz1bfa3162016-02-05 11:43:11 +0100319 if (virtio_net_set_vnet_endian_one(vdev, ncs[i].peer, enable) < 0 &&
320 enable) {
321 while (--i >= 0) {
322 virtio_net_set_vnet_endian_one(vdev, ncs[i].peer, false);
323 }
324
325 return true;
326 }
327 }
328
329 return false;
330}
331
332static void virtio_net_vnet_endian_status(VirtIONet *n, uint8_t status)
333{
334 VirtIODevice *vdev = VIRTIO_DEVICE(n);
Jason Wang441537f2021-10-20 12:55:57 +0800335 int queue_pairs = n->multiqueue ? n->max_queue_pairs : 1;
Greg Kurz1bfa3162016-02-05 11:43:11 +0100336
337 if (virtio_net_started(n, status)) {
338 /* Before using the device, we tell the network backend about the
339 * endianness to use when parsing vnet headers. If the backend
340 * can't do it, we fallback onto fixing the headers in the core
341 * virtio-net code.
342 */
343 n->needs_vnet_hdr_swap = virtio_net_set_vnet_endian(vdev, n->nic->ncs,
Jason Wang441537f2021-10-20 12:55:57 +0800344 queue_pairs, true);
Greg Kurz1bfa3162016-02-05 11:43:11 +0100345 } else if (virtio_net_started(n, vdev->status)) {
346 /* After using the device, we need to reset the network backend to
347 * the default (guest native endianness), otherwise the guest may
348 * lose network connectivity if it is rebooted into a different
349 * endianness.
350 */
Jason Wang441537f2021-10-20 12:55:57 +0800351 virtio_net_set_vnet_endian(vdev, n->nic->ncs, queue_pairs, false);
Greg Kurz1bfa3162016-02-05 11:43:11 +0100352 }
353}
354
Yuri Benditovich283e2c22016-12-13 10:12:08 +0200355static void virtio_net_drop_tx_queue_data(VirtIODevice *vdev, VirtQueue *vq)
356{
357 unsigned int dropped = virtqueue_drop_all(vq);
358 if (dropped) {
359 virtio_notify(vdev, vq);
360 }
361}
362
Michael S. Tsirkin783e7702010-11-22 19:52:30 +0200363static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
364{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +0200365 VirtIONet *n = VIRTIO_NET(vdev);
Jason Wangfed699f2013-01-30 19:12:39 +0800366 VirtIONetQueue *q;
367 int i;
368 uint8_t queue_status;
Michael S. Tsirkin783e7702010-11-22 19:52:30 +0200369
Greg Kurz1bfa3162016-02-05 11:43:11 +0100370 virtio_net_vnet_endian_status(n, status);
Michael S. Tsirkin783e7702010-11-22 19:52:30 +0200371 virtio_net_vhost_status(n, status);
372
Jason Wang441537f2021-10-20 12:55:57 +0800373 for (i = 0; i < n->max_queue_pairs; i++) {
Fam Zheng38705bb2015-07-15 11:02:27 +0800374 NetClientState *ncs = qemu_get_subqueue(n->nic, i);
375 bool queue_started;
Jason Wangfed699f2013-01-30 19:12:39 +0800376 q = &n->vqs[i];
Michael S. Tsirkin783e7702010-11-22 19:52:30 +0200377
Jason Wang441537f2021-10-20 12:55:57 +0800378 if ((!n->multiqueue && i != 0) || i >= n->curr_queue_pairs) {
Jason Wangfed699f2013-01-30 19:12:39 +0800379 queue_status = 0;
Michael S. Tsirkin783e7702010-11-22 19:52:30 +0200380 } else {
Jason Wangfed699f2013-01-30 19:12:39 +0800381 queue_status = status;
Michael S. Tsirkin783e7702010-11-22 19:52:30 +0200382 }
Fam Zheng38705bb2015-07-15 11:02:27 +0800383 queue_started =
384 virtio_net_started(n, queue_status) && !n->vhost_started;
385
386 if (queue_started) {
387 qemu_flush_queued_packets(ncs);
388 }
Jason Wangfed699f2013-01-30 19:12:39 +0800389
390 if (!q->tx_waiting) {
391 continue;
392 }
393
Fam Zheng38705bb2015-07-15 11:02:27 +0800394 if (queue_started) {
Jason Wangfed699f2013-01-30 19:12:39 +0800395 if (q->tx_timer) {
Alex Blighbc72ad62013-08-21 16:03:08 +0100396 timer_mod(q->tx_timer,
397 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout);
Jason Wangfed699f2013-01-30 19:12:39 +0800398 } else {
399 qemu_bh_schedule(q->tx_bh);
400 }
Michael S. Tsirkin783e7702010-11-22 19:52:30 +0200401 } else {
Jason Wangfed699f2013-01-30 19:12:39 +0800402 if (q->tx_timer) {
Alex Blighbc72ad62013-08-21 16:03:08 +0100403 timer_del(q->tx_timer);
Jason Wangfed699f2013-01-30 19:12:39 +0800404 } else {
405 qemu_bh_cancel(q->tx_bh);
406 }
Yuri Benditovich283e2c22016-12-13 10:12:08 +0200407 if ((n->status & VIRTIO_NET_S_LINK_UP) == 0 &&
Jason Wang70e53e62017-11-22 17:57:19 +0800408 (queue_status & VIRTIO_CONFIG_S_DRIVER_OK) &&
409 vdev->vm_running) {
Yuri Benditovich283e2c22016-12-13 10:12:08 +0200410 /* if tx is waiting we are likely have some packets in tx queue
411 * and disabled notification */
412 q->tx_waiting = 0;
413 virtio_queue_set_notification(q->tx_vq, 1);
414 virtio_net_drop_tx_queue_data(vdev, q->tx_vq);
415 }
Michael S. Tsirkin783e7702010-11-22 19:52:30 +0200416 }
417 }
418}
419
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +0100420static void virtio_net_set_link_status(NetClientState *nc)
aliguori554c97d2009-01-08 19:46:33 +0000421{
Jason Wangcc1f0f42013-01-30 19:12:23 +0800422 VirtIONet *n = qemu_get_nic_opaque(nc);
KONRAD Frederic17a0ca52013-04-11 16:30:01 +0200423 VirtIODevice *vdev = VIRTIO_DEVICE(n);
aliguori554c97d2009-01-08 19:46:33 +0000424 uint16_t old_status = n->status;
425
Mark McLoughlineb6b6c12009-11-25 18:49:11 +0000426 if (nc->link_down)
aliguori554c97d2009-01-08 19:46:33 +0000427 n->status &= ~VIRTIO_NET_S_LINK_UP;
428 else
429 n->status |= VIRTIO_NET_S_LINK_UP;
430
431 if (n->status != old_status)
KONRAD Frederic17a0ca52013-04-11 16:30:01 +0200432 virtio_notify_config(vdev);
Michael S. Tsirkinafbaa7b2010-09-27 18:41:30 +0200433
KONRAD Frederic17a0ca52013-04-11 16:30:01 +0200434 virtio_net_set_status(vdev, vdev->status);
aliguori554c97d2009-01-08 19:46:33 +0000435}
436
Amos Kongb1be4282013-06-14 15:45:52 +0800437static void rxfilter_notify(NetClientState *nc)
438{
Amos Kongb1be4282013-06-14 15:45:52 +0800439 VirtIONet *n = qemu_get_nic_opaque(nc);
440
441 if (nc->rxfilter_notify_enabled) {
Markus Armbrusterddfb0ba2020-05-05 17:29:10 +0200442 char *path = object_get_canonical_path(OBJECT(n->qdev));
Wenchao Xia06150272014-06-18 08:43:48 +0200443 qapi_event_send_nic_rx_filter_changed(!!n->netclient_name,
Peter Xu3ab72382018-08-15 21:37:37 +0800444 n->netclient_name, path);
Amos Kong96e35042013-11-18 23:32:17 +0800445 g_free(path);
Amos Kongb1be4282013-06-14 15:45:52 +0800446
447 /* disable event notification to avoid events flooding */
448 nc->rxfilter_notify_enabled = 0;
449 }
450}
451
Amos Kongf7bc8ef2014-03-26 08:19:43 +0800452static intList *get_vlan_table(VirtIONet *n)
453{
Eric Blake54aa3de2020-11-12 19:13:37 -0600454 intList *list;
Amos Kongf7bc8ef2014-03-26 08:19:43 +0800455 int i, j;
456
457 list = NULL;
458 for (i = 0; i < MAX_VLAN >> 5; i++) {
459 for (j = 0; n->vlans[i] && j <= 0x1f; j++) {
460 if (n->vlans[i] & (1U << j)) {
Eric Blake54aa3de2020-11-12 19:13:37 -0600461 QAPI_LIST_PREPEND(list, (i << 5) + j);
Amos Kongf7bc8ef2014-03-26 08:19:43 +0800462 }
463 }
464 }
465
466 return list;
467}
468
Amos Kongb1be4282013-06-14 15:45:52 +0800469static RxFilterInfo *virtio_net_query_rxfilter(NetClientState *nc)
470{
471 VirtIONet *n = qemu_get_nic_opaque(nc);
Amos Kongf7bc8ef2014-03-26 08:19:43 +0800472 VirtIODevice *vdev = VIRTIO_DEVICE(n);
Amos Kongb1be4282013-06-14 15:45:52 +0800473 RxFilterInfo *info;
Eric Blake54aa3de2020-11-12 19:13:37 -0600474 strList *str_list;
Amos Kongf7bc8ef2014-03-26 08:19:43 +0800475 int i;
Amos Kongb1be4282013-06-14 15:45:52 +0800476
477 info = g_malloc0(sizeof(*info));
478 info->name = g_strdup(nc->name);
479 info->promiscuous = n->promisc;
480
481 if (n->nouni) {
482 info->unicast = RX_STATE_NONE;
483 } else if (n->alluni) {
484 info->unicast = RX_STATE_ALL;
485 } else {
486 info->unicast = RX_STATE_NORMAL;
487 }
488
489 if (n->nomulti) {
490 info->multicast = RX_STATE_NONE;
491 } else if (n->allmulti) {
492 info->multicast = RX_STATE_ALL;
493 } else {
494 info->multicast = RX_STATE_NORMAL;
495 }
496
497 info->broadcast_allowed = n->nobcast;
498 info->multicast_overflow = n->mac_table.multi_overflow;
499 info->unicast_overflow = n->mac_table.uni_overflow;
500
Scott Feldmanb0575ba2015-03-13 21:09:26 -0700501 info->main_mac = qemu_mac_strdup_printf(n->mac);
Amos Kongb1be4282013-06-14 15:45:52 +0800502
503 str_list = NULL;
504 for (i = 0; i < n->mac_table.first_multi; i++) {
Eric Blake54aa3de2020-11-12 19:13:37 -0600505 QAPI_LIST_PREPEND(str_list,
506 qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN));
Amos Kongb1be4282013-06-14 15:45:52 +0800507 }
508 info->unicast_table = str_list;
509
510 str_list = NULL;
511 for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) {
Eric Blake54aa3de2020-11-12 19:13:37 -0600512 QAPI_LIST_PREPEND(str_list,
513 qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN));
Amos Kongb1be4282013-06-14 15:45:52 +0800514 }
515 info->multicast_table = str_list;
Amos Kongf7bc8ef2014-03-26 08:19:43 +0800516 info->vlan_table = get_vlan_table(n);
Amos Kongb1be4282013-06-14 15:45:52 +0800517
Cornelia Huck95129d62015-08-17 11:48:29 +0200518 if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VLAN)) {
Amos Kongf7bc8ef2014-03-26 08:19:43 +0800519 info->vlan = RX_STATE_ALL;
520 } else if (!info->vlan_table) {
521 info->vlan = RX_STATE_NONE;
522 } else {
523 info->vlan = RX_STATE_NORMAL;
Amos Kongb1be4282013-06-14 15:45:52 +0800524 }
Amos Kongb1be4282013-06-14 15:45:52 +0800525
526 /* enable event notification after query */
527 nc->rxfilter_notify_enabled = 1;
528
529 return info;
530}
531
aliguori002437c2009-02-05 22:36:20 +0000532static void virtio_net_reset(VirtIODevice *vdev)
533{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +0200534 VirtIONet *n = VIRTIO_NET(vdev);
Greg Kurz94b52952018-03-20 11:44:56 +0100535 int i;
aliguori002437c2009-02-05 22:36:20 +0000536
537 /* Reset back to compatibility mode */
538 n->promisc = 1;
539 n->allmulti = 0;
Alex Williamson015cb162009-06-05 14:47:18 -0600540 n->alluni = 0;
541 n->nomulti = 0;
542 n->nouni = 0;
543 n->nobcast = 0;
Jason Wangfed699f2013-01-30 19:12:39 +0800544 /* multiqueue is disabled by default */
Jason Wang441537f2021-10-20 12:55:57 +0800545 n->curr_queue_pairs = 1;
Dr. David Alan Gilbert9d8c6a22019-02-27 13:24:07 +0000546 timer_del(n->announce_timer.tm);
547 n->announce_timer.round = 0;
Jason Wangf57fcf72014-05-20 14:01:44 +0800548 n->status &= ~VIRTIO_NET_S_ANNOUNCE;
aliguorib6503ed2009-02-05 22:36:28 +0000549
aliguorif21c0ed2009-02-05 22:36:32 +0000550 /* Flush any MAC and VLAN filter table state */
aliguorib6503ed2009-02-05 22:36:28 +0000551 n->mac_table.in_use = 0;
Alex Williamson2d9aba32009-06-05 14:47:13 -0600552 n->mac_table.first_multi = 0;
Alex Williamson8fd2a2f2009-06-05 14:47:08 -0600553 n->mac_table.multi_overflow = 0;
554 n->mac_table.uni_overflow = 0;
aliguorib6503ed2009-02-05 22:36:28 +0000555 memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
Michael S. Tsirkin41dc8a62013-01-16 11:37:40 +0200556 memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac));
Michael S. Tsirkin702d66a2013-09-17 11:45:36 +0300557 qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
aliguorif21c0ed2009-02-05 22:36:32 +0000558 memset(n->vlans, 0, MAX_VLAN >> 3);
Greg Kurz94b52952018-03-20 11:44:56 +0100559
560 /* Flush any async TX */
Jason Wang441537f2021-10-20 12:55:57 +0800561 for (i = 0; i < n->max_queue_pairs; i++) {
Greg Kurz94b52952018-03-20 11:44:56 +0100562 NetClientState *nc = qemu_get_subqueue(n->nic, i);
563
564 if (nc->peer) {
565 qemu_flush_or_purge_queued_packets(nc->peer, true);
566 assert(!virtio_net_get_subqueue(nc)->async_tx.elem);
567 }
568 }
aliguori002437c2009-02-05 22:36:20 +0000569}
570
Michael S. Tsirkin6e371ab2012-09-24 17:04:21 +0200571static void peer_test_vnet_hdr(VirtIONet *n)
Mark McLoughlin3a330132009-10-22 17:43:45 +0100572{
Jason Wangb356f762013-01-30 19:12:22 +0800573 NetClientState *nc = qemu_get_queue(n->nic);
574 if (!nc->peer) {
Michael S. Tsirkin6e371ab2012-09-24 17:04:21 +0200575 return;
Jason Wangb356f762013-01-30 19:12:22 +0800576 }
Mark McLoughlin3a330132009-10-22 17:43:45 +0100577
Stefan Hajnoczid6085e32014-02-20 12:14:07 +0100578 n->has_vnet_hdr = qemu_has_vnet_hdr(nc->peer);
Michael S. Tsirkin6e371ab2012-09-24 17:04:21 +0200579}
Mark McLoughlin3a330132009-10-22 17:43:45 +0100580
Michael S. Tsirkin6e371ab2012-09-24 17:04:21 +0200581static int peer_has_vnet_hdr(VirtIONet *n)
582{
Mark McLoughlin3a330132009-10-22 17:43:45 +0100583 return n->has_vnet_hdr;
584}
585
Mark McLoughlin0ce0e8f2009-10-22 17:43:50 +0100586static int peer_has_ufo(VirtIONet *n)
587{
588 if (!peer_has_vnet_hdr(n))
589 return 0;
590
Stefan Hajnoczid6085e32014-02-20 12:14:07 +0100591 n->has_ufo = qemu_has_ufo(qemu_get_queue(n->nic)->peer);
Mark McLoughlin0ce0e8f2009-10-22 17:43:50 +0100592
593 return n->has_ufo;
594}
595
Cornelia Huckbb9d17f2015-06-04 12:34:17 +0200596static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
Yuri Benditoviche22f0602020-05-08 15:59:31 +0300597 int version_1, int hash_report)
Michael S. Tsirkinff3a8062012-09-24 21:05:03 +0200598{
Jason Wangfed699f2013-01-30 19:12:39 +0800599 int i;
600 NetClientState *nc;
601
Michael S. Tsirkinff3a8062012-09-24 21:05:03 +0200602 n->mergeable_rx_bufs = mergeable_rx_bufs;
603
Cornelia Huckbb9d17f2015-06-04 12:34:17 +0200604 if (version_1) {
Yuri Benditoviche22f0602020-05-08 15:59:31 +0300605 n->guest_hdr_len = hash_report ?
606 sizeof(struct virtio_net_hdr_v1_hash) :
607 sizeof(struct virtio_net_hdr_mrg_rxbuf);
608 n->rss_data.populate_hash = !!hash_report;
Cornelia Huckbb9d17f2015-06-04 12:34:17 +0200609 } else {
610 n->guest_hdr_len = n->mergeable_rx_bufs ?
611 sizeof(struct virtio_net_hdr_mrg_rxbuf) :
612 sizeof(struct virtio_net_hdr);
613 }
Michael S. Tsirkinff3a8062012-09-24 21:05:03 +0200614
Jason Wang441537f2021-10-20 12:55:57 +0800615 for (i = 0; i < n->max_queue_pairs; i++) {
Jason Wangfed699f2013-01-30 19:12:39 +0800616 nc = qemu_get_subqueue(n->nic, i);
617
618 if (peer_has_vnet_hdr(n) &&
Stefan Hajnoczid6085e32014-02-20 12:14:07 +0100619 qemu_has_vnet_hdr_len(nc->peer, n->guest_hdr_len)) {
620 qemu_set_vnet_hdr_len(nc->peer, n->guest_hdr_len);
Jason Wangfed699f2013-01-30 19:12:39 +0800621 n->host_hdr_len = n->guest_hdr_len;
622 }
Michael S. Tsirkinff3a8062012-09-24 21:05:03 +0200623 }
624}
625
Michael S. Tsirkin2eef2782017-07-03 22:25:24 +0300626static int virtio_net_max_tx_queue_size(VirtIONet *n)
627{
628 NetClientState *peer = n->nic_conf.peers.ncs[0];
629
630 /*
631 * Backends other than vhost-user don't support max queue size.
632 */
633 if (!peer) {
634 return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE;
635 }
636
637 if (peer->info->type != NET_CLIENT_DRIVER_VHOST_USER) {
638 return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE;
639 }
640
641 return VIRTQUEUE_MAX_SIZE;
642}
643
Jason Wangfed699f2013-01-30 19:12:39 +0800644static int peer_attach(VirtIONet *n, int index)
645{
646 NetClientState *nc = qemu_get_subqueue(n->nic, index);
647
648 if (!nc->peer) {
649 return 0;
650 }
651
Eric Blakef394b2e2016-07-13 21:50:23 -0600652 if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
Changchun Ouyang7263a0a2015-09-23 12:20:01 +0800653 vhost_set_vring_enable(nc->peer, 1);
654 }
655
Eric Blakef394b2e2016-07-13 21:50:23 -0600656 if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
Jason Wangfed699f2013-01-30 19:12:39 +0800657 return 0;
658 }
659
Jason Wang441537f2021-10-20 12:55:57 +0800660 if (n->max_queue_pairs == 1) {
Jason Wang1074b872017-03-29 10:41:23 +0800661 return 0;
662 }
663
Jason Wangfed699f2013-01-30 19:12:39 +0800664 return tap_enable(nc->peer);
665}
666
667static int peer_detach(VirtIONet *n, int index)
668{
669 NetClientState *nc = qemu_get_subqueue(n->nic, index);
670
671 if (!nc->peer) {
672 return 0;
673 }
674
Eric Blakef394b2e2016-07-13 21:50:23 -0600675 if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
Changchun Ouyang7263a0a2015-09-23 12:20:01 +0800676 vhost_set_vring_enable(nc->peer, 0);
677 }
678
Eric Blakef394b2e2016-07-13 21:50:23 -0600679 if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
Jason Wangfed699f2013-01-30 19:12:39 +0800680 return 0;
681 }
682
683 return tap_disable(nc->peer);
684}
685
Jason Wang441537f2021-10-20 12:55:57 +0800686static void virtio_net_set_queue_pairs(VirtIONet *n)
Jason Wangfed699f2013-01-30 19:12:39 +0800687{
688 int i;
Joel Stanleyddfa83e2014-02-11 10:42:02 +1030689 int r;
Jason Wangfed699f2013-01-30 19:12:39 +0800690
Yuri Benditovich68b5f312016-11-01 00:01:17 +0200691 if (n->nic->peer_deleted) {
692 return;
693 }
694
Jason Wang441537f2021-10-20 12:55:57 +0800695 for (i = 0; i < n->max_queue_pairs; i++) {
696 if (i < n->curr_queue_pairs) {
Joel Stanleyddfa83e2014-02-11 10:42:02 +1030697 r = peer_attach(n, i);
698 assert(!r);
Jason Wangfed699f2013-01-30 19:12:39 +0800699 } else {
Joel Stanleyddfa83e2014-02-11 10:42:02 +1030700 r = peer_detach(n, i);
701 assert(!r);
Jason Wangfed699f2013-01-30 19:12:39 +0800702 }
703 }
704}
705
Jason Wangec57db12013-04-25 15:24:23 +0800706static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue);
Jason Wangfed699f2013-01-30 19:12:39 +0800707
Jason Wang9d5b7312015-07-27 17:49:19 +0800708static uint64_t virtio_net_get_features(VirtIODevice *vdev, uint64_t features,
709 Error **errp)
aliguorifbe78f42008-12-17 19:13:11 +0000710{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +0200711 VirtIONet *n = VIRTIO_NET(vdev);
Jason Wangb356f762013-01-30 19:12:22 +0800712 NetClientState *nc = qemu_get_queue(n->nic);
aliguorifbe78f42008-12-17 19:13:11 +0000713
Shannon Zhaoda3e8a22015-04-28 19:51:12 +0800714 /* Firstly sync all virtio-net possible supported features */
715 features |= n->host_features;
716
Cornelia Huck0cd09c32014-12-11 14:25:05 +0100717 virtio_add_feature(&features, VIRTIO_NET_F_MAC);
Michael S. Tsirkinc9f79a32010-01-12 20:50:17 +0200718
Michael S. Tsirkin6e371ab2012-09-24 17:04:21 +0200719 if (!peer_has_vnet_hdr(n)) {
Cornelia Huck0cd09c32014-12-11 14:25:05 +0100720 virtio_clear_feature(&features, VIRTIO_NET_F_CSUM);
721 virtio_clear_feature(&features, VIRTIO_NET_F_HOST_TSO4);
722 virtio_clear_feature(&features, VIRTIO_NET_F_HOST_TSO6);
723 virtio_clear_feature(&features, VIRTIO_NET_F_HOST_ECN);
Mark McLoughlin3a330132009-10-22 17:43:45 +0100724
Cornelia Huck0cd09c32014-12-11 14:25:05 +0100725 virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_CSUM);
726 virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO4);
727 virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_TSO6);
728 virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_ECN);
Yuri Benditoviche22f0602020-05-08 15:59:31 +0300729
730 virtio_clear_feature(&features, VIRTIO_NET_F_HASH_REPORT);
Michael S. Tsirkin81725392010-01-10 13:52:53 +0200731 }
Mark McLoughlinf5436dd2009-10-22 17:43:47 +0100732
Michael S. Tsirkin81725392010-01-10 13:52:53 +0200733 if (!peer_has_vnet_hdr(n) || !peer_has_ufo(n)) {
Cornelia Huck0cd09c32014-12-11 14:25:05 +0100734 virtio_clear_feature(&features, VIRTIO_NET_F_GUEST_UFO);
735 virtio_clear_feature(&features, VIRTIO_NET_F_HOST_UFO);
Mark McLoughlin3a330132009-10-22 17:43:45 +0100736 }
737
Nikolay Nikolaeved8b4af2014-05-27 15:05:08 +0300738 if (!get_vhost_net(nc->peer)) {
Michael S. Tsirkin9bc63042010-03-17 13:08:42 +0200739 return features;
740 }
Yuri Benditovich2974e912019-01-03 15:12:29 +0200741
Andrew Melnychenko0145c392021-05-14 14:48:33 +0300742 if (!ebpf_rss_is_loaded(&n->ebpf_rss)) {
743 virtio_clear_feature(&features, VIRTIO_NET_F_RSS);
744 }
Maxime Coquelin75ebec12017-05-23 14:31:19 +0200745 features = vhost_net_get_features(get_vhost_net(nc->peer), features);
746 vdev->backend_features = features;
747
748 if (n->mtu_bypass_backend &&
749 (n->host_features & 1ULL << VIRTIO_NET_F_MTU)) {
750 features |= (1ULL << VIRTIO_NET_F_MTU);
751 }
752
753 return features;
aliguorifbe78f42008-12-17 19:13:11 +0000754}
755
Gerd Hoffmann019a3ed2015-06-01 10:45:40 +0200756static uint64_t virtio_net_bad_features(VirtIODevice *vdev)
aliguori8eca6b12009-04-05 17:40:08 +0000757{
Gerd Hoffmann019a3ed2015-06-01 10:45:40 +0200758 uint64_t features = 0;
aliguori8eca6b12009-04-05 17:40:08 +0000759
760 /* Linux kernel 2.6.25. It understood MAC (as everyone must),
761 * but also these: */
Cornelia Huck0cd09c32014-12-11 14:25:05 +0100762 virtio_add_feature(&features, VIRTIO_NET_F_MAC);
763 virtio_add_feature(&features, VIRTIO_NET_F_CSUM);
764 virtio_add_feature(&features, VIRTIO_NET_F_HOST_TSO4);
765 virtio_add_feature(&features, VIRTIO_NET_F_HOST_TSO6);
766 virtio_add_feature(&features, VIRTIO_NET_F_HOST_ECN);
aliguori8eca6b12009-04-05 17:40:08 +0000767
Michael S. Tsirkin81725392010-01-10 13:52:53 +0200768 return features;
aliguori8eca6b12009-04-05 17:40:08 +0000769}
770
Dmitry Fleytman644c9852013-05-20 11:18:14 +0300771static void virtio_net_apply_guest_offloads(VirtIONet *n)
772{
Stefan Hajnocziad37bb32014-02-20 12:14:09 +0100773 qemu_set_offload(qemu_get_queue(n->nic)->peer,
Dmitry Fleytman644c9852013-05-20 11:18:14 +0300774 !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_CSUM)),
775 !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO4)),
776 !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO6)),
777 !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_ECN)),
778 !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_UFO)));
779}
780
781static uint64_t virtio_net_guest_offloads_by_features(uint32_t features)
782{
783 static const uint64_t guest_offloads_mask =
784 (1ULL << VIRTIO_NET_F_GUEST_CSUM) |
785 (1ULL << VIRTIO_NET_F_GUEST_TSO4) |
786 (1ULL << VIRTIO_NET_F_GUEST_TSO6) |
787 (1ULL << VIRTIO_NET_F_GUEST_ECN) |
788 (1ULL << VIRTIO_NET_F_GUEST_UFO);
789
790 return guest_offloads_mask & features;
791}
792
793static inline uint64_t virtio_net_supported_guest_offloads(VirtIONet *n)
794{
795 VirtIODevice *vdev = VIRTIO_DEVICE(n);
796 return virtio_net_guest_offloads_by_features(vdev->guest_features);
797}
798
Juan Quintelaf5e18472020-11-18 09:37:44 +0100799typedef struct {
800 VirtIONet *n;
Kevin Wolf12b2fad2021-10-08 15:34:40 +0200801 DeviceState *dev;
802} FailoverDevice;
Juan Quintelaf5e18472020-11-18 09:37:44 +0100803
804/**
Kevin Wolf12b2fad2021-10-08 15:34:40 +0200805 * Set the failover primary device
Juan Quintelaf5e18472020-11-18 09:37:44 +0100806 *
807 * @opaque: FailoverId to setup
808 * @opts: opts for device we are handling
809 * @errp: returns an error if this function fails
810 */
Kevin Wolf12b2fad2021-10-08 15:34:40 +0200811static int failover_set_primary(DeviceState *dev, void *opaque)
Juan Quintelaf5e18472020-11-18 09:37:44 +0100812{
Kevin Wolf12b2fad2021-10-08 15:34:40 +0200813 FailoverDevice *fdev = opaque;
814 PCIDevice *pci_dev = (PCIDevice *)
815 object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE);
Juan Quintelaf5e18472020-11-18 09:37:44 +0100816
Kevin Wolf12b2fad2021-10-08 15:34:40 +0200817 if (!pci_dev) {
818 return 0;
819 }
820
821 if (!g_strcmp0(pci_dev->failover_pair_id, fdev->n->netclient_name)) {
822 fdev->dev = dev;
Juan Quintelaf5e18472020-11-18 09:37:44 +0100823 return 1;
824 }
825
826 return 0;
827}
828
829/**
Juan Quintela85d3b932020-11-18 09:37:39 +0100830 * Find the primary device for this failover virtio-net
831 *
832 * @n: VirtIONet device
833 * @errp: returns an error if this function fails
834 */
Juan Quintela0a0a27d2020-11-18 09:37:43 +0100835static DeviceState *failover_find_primary_device(VirtIONet *n)
Jens Freimann9711cd02019-10-29 12:49:04 +0100836{
Kevin Wolf12b2fad2021-10-08 15:34:40 +0200837 FailoverDevice fdev = {
838 .n = n,
839 };
Jens Freimann9711cd02019-10-29 12:49:04 +0100840
Kevin Wolf12b2fad2021-10-08 15:34:40 +0200841 qbus_walk_children(sysbus_get_default(), failover_set_primary, NULL,
842 NULL, NULL, &fdev);
843 return fdev.dev;
Jens Freimann9711cd02019-10-29 12:49:04 +0100844}
845
Juan Quintela21e87092020-11-18 09:37:48 +0100846static void failover_add_primary(VirtIONet *n, Error **errp)
847{
848 Error *err = NULL;
Juan Quintela21e87092020-11-18 09:37:48 +0100849 DeviceState *dev = failover_find_primary_device(n);
850
851 if (dev) {
852 return;
853 }
854
Kevin Wolf259a10d2021-10-08 15:34:39 +0200855 if (!n->primary_opts) {
Juan Quintela21e87092020-11-18 09:37:48 +0100856 error_setg(errp, "Primary device not found");
857 error_append_hint(errp, "Virtio-net failover will not work. Make "
858 "sure primary device has parameter"
Laurent Vivier97ca9c52021-02-12 14:52:49 +0100859 " failover_pair_id=%s\n", n->netclient_name);
860 return;
861 }
Kevin Wolf259a10d2021-10-08 15:34:39 +0200862
Kevin Wolff3558b12021-10-08 15:34:41 +0200863 dev = qdev_device_add_from_qdict(n->primary_opts,
864 n->primary_opts_from_json,
865 &err);
Laurent Vivier97ca9c52021-02-12 14:52:49 +0100866 if (err) {
Kevin Wolff3558b12021-10-08 15:34:41 +0200867 qobject_unref(n->primary_opts);
Kevin Wolf259a10d2021-10-08 15:34:39 +0200868 n->primary_opts = NULL;
Laurent Vivier97ca9c52021-02-12 14:52:49 +0100869 } else {
870 object_unref(OBJECT(dev));
Juan Quintela21e87092020-11-18 09:37:48 +0100871 }
872 error_propagate(errp, err);
873}
874
Gerd Hoffmannd5aaa1b2015-06-03 14:47:19 +0200875static void virtio_net_set_features(VirtIODevice *vdev, uint64_t features)
aliguorifbe78f42008-12-17 19:13:11 +0000876{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +0200877 VirtIONet *n = VIRTIO_NET(vdev);
Jens Freimann9711cd02019-10-29 12:49:04 +0100878 Error *err = NULL;
Jason Wangfed699f2013-01-30 19:12:39 +0800879 int i;
880
Maxime Coquelin75ebec12017-05-23 14:31:19 +0200881 if (n->mtu_bypass_backend &&
882 !virtio_has_feature(vdev->backend_features, VIRTIO_NET_F_MTU)) {
883 features &= ~(1ULL << VIRTIO_NET_F_MTU);
884 }
885
Cornelia Huckef546f12014-12-11 14:25:06 +0100886 virtio_net_set_multiqueue(n,
Yuri Benditovich59079022020-05-08 15:59:28 +0300887 virtio_has_feature(features, VIRTIO_NET_F_RSS) ||
Cornelia Huck95129d62015-08-17 11:48:29 +0200888 virtio_has_feature(features, VIRTIO_NET_F_MQ));
aliguorifbe78f42008-12-17 19:13:11 +0000889
Cornelia Huckef546f12014-12-11 14:25:06 +0100890 virtio_net_set_mrg_rx_bufs(n,
Cornelia Huck95129d62015-08-17 11:48:29 +0200891 virtio_has_feature(features,
892 VIRTIO_NET_F_MRG_RXBUF),
893 virtio_has_feature(features,
Yuri Benditoviche22f0602020-05-08 15:59:31 +0300894 VIRTIO_F_VERSION_1),
895 virtio_has_feature(features,
896 VIRTIO_NET_F_HASH_REPORT));
Mark McLoughlinf5436dd2009-10-22 17:43:47 +0100897
Yuri Benditovich2974e912019-01-03 15:12:29 +0200898 n->rsc4_enabled = virtio_has_feature(features, VIRTIO_NET_F_RSC_EXT) &&
899 virtio_has_feature(features, VIRTIO_NET_F_GUEST_TSO4);
900 n->rsc6_enabled = virtio_has_feature(features, VIRTIO_NET_F_RSC_EXT) &&
901 virtio_has_feature(features, VIRTIO_NET_F_GUEST_TSO6);
Yuri Benditoviche22f0602020-05-08 15:59:31 +0300902 n->rss_data.redirect = virtio_has_feature(features, VIRTIO_NET_F_RSS);
Yuri Benditovich2974e912019-01-03 15:12:29 +0200903
Mark McLoughlinf5436dd2009-10-22 17:43:47 +0100904 if (n->has_vnet_hdr) {
Dmitry Fleytman644c9852013-05-20 11:18:14 +0300905 n->curr_guest_offloads =
906 virtio_net_guest_offloads_by_features(features);
907 virtio_net_apply_guest_offloads(n);
Mark McLoughlinf5436dd2009-10-22 17:43:47 +0100908 }
Jason Wangfed699f2013-01-30 19:12:39 +0800909
Jason Wang441537f2021-10-20 12:55:57 +0800910 for (i = 0; i < n->max_queue_pairs; i++) {
Jason Wangfed699f2013-01-30 19:12:39 +0800911 NetClientState *nc = qemu_get_subqueue(n->nic, i);
912
Nikolay Nikolaeved8b4af2014-05-27 15:05:08 +0300913 if (!get_vhost_net(nc->peer)) {
Jason Wangfed699f2013-01-30 19:12:39 +0800914 continue;
915 }
Nikolay Nikolaeved8b4af2014-05-27 15:05:08 +0300916 vhost_net_ack_features(get_vhost_net(nc->peer), features);
David L Stevensdc14a392010-03-31 21:20:31 +0300917 }
Stefan Fritsch0b1eaa82014-03-26 18:29:52 +0800918
Cornelia Huck95129d62015-08-17 11:48:29 +0200919 if (virtio_has_feature(features, VIRTIO_NET_F_CTRL_VLAN)) {
Stefan Fritsch0b1eaa82014-03-26 18:29:52 +0800920 memset(n->vlans, 0, MAX_VLAN >> 3);
921 } else {
922 memset(n->vlans, 0xff, MAX_VLAN >> 3);
923 }
Jens Freimann9711cd02019-10-29 12:49:04 +0100924
925 if (virtio_has_feature(features, VIRTIO_NET_F_STANDBY)) {
926 qapi_event_send_failover_negotiated(n->netclient_name);
Juan Quintelae2bde832020-11-18 09:37:29 +0100927 qatomic_set(&n->failover_primary_hidden, false);
Jens Freimann9711cd02019-10-29 12:49:04 +0100928 failover_add_primary(n, &err);
929 if (err) {
Laurent Vivier1b529d92021-12-20 15:53:14 +0100930 if (!qtest_enabled()) {
931 warn_report_err(err);
932 } else {
933 error_free(err);
934 }
Jens Freimann9711cd02019-10-29 12:49:04 +0100935 }
936 }
aliguorifbe78f42008-12-17 19:13:11 +0000937}
938
aliguori002437c2009-02-05 22:36:20 +0000939static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +0800940 struct iovec *iov, unsigned int iov_cnt)
aliguori002437c2009-02-05 22:36:20 +0000941{
942 uint8_t on;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +0800943 size_t s;
Amos Kongb1be4282013-06-14 15:45:52 +0800944 NetClientState *nc = qemu_get_queue(n->nic);
aliguori002437c2009-02-05 22:36:20 +0000945
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +0800946 s = iov_to_buf(iov, iov_cnt, 0, &on, sizeof(on));
947 if (s != sizeof(on)) {
948 return VIRTIO_NET_ERR;
aliguori002437c2009-02-05 22:36:20 +0000949 }
950
Amos Kongdd234542013-01-22 23:44:46 +0800951 if (cmd == VIRTIO_NET_CTRL_RX_PROMISC) {
aliguori002437c2009-02-05 22:36:20 +0000952 n->promisc = on;
Amos Kongdd234542013-01-22 23:44:46 +0800953 } else if (cmd == VIRTIO_NET_CTRL_RX_ALLMULTI) {
aliguori002437c2009-02-05 22:36:20 +0000954 n->allmulti = on;
Amos Kongdd234542013-01-22 23:44:46 +0800955 } else if (cmd == VIRTIO_NET_CTRL_RX_ALLUNI) {
Alex Williamson015cb162009-06-05 14:47:18 -0600956 n->alluni = on;
Amos Kongdd234542013-01-22 23:44:46 +0800957 } else if (cmd == VIRTIO_NET_CTRL_RX_NOMULTI) {
Alex Williamson015cb162009-06-05 14:47:18 -0600958 n->nomulti = on;
Amos Kongdd234542013-01-22 23:44:46 +0800959 } else if (cmd == VIRTIO_NET_CTRL_RX_NOUNI) {
Alex Williamson015cb162009-06-05 14:47:18 -0600960 n->nouni = on;
Amos Kongdd234542013-01-22 23:44:46 +0800961 } else if (cmd == VIRTIO_NET_CTRL_RX_NOBCAST) {
Alex Williamson015cb162009-06-05 14:47:18 -0600962 n->nobcast = on;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +0800963 } else {
aliguori002437c2009-02-05 22:36:20 +0000964 return VIRTIO_NET_ERR;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +0800965 }
aliguori002437c2009-02-05 22:36:20 +0000966
Amos Kongb1be4282013-06-14 15:45:52 +0800967 rxfilter_notify(nc);
968
aliguori002437c2009-02-05 22:36:20 +0000969 return VIRTIO_NET_OK;
970}
971
Dmitry Fleytman644c9852013-05-20 11:18:14 +0300972static int virtio_net_handle_offloads(VirtIONet *n, uint8_t cmd,
973 struct iovec *iov, unsigned int iov_cnt)
974{
975 VirtIODevice *vdev = VIRTIO_DEVICE(n);
976 uint64_t offloads;
977 size_t s;
978
Cornelia Huck95129d62015-08-17 11:48:29 +0200979 if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
Dmitry Fleytman644c9852013-05-20 11:18:14 +0300980 return VIRTIO_NET_ERR;
981 }
982
983 s = iov_to_buf(iov, iov_cnt, 0, &offloads, sizeof(offloads));
984 if (s != sizeof(offloads)) {
985 return VIRTIO_NET_ERR;
986 }
987
988 if (cmd == VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET) {
989 uint64_t supported_offloads;
990
Jason Wang189ae6b2017-07-14 20:08:18 +0800991 offloads = virtio_ldq_p(vdev, &offloads);
992
Dmitry Fleytman644c9852013-05-20 11:18:14 +0300993 if (!n->has_vnet_hdr) {
994 return VIRTIO_NET_ERR;
995 }
996
Yuri Benditovich2974e912019-01-03 15:12:29 +0200997 n->rsc4_enabled = virtio_has_feature(offloads, VIRTIO_NET_F_RSC_EXT) &&
998 virtio_has_feature(offloads, VIRTIO_NET_F_GUEST_TSO4);
999 n->rsc6_enabled = virtio_has_feature(offloads, VIRTIO_NET_F_RSC_EXT) &&
1000 virtio_has_feature(offloads, VIRTIO_NET_F_GUEST_TSO6);
1001 virtio_clear_feature(&offloads, VIRTIO_NET_F_RSC_EXT);
1002
Dmitry Fleytman644c9852013-05-20 11:18:14 +03001003 supported_offloads = virtio_net_supported_guest_offloads(n);
1004 if (offloads & ~supported_offloads) {
1005 return VIRTIO_NET_ERR;
1006 }
1007
1008 n->curr_guest_offloads = offloads;
1009 virtio_net_apply_guest_offloads(n);
1010
1011 return VIRTIO_NET_OK;
1012 } else {
1013 return VIRTIO_NET_ERR;
1014 }
1015}
1016
aliguorib6503ed2009-02-05 22:36:28 +00001017static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001018 struct iovec *iov, unsigned int iov_cnt)
aliguorib6503ed2009-02-05 22:36:28 +00001019{
Rusty Russell1399c602014-06-24 19:42:54 +02001020 VirtIODevice *vdev = VIRTIO_DEVICE(n);
aliguorib6503ed2009-02-05 22:36:28 +00001021 struct virtio_net_ctrl_mac mac_data;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001022 size_t s;
Amos Kongb1be4282013-06-14 15:45:52 +08001023 NetClientState *nc = qemu_get_queue(n->nic);
aliguorib6503ed2009-02-05 22:36:28 +00001024
Amos Kongc1943a32013-01-22 23:44:45 +08001025 if (cmd == VIRTIO_NET_CTRL_MAC_ADDR_SET) {
1026 if (iov_size(iov, iov_cnt) != sizeof(n->mac)) {
1027 return VIRTIO_NET_ERR;
1028 }
1029 s = iov_to_buf(iov, iov_cnt, 0, &n->mac, sizeof(n->mac));
1030 assert(s == sizeof(n->mac));
Jason Wangb356f762013-01-30 19:12:22 +08001031 qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
Amos Kongb1be4282013-06-14 15:45:52 +08001032 rxfilter_notify(nc);
1033
Amos Kongc1943a32013-01-22 23:44:45 +08001034 return VIRTIO_NET_OK;
1035 }
1036
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001037 if (cmd != VIRTIO_NET_CTRL_MAC_TABLE_SET) {
aliguorib6503ed2009-02-05 22:36:28 +00001038 return VIRTIO_NET_ERR;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001039 }
aliguorib6503ed2009-02-05 22:36:28 +00001040
Amos Kongcae2e552013-11-11 11:48:36 +08001041 int in_use = 0;
1042 int first_multi = 0;
1043 uint8_t uni_overflow = 0;
1044 uint8_t multi_overflow = 0;
1045 uint8_t *macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);
aliguorib6503ed2009-02-05 22:36:28 +00001046
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001047 s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,
1048 sizeof(mac_data.entries));
Rusty Russell1399c602014-06-24 19:42:54 +02001049 mac_data.entries = virtio_ldl_p(vdev, &mac_data.entries);
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001050 if (s != sizeof(mac_data.entries)) {
Amos Kongb1be4282013-06-14 15:45:52 +08001051 goto error;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001052 }
1053 iov_discard_front(&iov, &iov_cnt, s);
1054
1055 if (mac_data.entries * ETH_ALEN > iov_size(iov, iov_cnt)) {
Amos Kongb1be4282013-06-14 15:45:52 +08001056 goto error;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001057 }
aliguorib6503ed2009-02-05 22:36:28 +00001058
1059 if (mac_data.entries <= MAC_TABLE_ENTRIES) {
Amos Kongcae2e552013-11-11 11:48:36 +08001060 s = iov_to_buf(iov, iov_cnt, 0, macs,
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001061 mac_data.entries * ETH_ALEN);
1062 if (s != mac_data.entries * ETH_ALEN) {
Amos Kongb1be4282013-06-14 15:45:52 +08001063 goto error;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001064 }
Amos Kongcae2e552013-11-11 11:48:36 +08001065 in_use += mac_data.entries;
aliguorib6503ed2009-02-05 22:36:28 +00001066 } else {
Amos Kongcae2e552013-11-11 11:48:36 +08001067 uni_overflow = 1;
aliguorib6503ed2009-02-05 22:36:28 +00001068 }
1069
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001070 iov_discard_front(&iov, &iov_cnt, mac_data.entries * ETH_ALEN);
1071
Amos Kongcae2e552013-11-11 11:48:36 +08001072 first_multi = in_use;
Alex Williamson2d9aba32009-06-05 14:47:13 -06001073
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001074 s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries,
1075 sizeof(mac_data.entries));
Rusty Russell1399c602014-06-24 19:42:54 +02001076 mac_data.entries = virtio_ldl_p(vdev, &mac_data.entries);
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001077 if (s != sizeof(mac_data.entries)) {
Amos Kongb1be4282013-06-14 15:45:52 +08001078 goto error;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001079 }
aliguorib6503ed2009-02-05 22:36:28 +00001080
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001081 iov_discard_front(&iov, &iov_cnt, s);
1082
1083 if (mac_data.entries * ETH_ALEN != iov_size(iov, iov_cnt)) {
Amos Kongb1be4282013-06-14 15:45:52 +08001084 goto error;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001085 }
1086
Michael S. Tsirkinedc24382014-04-11 15:18:08 +03001087 if (mac_data.entries <= MAC_TABLE_ENTRIES - in_use) {
Amos Kongcae2e552013-11-11 11:48:36 +08001088 s = iov_to_buf(iov, iov_cnt, 0, &macs[in_use * ETH_ALEN],
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001089 mac_data.entries * ETH_ALEN);
1090 if (s != mac_data.entries * ETH_ALEN) {
Amos Kongb1be4282013-06-14 15:45:52 +08001091 goto error;
Alex Williamson8fd2a2f2009-06-05 14:47:08 -06001092 }
Amos Kongcae2e552013-11-11 11:48:36 +08001093 in_use += mac_data.entries;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001094 } else {
Amos Kongcae2e552013-11-11 11:48:36 +08001095 multi_overflow = 1;
aliguorib6503ed2009-02-05 22:36:28 +00001096 }
1097
Amos Kongcae2e552013-11-11 11:48:36 +08001098 n->mac_table.in_use = in_use;
1099 n->mac_table.first_multi = first_multi;
1100 n->mac_table.uni_overflow = uni_overflow;
1101 n->mac_table.multi_overflow = multi_overflow;
1102 memcpy(n->mac_table.macs, macs, MAC_TABLE_ENTRIES * ETH_ALEN);
1103 g_free(macs);
Amos Kongb1be4282013-06-14 15:45:52 +08001104 rxfilter_notify(nc);
1105
aliguorib6503ed2009-02-05 22:36:28 +00001106 return VIRTIO_NET_OK;
Amos Kongb1be4282013-06-14 15:45:52 +08001107
1108error:
Amos Kongcae2e552013-11-11 11:48:36 +08001109 g_free(macs);
Amos Kongb1be4282013-06-14 15:45:52 +08001110 return VIRTIO_NET_ERR;
aliguorib6503ed2009-02-05 22:36:28 +00001111}
1112
aliguorif21c0ed2009-02-05 22:36:32 +00001113static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001114 struct iovec *iov, unsigned int iov_cnt)
aliguorif21c0ed2009-02-05 22:36:32 +00001115{
Rusty Russell1399c602014-06-24 19:42:54 +02001116 VirtIODevice *vdev = VIRTIO_DEVICE(n);
aliguorif21c0ed2009-02-05 22:36:32 +00001117 uint16_t vid;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001118 size_t s;
Amos Kongb1be4282013-06-14 15:45:52 +08001119 NetClientState *nc = qemu_get_queue(n->nic);
aliguorif21c0ed2009-02-05 22:36:32 +00001120
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001121 s = iov_to_buf(iov, iov_cnt, 0, &vid, sizeof(vid));
Rusty Russell1399c602014-06-24 19:42:54 +02001122 vid = virtio_lduw_p(vdev, &vid);
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001123 if (s != sizeof(vid)) {
aliguorif21c0ed2009-02-05 22:36:32 +00001124 return VIRTIO_NET_ERR;
1125 }
1126
aliguorif21c0ed2009-02-05 22:36:32 +00001127 if (vid >= MAX_VLAN)
1128 return VIRTIO_NET_ERR;
1129
1130 if (cmd == VIRTIO_NET_CTRL_VLAN_ADD)
1131 n->vlans[vid >> 5] |= (1U << (vid & 0x1f));
1132 else if (cmd == VIRTIO_NET_CTRL_VLAN_DEL)
1133 n->vlans[vid >> 5] &= ~(1U << (vid & 0x1f));
1134 else
1135 return VIRTIO_NET_ERR;
1136
Amos Kongb1be4282013-06-14 15:45:52 +08001137 rxfilter_notify(nc);
1138
aliguorif21c0ed2009-02-05 22:36:32 +00001139 return VIRTIO_NET_OK;
1140}
1141
Jason Wangf57fcf72014-05-20 14:01:44 +08001142static int virtio_net_handle_announce(VirtIONet *n, uint8_t cmd,
1143 struct iovec *iov, unsigned int iov_cnt)
1144{
Dr. David Alan Gilbert9d8c6a22019-02-27 13:24:07 +00001145 trace_virtio_net_handle_announce(n->announce_timer.round);
Jason Wangf57fcf72014-05-20 14:01:44 +08001146 if (cmd == VIRTIO_NET_CTRL_ANNOUNCE_ACK &&
1147 n->status & VIRTIO_NET_S_ANNOUNCE) {
1148 n->status &= ~VIRTIO_NET_S_ANNOUNCE;
Dr. David Alan Gilbert9d8c6a22019-02-27 13:24:07 +00001149 if (n->announce_timer.round) {
1150 qemu_announce_timer_step(&n->announce_timer);
Jason Wangf57fcf72014-05-20 14:01:44 +08001151 }
1152 return VIRTIO_NET_OK;
1153 } else {
1154 return VIRTIO_NET_ERR;
1155 }
1156}
1157
Andrew Melnychenko0145c392021-05-14 14:48:33 +03001158static void virtio_net_detach_epbf_rss(VirtIONet *n);
1159
Yuri Benditovich59079022020-05-08 15:59:28 +03001160static void virtio_net_disable_rss(VirtIONet *n)
1161{
1162 if (n->rss_data.enabled) {
1163 trace_virtio_net_rss_disable();
1164 }
1165 n->rss_data.enabled = false;
Andrew Melnychenko0145c392021-05-14 14:48:33 +03001166
1167 virtio_net_detach_epbf_rss(n);
1168}
1169
1170static bool virtio_net_attach_ebpf_to_backend(NICState *nic, int prog_fd)
1171{
1172 NetClientState *nc = qemu_get_peer(qemu_get_queue(nic), 0);
1173 if (nc == NULL || nc->info->set_steering_ebpf == NULL) {
1174 return false;
1175 }
1176
1177 return nc->info->set_steering_ebpf(nc, prog_fd);
1178}
1179
1180static void rss_data_to_rss_config(struct VirtioNetRssData *data,
1181 struct EBPFRSSConfig *config)
1182{
1183 config->redirect = data->redirect;
1184 config->populate_hash = data->populate_hash;
1185 config->hash_types = data->hash_types;
1186 config->indirections_len = data->indirections_len;
1187 config->default_queue = data->default_queue;
1188}
1189
1190static bool virtio_net_attach_epbf_rss(VirtIONet *n)
1191{
1192 struct EBPFRSSConfig config = {};
1193
1194 if (!ebpf_rss_is_loaded(&n->ebpf_rss)) {
1195 return false;
1196 }
1197
1198 rss_data_to_rss_config(&n->rss_data, &config);
1199
1200 if (!ebpf_rss_set_all(&n->ebpf_rss, &config,
1201 n->rss_data.indirections_table, n->rss_data.key)) {
1202 return false;
1203 }
1204
1205 if (!virtio_net_attach_ebpf_to_backend(n->nic, n->ebpf_rss.program_fd)) {
1206 return false;
1207 }
1208
1209 return true;
1210}
1211
1212static void virtio_net_detach_epbf_rss(VirtIONet *n)
1213{
1214 virtio_net_attach_ebpf_to_backend(n->nic, -1);
1215}
1216
1217static bool virtio_net_load_ebpf(VirtIONet *n)
1218{
1219 if (!virtio_net_attach_ebpf_to_backend(n->nic, -1)) {
1220 /* backend does't support steering ebpf */
1221 return false;
1222 }
1223
1224 return ebpf_rss_load(&n->ebpf_rss);
1225}
1226
1227static void virtio_net_unload_ebpf(VirtIONet *n)
1228{
1229 virtio_net_attach_ebpf_to_backend(n->nic, -1);
1230 ebpf_rss_unload(&n->ebpf_rss);
Yuri Benditovich59079022020-05-08 15:59:28 +03001231}
1232
1233static uint16_t virtio_net_handle_rss(VirtIONet *n,
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001234 struct iovec *iov,
1235 unsigned int iov_cnt,
1236 bool do_rss)
Yuri Benditovich59079022020-05-08 15:59:28 +03001237{
1238 VirtIODevice *vdev = VIRTIO_DEVICE(n);
1239 struct virtio_net_rss_config cfg;
1240 size_t s, offset = 0, size_get;
Jason Wang441537f2021-10-20 12:55:57 +08001241 uint16_t queue_pairs, i;
Yuri Benditovich59079022020-05-08 15:59:28 +03001242 struct {
1243 uint16_t us;
1244 uint8_t b;
1245 } QEMU_PACKED temp;
1246 const char *err_msg = "";
1247 uint32_t err_value = 0;
1248
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001249 if (do_rss && !virtio_vdev_has_feature(vdev, VIRTIO_NET_F_RSS)) {
Yuri Benditovich59079022020-05-08 15:59:28 +03001250 err_msg = "RSS is not negotiated";
1251 goto error;
1252 }
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001253 if (!do_rss && !virtio_vdev_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT)) {
1254 err_msg = "Hash report is not negotiated";
1255 goto error;
1256 }
Yuri Benditovich59079022020-05-08 15:59:28 +03001257 size_get = offsetof(struct virtio_net_rss_config, indirection_table);
1258 s = iov_to_buf(iov, iov_cnt, offset, &cfg, size_get);
1259 if (s != size_get) {
1260 err_msg = "Short command buffer";
1261 err_value = (uint32_t)s;
1262 goto error;
1263 }
1264 n->rss_data.hash_types = virtio_ldl_p(vdev, &cfg.hash_types);
1265 n->rss_data.indirections_len =
1266 virtio_lduw_p(vdev, &cfg.indirection_table_mask);
1267 n->rss_data.indirections_len++;
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001268 if (!do_rss) {
1269 n->rss_data.indirections_len = 1;
1270 }
Yuri Benditovich59079022020-05-08 15:59:28 +03001271 if (!is_power_of_2(n->rss_data.indirections_len)) {
1272 err_msg = "Invalid size of indirection table";
1273 err_value = n->rss_data.indirections_len;
1274 goto error;
1275 }
1276 if (n->rss_data.indirections_len > VIRTIO_NET_RSS_MAX_TABLE_LEN) {
1277 err_msg = "Too large indirection table";
1278 err_value = n->rss_data.indirections_len;
1279 goto error;
1280 }
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001281 n->rss_data.default_queue = do_rss ?
1282 virtio_lduw_p(vdev, &cfg.unclassified_queue) : 0;
Jason Wang441537f2021-10-20 12:55:57 +08001283 if (n->rss_data.default_queue >= n->max_queue_pairs) {
Yuri Benditovich59079022020-05-08 15:59:28 +03001284 err_msg = "Invalid default queue";
1285 err_value = n->rss_data.default_queue;
1286 goto error;
1287 }
1288 offset += size_get;
1289 size_get = sizeof(uint16_t) * n->rss_data.indirections_len;
1290 g_free(n->rss_data.indirections_table);
1291 n->rss_data.indirections_table = g_malloc(size_get);
1292 if (!n->rss_data.indirections_table) {
1293 err_msg = "Can't allocate indirections table";
1294 err_value = n->rss_data.indirections_len;
1295 goto error;
1296 }
1297 s = iov_to_buf(iov, iov_cnt, offset,
1298 n->rss_data.indirections_table, size_get);
1299 if (s != size_get) {
1300 err_msg = "Short indirection table buffer";
1301 err_value = (uint32_t)s;
1302 goto error;
1303 }
1304 for (i = 0; i < n->rss_data.indirections_len; ++i) {
1305 uint16_t val = n->rss_data.indirections_table[i];
1306 n->rss_data.indirections_table[i] = virtio_lduw_p(vdev, &val);
1307 }
1308 offset += size_get;
1309 size_get = sizeof(temp);
1310 s = iov_to_buf(iov, iov_cnt, offset, &temp, size_get);
1311 if (s != size_get) {
Jason Wang441537f2021-10-20 12:55:57 +08001312 err_msg = "Can't get queue_pairs";
Yuri Benditovich59079022020-05-08 15:59:28 +03001313 err_value = (uint32_t)s;
1314 goto error;
1315 }
Jason Wang441537f2021-10-20 12:55:57 +08001316 queue_pairs = do_rss ? virtio_lduw_p(vdev, &temp.us) : n->curr_queue_pairs;
1317 if (queue_pairs == 0 || queue_pairs > n->max_queue_pairs) {
1318 err_msg = "Invalid number of queue_pairs";
1319 err_value = queue_pairs;
Yuri Benditovich59079022020-05-08 15:59:28 +03001320 goto error;
1321 }
1322 if (temp.b > VIRTIO_NET_RSS_MAX_KEY_SIZE) {
1323 err_msg = "Invalid key size";
1324 err_value = temp.b;
1325 goto error;
1326 }
1327 if (!temp.b && n->rss_data.hash_types) {
1328 err_msg = "No key provided";
1329 err_value = 0;
1330 goto error;
1331 }
1332 if (!temp.b && !n->rss_data.hash_types) {
1333 virtio_net_disable_rss(n);
Jason Wang441537f2021-10-20 12:55:57 +08001334 return queue_pairs;
Yuri Benditovich59079022020-05-08 15:59:28 +03001335 }
1336 offset += size_get;
1337 size_get = temp.b;
1338 s = iov_to_buf(iov, iov_cnt, offset, n->rss_data.key, size_get);
1339 if (s != size_get) {
1340 err_msg = "Can get key buffer";
1341 err_value = (uint32_t)s;
1342 goto error;
1343 }
1344 n->rss_data.enabled = true;
Andrew Melnychenko0145c392021-05-14 14:48:33 +03001345
1346 if (!n->rss_data.populate_hash) {
1347 if (!virtio_net_attach_epbf_rss(n)) {
1348 /* EBPF must be loaded for vhost */
1349 if (get_vhost_net(qemu_get_queue(n->nic)->peer)) {
1350 warn_report("Can't load eBPF RSS for vhost");
1351 goto error;
1352 }
1353 /* fallback to software RSS */
1354 warn_report("Can't load eBPF RSS - fallback to software RSS");
1355 n->rss_data.enabled_software_rss = true;
1356 }
1357 } else {
1358 /* use software RSS for hash populating */
1359 /* and detach eBPF if was loaded before */
1360 virtio_net_detach_epbf_rss(n);
1361 n->rss_data.enabled_software_rss = true;
1362 }
1363
Yuri Benditovich59079022020-05-08 15:59:28 +03001364 trace_virtio_net_rss_enable(n->rss_data.hash_types,
1365 n->rss_data.indirections_len,
1366 temp.b);
Jason Wang441537f2021-10-20 12:55:57 +08001367 return queue_pairs;
Yuri Benditovich59079022020-05-08 15:59:28 +03001368error:
1369 trace_virtio_net_rss_error(err_msg, err_value);
1370 virtio_net_disable_rss(n);
1371 return 0;
1372}
1373
Jason Wangfed699f2013-01-30 19:12:39 +08001374static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
Jason Wangf8f7c532013-03-06 13:50:27 +08001375 struct iovec *iov, unsigned int iov_cnt)
Jason Wangfed699f2013-01-30 19:12:39 +08001376{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02001377 VirtIODevice *vdev = VIRTIO_DEVICE(n);
Jason Wang441537f2021-10-20 12:55:57 +08001378 uint16_t queue_pairs;
Jason Wangfed699f2013-01-30 19:12:39 +08001379
Yuri Benditovich59079022020-05-08 15:59:28 +03001380 virtio_net_disable_rss(n);
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001381 if (cmd == VIRTIO_NET_CTRL_MQ_HASH_CONFIG) {
Jason Wang441537f2021-10-20 12:55:57 +08001382 queue_pairs = virtio_net_handle_rss(n, iov, iov_cnt, false);
1383 return queue_pairs ? VIRTIO_NET_OK : VIRTIO_NET_ERR;
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001384 }
Yuri Benditovich59079022020-05-08 15:59:28 +03001385 if (cmd == VIRTIO_NET_CTRL_MQ_RSS_CONFIG) {
Jason Wang441537f2021-10-20 12:55:57 +08001386 queue_pairs = virtio_net_handle_rss(n, iov, iov_cnt, true);
Yuri Benditovich59079022020-05-08 15:59:28 +03001387 } else if (cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
1388 struct virtio_net_ctrl_mq mq;
1389 size_t s;
1390 if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_MQ)) {
1391 return VIRTIO_NET_ERR;
1392 }
1393 s = iov_to_buf(iov, iov_cnt, 0, &mq, sizeof(mq));
1394 if (s != sizeof(mq)) {
1395 return VIRTIO_NET_ERR;
1396 }
Jason Wang441537f2021-10-20 12:55:57 +08001397 queue_pairs = virtio_lduw_p(vdev, &mq.virtqueue_pairs);
Yuri Benditovich59079022020-05-08 15:59:28 +03001398
1399 } else {
Jason Wangfed699f2013-01-30 19:12:39 +08001400 return VIRTIO_NET_ERR;
1401 }
1402
Jason Wang441537f2021-10-20 12:55:57 +08001403 if (queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
1404 queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX ||
1405 queue_pairs > n->max_queue_pairs ||
Jason Wangfed699f2013-01-30 19:12:39 +08001406 !n->multiqueue) {
1407 return VIRTIO_NET_ERR;
1408 }
1409
Jason Wang441537f2021-10-20 12:55:57 +08001410 n->curr_queue_pairs = queue_pairs;
1411 /* stop the backend before changing the number of queue_pairs to avoid handling a
Jason Wangfed699f2013-01-30 19:12:39 +08001412 * disabled queue */
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02001413 virtio_net_set_status(vdev, vdev->status);
Jason Wang441537f2021-10-20 12:55:57 +08001414 virtio_net_set_queue_pairs(n);
Jason Wangfed699f2013-01-30 19:12:39 +08001415
1416 return VIRTIO_NET_OK;
1417}
Greg Kurzba7eadb2016-09-30 17:13:16 +02001418
aliguori3d11d362009-02-05 22:36:16 +00001419static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
1420{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02001421 VirtIONet *n = VIRTIO_NET(vdev);
aliguori3d11d362009-02-05 22:36:16 +00001422 struct virtio_net_ctrl_hdr ctrl;
1423 virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001424 VirtQueueElement *elem;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001425 size_t s;
Jason Wang771b6ed2014-11-27 18:04:03 +08001426 struct iovec *iov, *iov2;
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001427 unsigned int iov_cnt;
aliguori3d11d362009-02-05 22:36:16 +00001428
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001429 for (;;) {
1430 elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
1431 if (!elem) {
1432 break;
1433 }
1434 if (iov_size(elem->in_sg, elem->in_num) < sizeof(status) ||
1435 iov_size(elem->out_sg, elem->out_num) < sizeof(ctrl)) {
Greg Kurzba7eadb2016-09-30 17:13:16 +02001436 virtio_error(vdev, "virtio-net ctrl missing headers");
1437 virtqueue_detach_element(vq, elem, 0);
1438 g_free(elem);
1439 break;
aliguori3d11d362009-02-05 22:36:16 +00001440 }
1441
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001442 iov_cnt = elem->out_num;
1443 iov2 = iov = g_memdup(elem->out_sg, sizeof(struct iovec) * elem->out_num);
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001444 s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl));
1445 iov_discard_front(&iov, &iov_cnt, sizeof(ctrl));
1446 if (s != sizeof(ctrl)) {
1447 status = VIRTIO_NET_ERR;
Amos Kongdd234542013-01-22 23:44:46 +08001448 } else if (ctrl.class == VIRTIO_NET_CTRL_RX) {
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001449 status = virtio_net_handle_rx_mode(n, ctrl.cmd, iov, iov_cnt);
1450 } else if (ctrl.class == VIRTIO_NET_CTRL_MAC) {
1451 status = virtio_net_handle_mac(n, ctrl.cmd, iov, iov_cnt);
1452 } else if (ctrl.class == VIRTIO_NET_CTRL_VLAN) {
1453 status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, iov_cnt);
Jason Wangf57fcf72014-05-20 14:01:44 +08001454 } else if (ctrl.class == VIRTIO_NET_CTRL_ANNOUNCE) {
1455 status = virtio_net_handle_announce(n, ctrl.cmd, iov, iov_cnt);
Jason Wangfed699f2013-01-30 19:12:39 +08001456 } else if (ctrl.class == VIRTIO_NET_CTRL_MQ) {
Jason Wangf8f7c532013-03-06 13:50:27 +08001457 status = virtio_net_handle_mq(n, ctrl.cmd, iov, iov_cnt);
Dmitry Fleytman644c9852013-05-20 11:18:14 +03001458 } else if (ctrl.class == VIRTIO_NET_CTRL_GUEST_OFFLOADS) {
1459 status = virtio_net_handle_offloads(n, ctrl.cmd, iov, iov_cnt);
aliguori3d11d362009-02-05 22:36:16 +00001460 }
1461
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001462 s = iov_from_buf(elem->in_sg, elem->in_num, 0, &status, sizeof(status));
Michael S. Tsirkin921ac5d2013-01-22 23:44:44 +08001463 assert(s == sizeof(status));
aliguori3d11d362009-02-05 22:36:16 +00001464
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001465 virtqueue_push(vq, elem, sizeof(status));
aliguori3d11d362009-02-05 22:36:16 +00001466 virtio_notify(vdev, vq);
Jason Wang771b6ed2014-11-27 18:04:03 +08001467 g_free(iov2);
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001468 g_free(elem);
aliguori3d11d362009-02-05 22:36:16 +00001469 }
1470}
1471
aliguorifbe78f42008-12-17 19:13:11 +00001472/* RX */
1473
1474static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
1475{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02001476 VirtIONet *n = VIRTIO_NET(vdev);
Jason Wangfed699f2013-01-30 19:12:39 +08001477 int queue_index = vq2q(virtio_get_queue_index(vq));
Mark McLoughlin8aeff622009-04-29 13:40:02 +01001478
Jason Wangfed699f2013-01-30 19:12:39 +08001479 qemu_flush_queued_packets(qemu_get_subqueue(n->nic, queue_index));
aliguorifbe78f42008-12-17 19:13:11 +00001480}
1481
Philippe Mathieu-Daudéb8c4b672020-03-05 18:56:49 +01001482static bool virtio_net_can_receive(NetClientState *nc)
aliguorifbe78f42008-12-17 19:13:11 +00001483{
Jason Wangcc1f0f42013-01-30 19:12:23 +08001484 VirtIONet *n = qemu_get_nic_opaque(nc);
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02001485 VirtIODevice *vdev = VIRTIO_DEVICE(n);
Jason Wangfed699f2013-01-30 19:12:39 +08001486 VirtIONetQueue *q = virtio_net_get_subqueue(nc);
Jason Wang0c87e932013-01-30 19:12:38 +08001487
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02001488 if (!vdev->vm_running) {
Philippe Mathieu-Daudéb8c4b672020-03-05 18:56:49 +01001489 return false;
Michael S. Tsirkin95477322010-11-22 19:52:19 +02001490 }
Mark McLoughlincdd5cc12009-10-27 18:16:38 +00001491
Jason Wang441537f2021-10-20 12:55:57 +08001492 if (nc->queue_index >= n->curr_queue_pairs) {
Philippe Mathieu-Daudéb8c4b672020-03-05 18:56:49 +01001493 return false;
Jason Wangfed699f2013-01-30 19:12:39 +08001494 }
1495
Jason Wang0c87e932013-01-30 19:12:38 +08001496 if (!virtio_queue_ready(q->rx_vq) ||
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02001497 !(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
Philippe Mathieu-Daudéb8c4b672020-03-05 18:56:49 +01001498 return false;
Jason Wang0c87e932013-01-30 19:12:38 +08001499 }
aliguorifbe78f42008-12-17 19:13:11 +00001500
Philippe Mathieu-Daudéb8c4b672020-03-05 18:56:49 +01001501 return true;
Mark McLoughlincdd5cc12009-10-27 18:16:38 +00001502}
1503
Jason Wang0c87e932013-01-30 19:12:38 +08001504static int virtio_net_has_buffers(VirtIONetQueue *q, int bufsize)
Mark McLoughlincdd5cc12009-10-27 18:16:38 +00001505{
Jason Wang0c87e932013-01-30 19:12:38 +08001506 VirtIONet *n = q->n;
1507 if (virtio_queue_empty(q->rx_vq) ||
aliguorifbe78f42008-12-17 19:13:11 +00001508 (n->mergeable_rx_bufs &&
Jason Wang0c87e932013-01-30 19:12:38 +08001509 !virtqueue_avail_bytes(q->rx_vq, bufsize, 0))) {
1510 virtio_queue_set_notification(q->rx_vq, 1);
Tom Lendacky06b12972010-02-08 10:10:01 -06001511
1512 /* To avoid a race condition where the guest has made some buffers
1513 * available after the above check but before notification was
1514 * enabled, check for available buffers again.
1515 */
Jason Wang0c87e932013-01-30 19:12:38 +08001516 if (virtio_queue_empty(q->rx_vq) ||
Tom Lendacky06b12972010-02-08 10:10:01 -06001517 (n->mergeable_rx_bufs &&
Jason Wang0c87e932013-01-30 19:12:38 +08001518 !virtqueue_avail_bytes(q->rx_vq, bufsize, 0))) {
Tom Lendacky06b12972010-02-08 10:10:01 -06001519 return 0;
Jason Wang0c87e932013-01-30 19:12:38 +08001520 }
aliguorifbe78f42008-12-17 19:13:11 +00001521 }
1522
Jason Wang0c87e932013-01-30 19:12:38 +08001523 virtio_queue_set_notification(q->rx_vq, 0);
aliguorifbe78f42008-12-17 19:13:11 +00001524 return 1;
1525}
1526
Rusty Russell1399c602014-06-24 19:42:54 +02001527static void virtio_net_hdr_swap(VirtIODevice *vdev, struct virtio_net_hdr *hdr)
Cédric Le Goater032a74a2014-06-24 19:11:32 +02001528{
Rusty Russell1399c602014-06-24 19:42:54 +02001529 virtio_tswap16s(vdev, &hdr->hdr_len);
1530 virtio_tswap16s(vdev, &hdr->gso_size);
1531 virtio_tswap16s(vdev, &hdr->csum_start);
1532 virtio_tswap16s(vdev, &hdr->csum_offset);
Cédric Le Goater032a74a2014-06-24 19:11:32 +02001533}
1534
Anthony Liguori1d41b0c2009-10-22 17:43:48 +01001535/* dhclient uses AF_PACKET but doesn't pass auxdata to the kernel so
1536 * it never finds out that the packets don't have valid checksums. This
1537 * causes dhclient to get upset. Fedora's carried a patch for ages to
1538 * fix this with Xen but it hasn't appeared in an upstream release of
1539 * dhclient yet.
1540 *
1541 * To avoid breaking existing guests, we catch udp packets and add
1542 * checksums. This is terrible but it's better than hacking the guest
1543 * kernels.
1544 *
1545 * N.B. if we introduce a zero-copy API, this operation is no longer free so
1546 * we should provide a mechanism to disable it to avoid polluting the host
1547 * cache.
1548 */
1549static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
Michael S. Tsirkin22cc84d2012-09-24 13:14:16 +02001550 uint8_t *buf, size_t size)
Anthony Liguori1d41b0c2009-10-22 17:43:48 +01001551{
1552 if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */
1553 (size > 27 && size < 1500) && /* normal sized MTU */
1554 (buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */
1555 (buf[23] == 17) && /* ip.protocol == UDP */
1556 (buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */
Bin Mengf5746332020-12-11 17:35:12 +08001557 net_checksum_calculate(buf, size, CSUM_UDP);
Anthony Liguori1d41b0c2009-10-22 17:43:48 +01001558 hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
1559 }
1560}
1561
Michael S. Tsirkin280598b2012-09-24 13:24:17 +02001562static void receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt,
1563 const void *buf, size_t size)
aliguorifbe78f42008-12-17 19:13:11 +00001564{
Mark McLoughlin3a330132009-10-22 17:43:45 +01001565 if (n->has_vnet_hdr) {
Michael S. Tsirkin22cc84d2012-09-24 13:14:16 +02001566 /* FIXME this cast is evil */
1567 void *wbuf = (void *)buf;
Michael S. Tsirkin280598b2012-09-24 13:24:17 +02001568 work_around_broken_dhclient(wbuf, wbuf + n->host_hdr_len,
1569 size - n->host_hdr_len);
Greg Kurz1bfa3162016-02-05 11:43:11 +01001570
1571 if (n->needs_vnet_hdr_swap) {
1572 virtio_net_hdr_swap(VIRTIO_DEVICE(n), wbuf);
1573 }
Michael S. Tsirkin280598b2012-09-24 13:24:17 +02001574 iov_from_buf(iov, iov_cnt, 0, buf, sizeof(struct virtio_net_hdr));
Michael S. Tsirkin22cc84d2012-09-24 13:14:16 +02001575 } else {
1576 struct virtio_net_hdr hdr = {
1577 .flags = 0,
1578 .gso_type = VIRTIO_NET_HDR_GSO_NONE
1579 };
1580 iov_from_buf(iov, iov_cnt, 0, &hdr, sizeof hdr);
Mark McLoughlin3a330132009-10-22 17:43:45 +01001581 }
aliguorifbe78f42008-12-17 19:13:11 +00001582}
1583
aliguori3831ab22009-02-05 22:36:24 +00001584static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
1585{
1586 static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
aliguorif21c0ed2009-02-05 22:36:32 +00001587 static const uint8_t vlan[] = {0x81, 0x00};
aliguori3831ab22009-02-05 22:36:24 +00001588 uint8_t *ptr = (uint8_t *)buf;
aliguorib6503ed2009-02-05 22:36:28 +00001589 int i;
aliguori3831ab22009-02-05 22:36:24 +00001590
1591 if (n->promisc)
1592 return 1;
1593
Michael S. Tsirkine043ebc2012-09-24 16:27:27 +02001594 ptr += n->host_hdr_len;
Mark McLoughlin3a330132009-10-22 17:43:45 +01001595
aliguorif21c0ed2009-02-05 22:36:32 +00001596 if (!memcmp(&ptr[12], vlan, sizeof(vlan))) {
Peter Maydell7542d3e2016-06-16 18:17:25 +01001597 int vid = lduw_be_p(ptr + 14) & 0xfff;
aliguorif21c0ed2009-02-05 22:36:32 +00001598 if (!(n->vlans[vid >> 5] & (1U << (vid & 0x1f))))
1599 return 0;
1600 }
1601
Alex Williamsonbbe2f392009-06-05 14:47:02 -06001602 if (ptr[0] & 1) { // multicast
1603 if (!memcmp(ptr, bcast, sizeof(bcast))) {
Alex Williamson015cb162009-06-05 14:47:18 -06001604 return !n->nobcast;
1605 } else if (n->nomulti) {
1606 return 0;
Alex Williamson8fd2a2f2009-06-05 14:47:08 -06001607 } else if (n->allmulti || n->mac_table.multi_overflow) {
Alex Williamsonbbe2f392009-06-05 14:47:02 -06001608 return 1;
1609 }
Alex Williamson2d9aba32009-06-05 14:47:13 -06001610
1611 for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) {
1612 if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) {
1613 return 1;
1614 }
1615 }
Alex Williamsonbbe2f392009-06-05 14:47:02 -06001616 } else { // unicast
Alex Williamson015cb162009-06-05 14:47:18 -06001617 if (n->nouni) {
1618 return 0;
1619 } else if (n->alluni || n->mac_table.uni_overflow) {
Alex Williamson8fd2a2f2009-06-05 14:47:08 -06001620 return 1;
1621 } else if (!memcmp(ptr, n->mac, ETH_ALEN)) {
Alex Williamsonbbe2f392009-06-05 14:47:02 -06001622 return 1;
1623 }
aliguori3831ab22009-02-05 22:36:24 +00001624
Alex Williamson2d9aba32009-06-05 14:47:13 -06001625 for (i = 0; i < n->mac_table.first_multi; i++) {
1626 if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) {
1627 return 1;
1628 }
1629 }
aliguorib6503ed2009-02-05 22:36:28 +00001630 }
1631
aliguori3831ab22009-02-05 22:36:24 +00001632 return 0;
1633}
1634
Yuri Benditovich4474e372020-05-08 15:59:29 +03001635static uint8_t virtio_net_get_hash_type(bool isip4,
1636 bool isip6,
1637 bool isudp,
1638 bool istcp,
1639 uint32_t types)
1640{
1641 if (isip4) {
1642 if (istcp && (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv4)) {
1643 return NetPktRssIpV4Tcp;
1644 }
1645 if (isudp && (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv4)) {
1646 return NetPktRssIpV4Udp;
1647 }
1648 if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv4) {
1649 return NetPktRssIpV4;
1650 }
1651 } else if (isip6) {
1652 uint32_t mask = VIRTIO_NET_RSS_HASH_TYPE_TCP_EX |
1653 VIRTIO_NET_RSS_HASH_TYPE_TCPv6;
1654
1655 if (istcp && (types & mask)) {
1656 return (types & VIRTIO_NET_RSS_HASH_TYPE_TCP_EX) ?
1657 NetPktRssIpV6TcpEx : NetPktRssIpV6Tcp;
1658 }
1659 mask = VIRTIO_NET_RSS_HASH_TYPE_UDP_EX | VIRTIO_NET_RSS_HASH_TYPE_UDPv6;
1660 if (isudp && (types & mask)) {
1661 return (types & VIRTIO_NET_RSS_HASH_TYPE_UDP_EX) ?
1662 NetPktRssIpV6UdpEx : NetPktRssIpV6Udp;
1663 }
1664 mask = VIRTIO_NET_RSS_HASH_TYPE_IP_EX | VIRTIO_NET_RSS_HASH_TYPE_IPv6;
1665 if (types & mask) {
1666 return (types & VIRTIO_NET_RSS_HASH_TYPE_IP_EX) ?
1667 NetPktRssIpV6Ex : NetPktRssIpV6;
1668 }
1669 }
1670 return 0xff;
1671}
1672
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001673static void virtio_set_packet_hash(const uint8_t *buf, uint8_t report,
1674 uint32_t hash)
1675{
1676 struct virtio_net_hdr_v1_hash *hdr = (void *)buf;
1677 hdr->hash_value = hash;
1678 hdr->hash_report = report;
1679}
1680
Yuri Benditovich4474e372020-05-08 15:59:29 +03001681static int virtio_net_process_rss(NetClientState *nc, const uint8_t *buf,
1682 size_t size)
1683{
1684 VirtIONet *n = qemu_get_nic_opaque(nc);
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001685 unsigned int index = nc->queue_index, new_index = index;
Yuri Benditovich4474e372020-05-08 15:59:29 +03001686 struct NetRxPkt *pkt = n->rx_pkt;
1687 uint8_t net_hash_type;
1688 uint32_t hash;
1689 bool isip4, isip6, isudp, istcp;
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001690 static const uint8_t reports[NetPktRssIpV6UdpEx + 1] = {
1691 VIRTIO_NET_HASH_REPORT_IPv4,
1692 VIRTIO_NET_HASH_REPORT_TCPv4,
1693 VIRTIO_NET_HASH_REPORT_TCPv6,
1694 VIRTIO_NET_HASH_REPORT_IPv6,
1695 VIRTIO_NET_HASH_REPORT_IPv6_EX,
1696 VIRTIO_NET_HASH_REPORT_TCPv6_EX,
1697 VIRTIO_NET_HASH_REPORT_UDPv4,
1698 VIRTIO_NET_HASH_REPORT_UDPv6,
1699 VIRTIO_NET_HASH_REPORT_UDPv6_EX
1700 };
Yuri Benditovich4474e372020-05-08 15:59:29 +03001701
1702 net_rx_pkt_set_protocols(pkt, buf + n->host_hdr_len,
1703 size - n->host_hdr_len);
1704 net_rx_pkt_get_protocols(pkt, &isip4, &isip6, &isudp, &istcp);
1705 if (isip4 && (net_rx_pkt_get_ip4_info(pkt)->fragment)) {
1706 istcp = isudp = false;
1707 }
1708 if (isip6 && (net_rx_pkt_get_ip6_info(pkt)->fragment)) {
1709 istcp = isudp = false;
1710 }
1711 net_hash_type = virtio_net_get_hash_type(isip4, isip6, isudp, istcp,
1712 n->rss_data.hash_types);
1713 if (net_hash_type > NetPktRssIpV6UdpEx) {
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001714 if (n->rss_data.populate_hash) {
1715 virtio_set_packet_hash(buf, VIRTIO_NET_HASH_REPORT_NONE, 0);
1716 }
1717 return n->rss_data.redirect ? n->rss_data.default_queue : -1;
Yuri Benditovich4474e372020-05-08 15:59:29 +03001718 }
1719
1720 hash = net_rx_pkt_calc_rss_hash(pkt, net_hash_type, n->rss_data.key);
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001721
1722 if (n->rss_data.populate_hash) {
1723 virtio_set_packet_hash(buf, reports[net_hash_type], hash);
Yuri Benditovich4474e372020-05-08 15:59:29 +03001724 }
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001725
1726 if (n->rss_data.redirect) {
1727 new_index = hash & (n->rss_data.indirections_len - 1);
1728 new_index = n->rss_data.indirections_table[new_index];
1729 }
1730
1731 return (index == new_index) ? -1 : new_index;
Yuri Benditovich4474e372020-05-08 15:59:29 +03001732}
1733
Paolo Bonzini97cd9652017-01-27 16:40:20 +01001734static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
Yuri Benditovich4474e372020-05-08 15:59:29 +03001735 size_t size, bool no_rss)
aliguorifbe78f42008-12-17 19:13:11 +00001736{
Jason Wangcc1f0f42013-01-30 19:12:23 +08001737 VirtIONet *n = qemu_get_nic_opaque(nc);
Jason Wangfed699f2013-01-30 19:12:39 +08001738 VirtIONetQueue *q = virtio_net_get_subqueue(nc);
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02001739 VirtIODevice *vdev = VIRTIO_DEVICE(n);
Jason Wangbedd7e92021-09-02 13:44:12 +08001740 VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE];
1741 size_t lens[VIRTQUEUE_MAX_SIZE];
Michael S. Tsirkin63c58722012-09-24 13:17:13 +02001742 struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE];
1743 struct virtio_net_hdr_mrg_rxbuf mhdr;
1744 unsigned mhdr_cnt = 0;
Jason Wangbedd7e92021-09-02 13:44:12 +08001745 size_t offset, i, guest_offset, j;
1746 ssize_t err;
aliguorifbe78f42008-12-17 19:13:11 +00001747
Jason Wangfed699f2013-01-30 19:12:39 +08001748 if (!virtio_net_can_receive(nc)) {
Mark McLoughlincdd5cc12009-10-27 18:16:38 +00001749 return -1;
Jason Wangb356f762013-01-30 19:12:22 +08001750 }
Mark McLoughlincdd5cc12009-10-27 18:16:38 +00001751
Andrew Melnychenko0145c392021-05-14 14:48:33 +03001752 if (!no_rss && n->rss_data.enabled && n->rss_data.enabled_software_rss) {
Yuri Benditovich4474e372020-05-08 15:59:29 +03001753 int index = virtio_net_process_rss(nc, buf, size);
1754 if (index >= 0) {
1755 NetClientState *nc2 = qemu_get_subqueue(n->nic, index);
1756 return virtio_net_receive_rcu(nc2, buf, size, true);
1757 }
1758 }
1759
Michael S. Tsirkin940cda92010-06-06 18:53:10 +03001760 /* hdr_len refers to the header we supply to the guest */
Jason Wang0c87e932013-01-30 19:12:38 +08001761 if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_len)) {
Mark McLoughlin8aeff622009-04-29 13:40:02 +01001762 return 0;
Jason Wang0c87e932013-01-30 19:12:38 +08001763 }
aliguorifbe78f42008-12-17 19:13:11 +00001764
aliguori3831ab22009-02-05 22:36:24 +00001765 if (!receive_filter(n, buf, size))
Mark McLoughlin4f1c9422009-05-18 13:40:55 +01001766 return size;
aliguori3831ab22009-02-05 22:36:24 +00001767
aliguorifbe78f42008-12-17 19:13:11 +00001768 offset = i = 0;
1769
1770 while (offset < size) {
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001771 VirtQueueElement *elem;
aliguorifbe78f42008-12-17 19:13:11 +00001772 int len, total;
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001773 const struct iovec *sg;
aliguorifbe78f42008-12-17 19:13:11 +00001774
Amit Shah22c253d2010-01-13 16:24:43 +05301775 total = 0;
aliguorifbe78f42008-12-17 19:13:11 +00001776
Jason Wangbedd7e92021-09-02 13:44:12 +08001777 if (i == VIRTQUEUE_MAX_SIZE) {
1778 virtio_error(vdev, "virtio-net unexpected long buffer chain");
1779 err = size;
1780 goto err;
1781 }
1782
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001783 elem = virtqueue_pop(q->rx_vq, sizeof(VirtQueueElement));
1784 if (!elem) {
Greg Kurzba10b9c2016-09-30 17:13:24 +02001785 if (i) {
1786 virtio_error(vdev, "virtio-net unexpected empty queue: "
1787 "i %zd mergeable %d offset %zd, size %zd, "
1788 "guest hdr len %zd, host hdr len %zd "
1789 "guest features 0x%" PRIx64,
1790 i, n->mergeable_rx_bufs, offset, size,
1791 n->guest_hdr_len, n->host_hdr_len,
1792 vdev->guest_features);
1793 }
Jason Wangbedd7e92021-09-02 13:44:12 +08001794 err = -1;
1795 goto err;
aliguorifbe78f42008-12-17 19:13:11 +00001796 }
1797
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001798 if (elem->in_num < 1) {
Greg Kurzba10b9c2016-09-30 17:13:24 +02001799 virtio_error(vdev,
1800 "virtio-net receive queue contains no in buffers");
1801 virtqueue_detach_element(q->rx_vq, elem, 0);
1802 g_free(elem);
Jason Wangbedd7e92021-09-02 13:44:12 +08001803 err = -1;
1804 goto err;
aliguorifbe78f42008-12-17 19:13:11 +00001805 }
1806
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001807 sg = elem->in_sg;
aliguorifbe78f42008-12-17 19:13:11 +00001808 if (i == 0) {
Michael S. Tsirkinc8d28e72012-09-24 13:26:55 +02001809 assert(offset == 0);
Michael S. Tsirkin63c58722012-09-24 13:17:13 +02001810 if (n->mergeable_rx_bufs) {
1811 mhdr_cnt = iov_copy(mhdr_sg, ARRAY_SIZE(mhdr_sg),
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001812 sg, elem->in_num,
Michael S. Tsirkin63c58722012-09-24 13:17:13 +02001813 offsetof(typeof(mhdr), num_buffers),
1814 sizeof(mhdr.num_buffers));
1815 }
aliguorifbe78f42008-12-17 19:13:11 +00001816
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001817 receive_header(n, sg, elem->in_num, buf, size);
Yuri Benditoviche22f0602020-05-08 15:59:31 +03001818 if (n->rss_data.populate_hash) {
1819 offset = sizeof(mhdr);
1820 iov_from_buf(sg, elem->in_num, offset,
1821 buf + offset, n->host_hdr_len - sizeof(mhdr));
1822 }
Michael S. Tsirkinc8d28e72012-09-24 13:26:55 +02001823 offset = n->host_hdr_len;
Michael S. Tsirkine35e23f2012-09-24 12:12:25 +02001824 total += n->guest_hdr_len;
Michael S. Tsirkin22cc84d2012-09-24 13:14:16 +02001825 guest_offset = n->guest_hdr_len;
1826 } else {
1827 guest_offset = 0;
aliguorifbe78f42008-12-17 19:13:11 +00001828 }
1829
1830 /* copy in packet. ugh */
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001831 len = iov_from_buf(sg, elem->in_num, guest_offset,
Michael Tokarevdcf6f5e2012-03-11 18:05:12 +04001832 buf + offset, size - offset);
aliguorifbe78f42008-12-17 19:13:11 +00001833 total += len;
Michael S. Tsirkin279a4252010-06-22 16:22:49 +03001834 offset += len;
1835 /* If buffers can't be merged, at this point we
1836 * must have consumed the complete packet.
1837 * Otherwise, drop it. */
1838 if (!n->mergeable_rx_bufs && offset < size) {
Ladi Prosek27e57ef2016-11-03 09:55:49 +01001839 virtqueue_unpop(q->rx_vq, elem, total);
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02001840 g_free(elem);
Jason Wangbedd7e92021-09-02 13:44:12 +08001841 err = size;
1842 goto err;
Michael S. Tsirkin279a4252010-06-22 16:22:49 +03001843 }
aliguorifbe78f42008-12-17 19:13:11 +00001844
Jason Wangbedd7e92021-09-02 13:44:12 +08001845 elems[i] = elem;
1846 lens[i] = total;
1847 i++;
aliguorifbe78f42008-12-17 19:13:11 +00001848 }
1849
Michael S. Tsirkin63c58722012-09-24 13:17:13 +02001850 if (mhdr_cnt) {
Rusty Russell1399c602014-06-24 19:42:54 +02001851 virtio_stw_p(vdev, &mhdr.num_buffers, i);
Michael S. Tsirkin63c58722012-09-24 13:17:13 +02001852 iov_from_buf(mhdr_sg, mhdr_cnt,
1853 0,
1854 &mhdr.num_buffers, sizeof mhdr.num_buffers);
Aurelien Jarno44b15bc2011-01-25 11:55:14 +01001855 }
aliguorifbe78f42008-12-17 19:13:11 +00001856
Jason Wangbedd7e92021-09-02 13:44:12 +08001857 for (j = 0; j < i; j++) {
1858 /* signal other side */
1859 virtqueue_fill(q->rx_vq, elems[j], lens[j], j);
1860 g_free(elems[j]);
1861 }
1862
Jason Wang0c87e932013-01-30 19:12:38 +08001863 virtqueue_flush(q->rx_vq, i);
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02001864 virtio_notify(vdev, q->rx_vq);
Mark McLoughlin4f1c9422009-05-18 13:40:55 +01001865
1866 return size;
Jason Wangbedd7e92021-09-02 13:44:12 +08001867
1868err:
1869 for (j = 0; j < i; j++) {
1870 g_free(elems[j]);
1871 }
1872
1873 return err;
aliguorifbe78f42008-12-17 19:13:11 +00001874}
1875
Yuri Benditovich2974e912019-01-03 15:12:29 +02001876static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf,
Paolo Bonzini97cd9652017-01-27 16:40:20 +01001877 size_t size)
1878{
Dr. David Alan Gilbert068ddfa2019-10-25 11:34:03 +01001879 RCU_READ_LOCK_GUARD();
Paolo Bonzini97cd9652017-01-27 16:40:20 +01001880
Yuri Benditovich4474e372020-05-08 15:59:29 +03001881 return virtio_net_receive_rcu(nc, buf, size, false);
Paolo Bonzini97cd9652017-01-27 16:40:20 +01001882}
1883
Yuri Benditovich2974e912019-01-03 15:12:29 +02001884static void virtio_net_rsc_extract_unit4(VirtioNetRscChain *chain,
1885 const uint8_t *buf,
1886 VirtioNetRscUnit *unit)
1887{
1888 uint16_t ip_hdrlen;
1889 struct ip_header *ip;
1890
1891 ip = (struct ip_header *)(buf + chain->n->guest_hdr_len
1892 + sizeof(struct eth_header));
1893 unit->ip = (void *)ip;
1894 ip_hdrlen = (ip->ip_ver_len & 0xF) << 2;
1895 unit->ip_plen = &ip->ip_len;
1896 unit->tcp = (struct tcp_header *)(((uint8_t *)unit->ip) + ip_hdrlen);
1897 unit->tcp_hdrlen = (htons(unit->tcp->th_offset_flags) & 0xF000) >> 10;
1898 unit->payload = htons(*unit->ip_plen) - ip_hdrlen - unit->tcp_hdrlen;
1899}
1900
1901static void virtio_net_rsc_extract_unit6(VirtioNetRscChain *chain,
1902 const uint8_t *buf,
1903 VirtioNetRscUnit *unit)
1904{
1905 struct ip6_header *ip6;
1906
1907 ip6 = (struct ip6_header *)(buf + chain->n->guest_hdr_len
1908 + sizeof(struct eth_header));
1909 unit->ip = ip6;
1910 unit->ip_plen = &(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
Philippe Mathieu-Daudé78ee6bd2020-04-13 00:35:56 +02001911 unit->tcp = (struct tcp_header *)(((uint8_t *)unit->ip)
Yuri Benditovich2974e912019-01-03 15:12:29 +02001912 + sizeof(struct ip6_header));
1913 unit->tcp_hdrlen = (htons(unit->tcp->th_offset_flags) & 0xF000) >> 10;
1914
1915 /* There is a difference between payload lenght in ipv4 and v6,
1916 ip header is excluded in ipv6 */
1917 unit->payload = htons(*unit->ip_plen) - unit->tcp_hdrlen;
1918}
1919
1920static size_t virtio_net_rsc_drain_seg(VirtioNetRscChain *chain,
1921 VirtioNetRscSeg *seg)
1922{
1923 int ret;
Yuri Benditovichdd3d85e2020-05-08 15:59:34 +03001924 struct virtio_net_hdr_v1 *h;
Yuri Benditovich2974e912019-01-03 15:12:29 +02001925
Yuri Benditovichdd3d85e2020-05-08 15:59:34 +03001926 h = (struct virtio_net_hdr_v1 *)seg->buf;
Yuri Benditovich2974e912019-01-03 15:12:29 +02001927 h->flags = 0;
1928 h->gso_type = VIRTIO_NET_HDR_GSO_NONE;
1929
1930 if (seg->is_coalesced) {
Yuri Benditovichdd3d85e2020-05-08 15:59:34 +03001931 h->rsc.segments = seg->packets;
1932 h->rsc.dup_acks = seg->dup_ack;
Yuri Benditovich2974e912019-01-03 15:12:29 +02001933 h->flags = VIRTIO_NET_HDR_F_RSC_INFO;
1934 if (chain->proto == ETH_P_IP) {
1935 h->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
1936 } else {
1937 h->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
1938 }
1939 }
1940
1941 ret = virtio_net_do_receive(seg->nc, seg->buf, seg->size);
1942 QTAILQ_REMOVE(&chain->buffers, seg, next);
1943 g_free(seg->buf);
1944 g_free(seg);
1945
1946 return ret;
1947}
1948
1949static void virtio_net_rsc_purge(void *opq)
1950{
1951 VirtioNetRscSeg *seg, *rn;
1952 VirtioNetRscChain *chain = (VirtioNetRscChain *)opq;
1953
1954 QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, rn) {
1955 if (virtio_net_rsc_drain_seg(chain, seg) == 0) {
1956 chain->stat.purge_failed++;
1957 continue;
1958 }
1959 }
1960
1961 chain->stat.timer++;
1962 if (!QTAILQ_EMPTY(&chain->buffers)) {
1963 timer_mod(chain->drain_timer,
1964 qemu_clock_get_ns(QEMU_CLOCK_HOST) + chain->n->rsc_timeout);
1965 }
1966}
1967
1968static void virtio_net_rsc_cleanup(VirtIONet *n)
1969{
1970 VirtioNetRscChain *chain, *rn_chain;
1971 VirtioNetRscSeg *seg, *rn_seg;
1972
1973 QTAILQ_FOREACH_SAFE(chain, &n->rsc_chains, next, rn_chain) {
1974 QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, rn_seg) {
1975 QTAILQ_REMOVE(&chain->buffers, seg, next);
1976 g_free(seg->buf);
1977 g_free(seg);
1978 }
1979
Yuri Benditovich2974e912019-01-03 15:12:29 +02001980 timer_free(chain->drain_timer);
1981 QTAILQ_REMOVE(&n->rsc_chains, chain, next);
1982 g_free(chain);
1983 }
1984}
1985
1986static void virtio_net_rsc_cache_buf(VirtioNetRscChain *chain,
1987 NetClientState *nc,
1988 const uint8_t *buf, size_t size)
1989{
1990 uint16_t hdr_len;
1991 VirtioNetRscSeg *seg;
1992
1993 hdr_len = chain->n->guest_hdr_len;
1994 seg = g_malloc(sizeof(VirtioNetRscSeg));
1995 seg->buf = g_malloc(hdr_len + sizeof(struct eth_header)
1996 + sizeof(struct ip6_header) + VIRTIO_NET_MAX_TCP_PAYLOAD);
1997 memcpy(seg->buf, buf, size);
1998 seg->size = size;
1999 seg->packets = 1;
2000 seg->dup_ack = 0;
2001 seg->is_coalesced = 0;
2002 seg->nc = nc;
2003
2004 QTAILQ_INSERT_TAIL(&chain->buffers, seg, next);
2005 chain->stat.cache++;
2006
2007 switch (chain->proto) {
2008 case ETH_P_IP:
2009 virtio_net_rsc_extract_unit4(chain, seg->buf, &seg->unit);
2010 break;
2011 case ETH_P_IPV6:
2012 virtio_net_rsc_extract_unit6(chain, seg->buf, &seg->unit);
2013 break;
2014 default:
2015 g_assert_not_reached();
2016 }
2017}
2018
2019static int32_t virtio_net_rsc_handle_ack(VirtioNetRscChain *chain,
2020 VirtioNetRscSeg *seg,
2021 const uint8_t *buf,
2022 struct tcp_header *n_tcp,
2023 struct tcp_header *o_tcp)
2024{
2025 uint32_t nack, oack;
2026 uint16_t nwin, owin;
2027
2028 nack = htonl(n_tcp->th_ack);
2029 nwin = htons(n_tcp->th_win);
2030 oack = htonl(o_tcp->th_ack);
2031 owin = htons(o_tcp->th_win);
2032
2033 if ((nack - oack) >= VIRTIO_NET_MAX_TCP_PAYLOAD) {
2034 chain->stat.ack_out_of_win++;
2035 return RSC_FINAL;
2036 } else if (nack == oack) {
2037 /* duplicated ack or window probe */
2038 if (nwin == owin) {
2039 /* duplicated ack, add dup ack count due to whql test up to 1 */
2040 chain->stat.dup_ack++;
2041 return RSC_FINAL;
2042 } else {
2043 /* Coalesce window update */
2044 o_tcp->th_win = n_tcp->th_win;
2045 chain->stat.win_update++;
2046 return RSC_COALESCE;
2047 }
2048 } else {
2049 /* pure ack, go to 'C', finalize*/
2050 chain->stat.pure_ack++;
2051 return RSC_FINAL;
2052 }
2053}
2054
2055static int32_t virtio_net_rsc_coalesce_data(VirtioNetRscChain *chain,
2056 VirtioNetRscSeg *seg,
2057 const uint8_t *buf,
2058 VirtioNetRscUnit *n_unit)
2059{
2060 void *data;
2061 uint16_t o_ip_len;
2062 uint32_t nseq, oseq;
2063 VirtioNetRscUnit *o_unit;
2064
2065 o_unit = &seg->unit;
2066 o_ip_len = htons(*o_unit->ip_plen);
2067 nseq = htonl(n_unit->tcp->th_seq);
2068 oseq = htonl(o_unit->tcp->th_seq);
2069
2070 /* out of order or retransmitted. */
2071 if ((nseq - oseq) > VIRTIO_NET_MAX_TCP_PAYLOAD) {
2072 chain->stat.data_out_of_win++;
2073 return RSC_FINAL;
2074 }
2075
2076 data = ((uint8_t *)n_unit->tcp) + n_unit->tcp_hdrlen;
2077 if (nseq == oseq) {
2078 if ((o_unit->payload == 0) && n_unit->payload) {
2079 /* From no payload to payload, normal case, not a dup ack or etc */
2080 chain->stat.data_after_pure_ack++;
2081 goto coalesce;
2082 } else {
2083 return virtio_net_rsc_handle_ack(chain, seg, buf,
2084 n_unit->tcp, o_unit->tcp);
2085 }
2086 } else if ((nseq - oseq) != o_unit->payload) {
2087 /* Not a consistent packet, out of order */
2088 chain->stat.data_out_of_order++;
2089 return RSC_FINAL;
2090 } else {
2091coalesce:
2092 if ((o_ip_len + n_unit->payload) > chain->max_payload) {
2093 chain->stat.over_size++;
2094 return RSC_FINAL;
2095 }
2096
2097 /* Here comes the right data, the payload length in v4/v6 is different,
2098 so use the field value to update and record the new data len */
2099 o_unit->payload += n_unit->payload; /* update new data len */
2100
2101 /* update field in ip header */
2102 *o_unit->ip_plen = htons(o_ip_len + n_unit->payload);
2103
2104 /* Bring 'PUSH' big, the whql test guide says 'PUSH' can be coalesced
2105 for windows guest, while this may change the behavior for linux
2106 guest (only if it uses RSC feature). */
2107 o_unit->tcp->th_offset_flags = n_unit->tcp->th_offset_flags;
2108
2109 o_unit->tcp->th_ack = n_unit->tcp->th_ack;
2110 o_unit->tcp->th_win = n_unit->tcp->th_win;
2111
2112 memmove(seg->buf + seg->size, data, n_unit->payload);
2113 seg->size += n_unit->payload;
2114 seg->packets++;
2115 chain->stat.coalesced++;
2116 return RSC_COALESCE;
2117 }
2118}
2119
2120static int32_t virtio_net_rsc_coalesce4(VirtioNetRscChain *chain,
2121 VirtioNetRscSeg *seg,
2122 const uint8_t *buf, size_t size,
2123 VirtioNetRscUnit *unit)
2124{
2125 struct ip_header *ip1, *ip2;
2126
2127 ip1 = (struct ip_header *)(unit->ip);
2128 ip2 = (struct ip_header *)(seg->unit.ip);
2129 if ((ip1->ip_src ^ ip2->ip_src) || (ip1->ip_dst ^ ip2->ip_dst)
2130 || (unit->tcp->th_sport ^ seg->unit.tcp->th_sport)
2131 || (unit->tcp->th_dport ^ seg->unit.tcp->th_dport)) {
2132 chain->stat.no_match++;
2133 return RSC_NO_MATCH;
2134 }
2135
2136 return virtio_net_rsc_coalesce_data(chain, seg, buf, unit);
2137}
2138
2139static int32_t virtio_net_rsc_coalesce6(VirtioNetRscChain *chain,
2140 VirtioNetRscSeg *seg,
2141 const uint8_t *buf, size_t size,
2142 VirtioNetRscUnit *unit)
2143{
2144 struct ip6_header *ip1, *ip2;
2145
2146 ip1 = (struct ip6_header *)(unit->ip);
2147 ip2 = (struct ip6_header *)(seg->unit.ip);
2148 if (memcmp(&ip1->ip6_src, &ip2->ip6_src, sizeof(struct in6_address))
2149 || memcmp(&ip1->ip6_dst, &ip2->ip6_dst, sizeof(struct in6_address))
2150 || (unit->tcp->th_sport ^ seg->unit.tcp->th_sport)
2151 || (unit->tcp->th_dport ^ seg->unit.tcp->th_dport)) {
2152 chain->stat.no_match++;
2153 return RSC_NO_MATCH;
2154 }
2155
2156 return virtio_net_rsc_coalesce_data(chain, seg, buf, unit);
2157}
2158
2159/* Packets with 'SYN' should bypass, other flag should be sent after drain
2160 * to prevent out of order */
2161static int virtio_net_rsc_tcp_ctrl_check(VirtioNetRscChain *chain,
2162 struct tcp_header *tcp)
2163{
2164 uint16_t tcp_hdr;
2165 uint16_t tcp_flag;
2166
2167 tcp_flag = htons(tcp->th_offset_flags);
2168 tcp_hdr = (tcp_flag & VIRTIO_NET_TCP_HDR_LENGTH) >> 10;
2169 tcp_flag &= VIRTIO_NET_TCP_FLAG;
Yuri Benditovich2974e912019-01-03 15:12:29 +02002170 if (tcp_flag & TH_SYN) {
2171 chain->stat.tcp_syn++;
2172 return RSC_BYPASS;
2173 }
2174
2175 if (tcp_flag & (TH_FIN | TH_URG | TH_RST | TH_ECE | TH_CWR)) {
2176 chain->stat.tcp_ctrl_drain++;
2177 return RSC_FINAL;
2178 }
2179
2180 if (tcp_hdr > sizeof(struct tcp_header)) {
2181 chain->stat.tcp_all_opt++;
2182 return RSC_FINAL;
2183 }
2184
2185 return RSC_CANDIDATE;
2186}
2187
2188static size_t virtio_net_rsc_do_coalesce(VirtioNetRscChain *chain,
2189 NetClientState *nc,
2190 const uint8_t *buf, size_t size,
2191 VirtioNetRscUnit *unit)
2192{
2193 int ret;
2194 VirtioNetRscSeg *seg, *nseg;
2195
2196 if (QTAILQ_EMPTY(&chain->buffers)) {
2197 chain->stat.empty_cache++;
2198 virtio_net_rsc_cache_buf(chain, nc, buf, size);
2199 timer_mod(chain->drain_timer,
2200 qemu_clock_get_ns(QEMU_CLOCK_HOST) + chain->n->rsc_timeout);
2201 return size;
2202 }
2203
2204 QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, nseg) {
2205 if (chain->proto == ETH_P_IP) {
2206 ret = virtio_net_rsc_coalesce4(chain, seg, buf, size, unit);
2207 } else {
2208 ret = virtio_net_rsc_coalesce6(chain, seg, buf, size, unit);
2209 }
2210
2211 if (ret == RSC_FINAL) {
2212 if (virtio_net_rsc_drain_seg(chain, seg) == 0) {
2213 /* Send failed */
2214 chain->stat.final_failed++;
2215 return 0;
2216 }
2217
2218 /* Send current packet */
2219 return virtio_net_do_receive(nc, buf, size);
2220 } else if (ret == RSC_NO_MATCH) {
2221 continue;
2222 } else {
2223 /* Coalesced, mark coalesced flag to tell calc cksum for ipv4 */
2224 seg->is_coalesced = 1;
2225 return size;
2226 }
2227 }
2228
2229 chain->stat.no_match_cache++;
2230 virtio_net_rsc_cache_buf(chain, nc, buf, size);
2231 return size;
2232}
2233
2234/* Drain a connection data, this is to avoid out of order segments */
2235static size_t virtio_net_rsc_drain_flow(VirtioNetRscChain *chain,
2236 NetClientState *nc,
2237 const uint8_t *buf, size_t size,
2238 uint16_t ip_start, uint16_t ip_size,
2239 uint16_t tcp_port)
2240{
2241 VirtioNetRscSeg *seg, *nseg;
2242 uint32_t ppair1, ppair2;
2243
2244 ppair1 = *(uint32_t *)(buf + tcp_port);
2245 QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, nseg) {
2246 ppair2 = *(uint32_t *)(seg->buf + tcp_port);
2247 if (memcmp(buf + ip_start, seg->buf + ip_start, ip_size)
2248 || (ppair1 != ppair2)) {
2249 continue;
2250 }
2251 if (virtio_net_rsc_drain_seg(chain, seg) == 0) {
2252 chain->stat.drain_failed++;
2253 }
2254
2255 break;
2256 }
2257
2258 return virtio_net_do_receive(nc, buf, size);
2259}
2260
2261static int32_t virtio_net_rsc_sanity_check4(VirtioNetRscChain *chain,
2262 struct ip_header *ip,
2263 const uint8_t *buf, size_t size)
2264{
2265 uint16_t ip_len;
2266
2267 /* Not an ipv4 packet */
2268 if (((ip->ip_ver_len & 0xF0) >> 4) != IP_HEADER_VERSION_4) {
2269 chain->stat.ip_option++;
2270 return RSC_BYPASS;
2271 }
2272
2273 /* Don't handle packets with ip option */
2274 if ((ip->ip_ver_len & 0xF) != VIRTIO_NET_IP4_HEADER_LENGTH) {
2275 chain->stat.ip_option++;
2276 return RSC_BYPASS;
2277 }
2278
2279 if (ip->ip_p != IPPROTO_TCP) {
2280 chain->stat.bypass_not_tcp++;
2281 return RSC_BYPASS;
2282 }
2283
2284 /* Don't handle packets with ip fragment */
2285 if (!(htons(ip->ip_off) & IP_DF)) {
2286 chain->stat.ip_frag++;
2287 return RSC_BYPASS;
2288 }
2289
2290 /* Don't handle packets with ecn flag */
2291 if (IPTOS_ECN(ip->ip_tos)) {
2292 chain->stat.ip_ecn++;
2293 return RSC_BYPASS;
2294 }
2295
2296 ip_len = htons(ip->ip_len);
2297 if (ip_len < (sizeof(struct ip_header) + sizeof(struct tcp_header))
2298 || ip_len > (size - chain->n->guest_hdr_len -
2299 sizeof(struct eth_header))) {
2300 chain->stat.ip_hacked++;
2301 return RSC_BYPASS;
2302 }
2303
2304 return RSC_CANDIDATE;
2305}
2306
2307static size_t virtio_net_rsc_receive4(VirtioNetRscChain *chain,
2308 NetClientState *nc,
2309 const uint8_t *buf, size_t size)
2310{
2311 int32_t ret;
2312 uint16_t hdr_len;
2313 VirtioNetRscUnit unit;
2314
2315 hdr_len = ((VirtIONet *)(chain->n))->guest_hdr_len;
2316
2317 if (size < (hdr_len + sizeof(struct eth_header) + sizeof(struct ip_header)
2318 + sizeof(struct tcp_header))) {
2319 chain->stat.bypass_not_tcp++;
2320 return virtio_net_do_receive(nc, buf, size);
2321 }
2322
2323 virtio_net_rsc_extract_unit4(chain, buf, &unit);
2324 if (virtio_net_rsc_sanity_check4(chain, unit.ip, buf, size)
2325 != RSC_CANDIDATE) {
2326 return virtio_net_do_receive(nc, buf, size);
2327 }
2328
2329 ret = virtio_net_rsc_tcp_ctrl_check(chain, unit.tcp);
2330 if (ret == RSC_BYPASS) {
2331 return virtio_net_do_receive(nc, buf, size);
2332 } else if (ret == RSC_FINAL) {
2333 return virtio_net_rsc_drain_flow(chain, nc, buf, size,
2334 ((hdr_len + sizeof(struct eth_header)) + 12),
2335 VIRTIO_NET_IP4_ADDR_SIZE,
2336 hdr_len + sizeof(struct eth_header) + sizeof(struct ip_header));
2337 }
2338
2339 return virtio_net_rsc_do_coalesce(chain, nc, buf, size, &unit);
2340}
2341
2342static int32_t virtio_net_rsc_sanity_check6(VirtioNetRscChain *chain,
2343 struct ip6_header *ip6,
2344 const uint8_t *buf, size_t size)
2345{
2346 uint16_t ip_len;
2347
2348 if (((ip6->ip6_ctlun.ip6_un1.ip6_un1_flow & 0xF0) >> 4)
2349 != IP_HEADER_VERSION_6) {
2350 return RSC_BYPASS;
2351 }
2352
2353 /* Both option and protocol is checked in this */
2354 if (ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt != IPPROTO_TCP) {
2355 chain->stat.bypass_not_tcp++;
2356 return RSC_BYPASS;
2357 }
2358
2359 ip_len = htons(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
2360 if (ip_len < sizeof(struct tcp_header) ||
2361 ip_len > (size - chain->n->guest_hdr_len - sizeof(struct eth_header)
2362 - sizeof(struct ip6_header))) {
2363 chain->stat.ip_hacked++;
2364 return RSC_BYPASS;
2365 }
2366
2367 /* Don't handle packets with ecn flag */
2368 if (IP6_ECN(ip6->ip6_ctlun.ip6_un3.ip6_un3_ecn)) {
2369 chain->stat.ip_ecn++;
2370 return RSC_BYPASS;
2371 }
2372
2373 return RSC_CANDIDATE;
2374}
2375
2376static size_t virtio_net_rsc_receive6(void *opq, NetClientState *nc,
2377 const uint8_t *buf, size_t size)
2378{
2379 int32_t ret;
2380 uint16_t hdr_len;
2381 VirtioNetRscChain *chain;
2382 VirtioNetRscUnit unit;
2383
2384 chain = (VirtioNetRscChain *)opq;
2385 hdr_len = ((VirtIONet *)(chain->n))->guest_hdr_len;
2386
2387 if (size < (hdr_len + sizeof(struct eth_header) + sizeof(struct ip6_header)
2388 + sizeof(tcp_header))) {
2389 return virtio_net_do_receive(nc, buf, size);
2390 }
2391
2392 virtio_net_rsc_extract_unit6(chain, buf, &unit);
2393 if (RSC_CANDIDATE != virtio_net_rsc_sanity_check6(chain,
2394 unit.ip, buf, size)) {
2395 return virtio_net_do_receive(nc, buf, size);
2396 }
2397
2398 ret = virtio_net_rsc_tcp_ctrl_check(chain, unit.tcp);
2399 if (ret == RSC_BYPASS) {
2400 return virtio_net_do_receive(nc, buf, size);
2401 } else if (ret == RSC_FINAL) {
2402 return virtio_net_rsc_drain_flow(chain, nc, buf, size,
2403 ((hdr_len + sizeof(struct eth_header)) + 8),
2404 VIRTIO_NET_IP6_ADDR_SIZE,
2405 hdr_len + sizeof(struct eth_header)
2406 + sizeof(struct ip6_header));
2407 }
2408
2409 return virtio_net_rsc_do_coalesce(chain, nc, buf, size, &unit);
2410}
2411
2412static VirtioNetRscChain *virtio_net_rsc_lookup_chain(VirtIONet *n,
2413 NetClientState *nc,
2414 uint16_t proto)
2415{
2416 VirtioNetRscChain *chain;
2417
2418 if ((proto != (uint16_t)ETH_P_IP) && (proto != (uint16_t)ETH_P_IPV6)) {
2419 return NULL;
2420 }
2421
2422 QTAILQ_FOREACH(chain, &n->rsc_chains, next) {
2423 if (chain->proto == proto) {
2424 return chain;
2425 }
2426 }
2427
2428 chain = g_malloc(sizeof(*chain));
2429 chain->n = n;
2430 chain->proto = proto;
2431 if (proto == (uint16_t)ETH_P_IP) {
2432 chain->max_payload = VIRTIO_NET_MAX_IP4_PAYLOAD;
2433 chain->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
2434 } else {
2435 chain->max_payload = VIRTIO_NET_MAX_IP6_PAYLOAD;
2436 chain->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
2437 }
2438 chain->drain_timer = timer_new_ns(QEMU_CLOCK_HOST,
2439 virtio_net_rsc_purge, chain);
2440 memset(&chain->stat, 0, sizeof(chain->stat));
2441
2442 QTAILQ_INIT(&chain->buffers);
2443 QTAILQ_INSERT_TAIL(&n->rsc_chains, chain, next);
2444
2445 return chain;
2446}
2447
2448static ssize_t virtio_net_rsc_receive(NetClientState *nc,
2449 const uint8_t *buf,
2450 size_t size)
2451{
2452 uint16_t proto;
2453 VirtioNetRscChain *chain;
2454 struct eth_header *eth;
2455 VirtIONet *n;
2456
2457 n = qemu_get_nic_opaque(nc);
2458 if (size < (n->host_hdr_len + sizeof(struct eth_header))) {
2459 return virtio_net_do_receive(nc, buf, size);
2460 }
2461
2462 eth = (struct eth_header *)(buf + n->guest_hdr_len);
2463 proto = htons(eth->h_proto);
2464
2465 chain = virtio_net_rsc_lookup_chain(n, nc, proto);
2466 if (chain) {
2467 chain->stat.received++;
2468 if (proto == (uint16_t)ETH_P_IP && n->rsc4_enabled) {
2469 return virtio_net_rsc_receive4(chain, nc, buf, size);
2470 } else if (proto == (uint16_t)ETH_P_IPV6 && n->rsc6_enabled) {
2471 return virtio_net_rsc_receive6(chain, nc, buf, size);
2472 }
2473 }
2474 return virtio_net_do_receive(nc, buf, size);
2475}
2476
2477static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf,
2478 size_t size)
2479{
2480 VirtIONet *n = qemu_get_nic_opaque(nc);
2481 if ((n->rsc4_enabled || n->rsc6_enabled)) {
2482 return virtio_net_rsc_receive(nc, buf, size);
2483 } else {
2484 return virtio_net_do_receive(nc, buf, size);
2485 }
2486}
2487
Jason Wang0c87e932013-01-30 19:12:38 +08002488static int32_t virtio_net_flush_tx(VirtIONetQueue *q);
Mark McLoughlin62433752009-06-18 18:21:36 +01002489
Stefan Hajnoczi4e68f7a2012-07-24 16:35:13 +01002490static void virtio_net_tx_complete(NetClientState *nc, ssize_t len)
Mark McLoughlin62433752009-06-18 18:21:36 +01002491{
Jason Wangcc1f0f42013-01-30 19:12:23 +08002492 VirtIONet *n = qemu_get_nic_opaque(nc);
Jason Wangfed699f2013-01-30 19:12:39 +08002493 VirtIONetQueue *q = virtio_net_get_subqueue(nc);
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002494 VirtIODevice *vdev = VIRTIO_DEVICE(n);
Mark McLoughlin62433752009-06-18 18:21:36 +01002495
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02002496 virtqueue_push(q->tx_vq, q->async_tx.elem, 0);
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002497 virtio_notify(vdev, q->tx_vq);
Mark McLoughlin62433752009-06-18 18:21:36 +01002498
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02002499 g_free(q->async_tx.elem);
2500 q->async_tx.elem = NULL;
Mark McLoughlin62433752009-06-18 18:21:36 +01002501
Jason Wang0c87e932013-01-30 19:12:38 +08002502 virtio_queue_set_notification(q->tx_vq, 1);
2503 virtio_net_flush_tx(q);
Mark McLoughlin62433752009-06-18 18:21:36 +01002504}
2505
aliguorifbe78f42008-12-17 19:13:11 +00002506/* TX */
Jason Wang0c87e932013-01-30 19:12:38 +08002507static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
aliguorifbe78f42008-12-17 19:13:11 +00002508{
Jason Wang0c87e932013-01-30 19:12:38 +08002509 VirtIONet *n = q->n;
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002510 VirtIODevice *vdev = VIRTIO_DEVICE(n);
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02002511 VirtQueueElement *elem;
Alex Williamsone3f30482010-09-02 09:00:57 -06002512 int32_t num_packets = 0;
Jason Wangfed699f2013-01-30 19:12:39 +08002513 int queue_index = vq2q(virtio_get_queue_index(q->tx_vq));
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002514 if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
Alex Williamsone3f30482010-09-02 09:00:57 -06002515 return num_packets;
2516 }
aliguorifbe78f42008-12-17 19:13:11 +00002517
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02002518 if (q->async_tx.elem) {
Jason Wang0c87e932013-01-30 19:12:38 +08002519 virtio_queue_set_notification(q->tx_vq, 0);
Alex Williamsone3f30482010-09-02 09:00:57 -06002520 return num_packets;
Mark McLoughlin62433752009-06-18 18:21:36 +01002521 }
2522
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02002523 for (;;) {
Jason Wangbd89dd92015-08-03 13:20:38 +08002524 ssize_t ret;
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02002525 unsigned int out_num;
2526 struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1], *out_sg;
Jason Wangfeb93f32015-07-17 15:19:18 +08002527 struct virtio_net_hdr_mrg_rxbuf mhdr;
aliguorifbe78f42008-12-17 19:13:11 +00002528
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02002529 elem = virtqueue_pop(q->tx_vq, sizeof(VirtQueueElement));
2530 if (!elem) {
2531 break;
2532 }
2533
2534 out_num = elem->out_num;
2535 out_sg = elem->out_sg;
Michael S. Tsirkin7b80d082012-09-24 14:54:44 +02002536 if (out_num < 1) {
Greg Kurzfa5e56c2016-09-30 17:13:32 +02002537 virtio_error(vdev, "virtio-net header not in first element");
2538 virtqueue_detach_element(q->tx_vq, elem, 0);
2539 g_free(elem);
2540 return -EINVAL;
aliguorifbe78f42008-12-17 19:13:11 +00002541 }
2542
Cédric Le Goater032a74a2014-06-24 19:11:32 +02002543 if (n->has_vnet_hdr) {
Jason Wangfeb93f32015-07-17 15:19:18 +08002544 if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) <
2545 n->guest_hdr_len) {
Greg Kurzfa5e56c2016-09-30 17:13:32 +02002546 virtio_error(vdev, "virtio-net header incorrect");
2547 virtqueue_detach_element(q->tx_vq, elem, 0);
2548 g_free(elem);
2549 return -EINVAL;
Cédric Le Goater032a74a2014-06-24 19:11:32 +02002550 }
Greg Kurz1bfa3162016-02-05 11:43:11 +01002551 if (n->needs_vnet_hdr_swap) {
Jason Wangfeb93f32015-07-17 15:19:18 +08002552 virtio_net_hdr_swap(vdev, (void *) &mhdr);
2553 sg2[0].iov_base = &mhdr;
2554 sg2[0].iov_len = n->guest_hdr_len;
2555 out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1,
2556 out_sg, out_num,
2557 n->guest_hdr_len, -1);
2558 if (out_num == VIRTQUEUE_MAX_SIZE) {
2559 goto drop;
Paolo Bonzini7d374352018-12-13 23:37:37 +01002560 }
Jason Wangfeb93f32015-07-17 15:19:18 +08002561 out_num += 1;
2562 out_sg = sg2;
Paolo Bonzini7d374352018-12-13 23:37:37 +01002563 }
Cédric Le Goater032a74a2014-06-24 19:11:32 +02002564 }
Michael S. Tsirkin14761f92012-09-24 14:52:28 +02002565 /*
2566 * If host wants to see the guest header as is, we can
2567 * pass it on unchanged. Otherwise, copy just the parts
2568 * that host is interested in.
2569 */
2570 assert(n->host_hdr_len <= n->guest_hdr_len);
2571 if (n->host_hdr_len != n->guest_hdr_len) {
2572 unsigned sg_num = iov_copy(sg, ARRAY_SIZE(sg),
2573 out_sg, out_num,
2574 0, n->host_hdr_len);
2575 sg_num += iov_copy(sg + sg_num, ARRAY_SIZE(sg) - sg_num,
2576 out_sg, out_num,
2577 n->guest_hdr_len, -1);
2578 out_num = sg_num;
2579 out_sg = sg;
aliguorifbe78f42008-12-17 19:13:11 +00002580 }
2581
Jason Wangfed699f2013-01-30 19:12:39 +08002582 ret = qemu_sendv_packet_async(qemu_get_subqueue(n->nic, queue_index),
2583 out_sg, out_num, virtio_net_tx_complete);
Mark McLoughlin62433752009-06-18 18:21:36 +01002584 if (ret == 0) {
Jason Wang0c87e932013-01-30 19:12:38 +08002585 virtio_queue_set_notification(q->tx_vq, 0);
2586 q->async_tx.elem = elem;
Alex Williamsone3f30482010-09-02 09:00:57 -06002587 return -EBUSY;
Mark McLoughlin62433752009-06-18 18:21:36 +01002588 }
2589
Jason Wangfeb93f32015-07-17 15:19:18 +08002590drop:
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02002591 virtqueue_push(q->tx_vq, elem, 0);
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002592 virtio_notify(vdev, q->tx_vq);
Paolo Bonzini51b19eb2016-02-04 16:26:51 +02002593 g_free(elem);
Alex Williamsone3f30482010-09-02 09:00:57 -06002594
2595 if (++num_packets >= n->tx_burst) {
2596 break;
2597 }
aliguorifbe78f42008-12-17 19:13:11 +00002598 }
Alex Williamsone3f30482010-09-02 09:00:57 -06002599 return num_packets;
aliguorifbe78f42008-12-17 19:13:11 +00002600}
2601
Alex Williamsona697a332010-09-02 09:01:10 -06002602static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq)
aliguorifbe78f42008-12-17 19:13:11 +00002603{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002604 VirtIONet *n = VIRTIO_NET(vdev);
Jason Wangfed699f2013-01-30 19:12:39 +08002605 VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))];
aliguorifbe78f42008-12-17 19:13:11 +00002606
Yuri Benditovich283e2c22016-12-13 10:12:08 +02002607 if (unlikely((n->status & VIRTIO_NET_S_LINK_UP) == 0)) {
2608 virtio_net_drop_tx_queue_data(vdev, vq);
2609 return;
2610 }
2611
Michael S. Tsirkin783e7702010-11-22 19:52:30 +02002612 /* This happens when device was stopped but VCPU wasn't. */
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002613 if (!vdev->vm_running) {
Jason Wang0c87e932013-01-30 19:12:38 +08002614 q->tx_waiting = 1;
Michael S. Tsirkin783e7702010-11-22 19:52:30 +02002615 return;
2616 }
2617
Jason Wang0c87e932013-01-30 19:12:38 +08002618 if (q->tx_waiting) {
aliguorifbe78f42008-12-17 19:13:11 +00002619 virtio_queue_set_notification(vq, 1);
Alex Blighbc72ad62013-08-21 16:03:08 +01002620 timer_del(q->tx_timer);
Jason Wang0c87e932013-01-30 19:12:38 +08002621 q->tx_waiting = 0;
Greg Kurzfa5e56c2016-09-30 17:13:32 +02002622 if (virtio_net_flush_tx(q) == -EINVAL) {
2623 return;
2624 }
aliguorifbe78f42008-12-17 19:13:11 +00002625 } else {
Alex Blighbc72ad62013-08-21 16:03:08 +01002626 timer_mod(q->tx_timer,
2627 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout);
Jason Wang0c87e932013-01-30 19:12:38 +08002628 q->tx_waiting = 1;
aliguorifbe78f42008-12-17 19:13:11 +00002629 virtio_queue_set_notification(vq, 0);
2630 }
2631}
2632
Alex Williamsona697a332010-09-02 09:01:10 -06002633static void virtio_net_handle_tx_bh(VirtIODevice *vdev, VirtQueue *vq)
2634{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002635 VirtIONet *n = VIRTIO_NET(vdev);
Jason Wangfed699f2013-01-30 19:12:39 +08002636 VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))];
Alex Williamsona697a332010-09-02 09:01:10 -06002637
Yuri Benditovich283e2c22016-12-13 10:12:08 +02002638 if (unlikely((n->status & VIRTIO_NET_S_LINK_UP) == 0)) {
2639 virtio_net_drop_tx_queue_data(vdev, vq);
2640 return;
2641 }
2642
Jason Wang0c87e932013-01-30 19:12:38 +08002643 if (unlikely(q->tx_waiting)) {
Alex Williamsona697a332010-09-02 09:01:10 -06002644 return;
2645 }
Jason Wang0c87e932013-01-30 19:12:38 +08002646 q->tx_waiting = 1;
Michael S. Tsirkin783e7702010-11-22 19:52:30 +02002647 /* This happens when device was stopped but VCPU wasn't. */
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002648 if (!vdev->vm_running) {
Michael S. Tsirkin783e7702010-11-22 19:52:30 +02002649 return;
2650 }
Alex Williamsona697a332010-09-02 09:01:10 -06002651 virtio_queue_set_notification(vq, 0);
Jason Wang0c87e932013-01-30 19:12:38 +08002652 qemu_bh_schedule(q->tx_bh);
Alex Williamsona697a332010-09-02 09:01:10 -06002653}
2654
aliguorifbe78f42008-12-17 19:13:11 +00002655static void virtio_net_tx_timer(void *opaque)
2656{
Jason Wang0c87e932013-01-30 19:12:38 +08002657 VirtIONetQueue *q = opaque;
2658 VirtIONet *n = q->n;
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002659 VirtIODevice *vdev = VIRTIO_DEVICE(n);
Michael S. Tsirkine8bcf842014-09-02 17:26:12 +03002660 /* This happens when device was stopped but BH wasn't. */
2661 if (!vdev->vm_running) {
2662 /* Make sure tx waiting is set, so we'll run when restarted. */
2663 assert(q->tx_waiting);
2664 return;
2665 }
aliguorifbe78f42008-12-17 19:13:11 +00002666
Jason Wang0c87e932013-01-30 19:12:38 +08002667 q->tx_waiting = 0;
aliguorifbe78f42008-12-17 19:13:11 +00002668
2669 /* Just in case the driver is not ready on more */
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002670 if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
aliguorifbe78f42008-12-17 19:13:11 +00002671 return;
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002672 }
aliguorifbe78f42008-12-17 19:13:11 +00002673
Jason Wang0c87e932013-01-30 19:12:38 +08002674 virtio_queue_set_notification(q->tx_vq, 1);
2675 virtio_net_flush_tx(q);
aliguorifbe78f42008-12-17 19:13:11 +00002676}
2677
Alex Williamsona697a332010-09-02 09:01:10 -06002678static void virtio_net_tx_bh(void *opaque)
2679{
Jason Wang0c87e932013-01-30 19:12:38 +08002680 VirtIONetQueue *q = opaque;
2681 VirtIONet *n = q->n;
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002682 VirtIODevice *vdev = VIRTIO_DEVICE(n);
Alex Williamsona697a332010-09-02 09:01:10 -06002683 int32_t ret;
2684
Michael S. Tsirkine8bcf842014-09-02 17:26:12 +03002685 /* This happens when device was stopped but BH wasn't. */
2686 if (!vdev->vm_running) {
2687 /* Make sure tx waiting is set, so we'll run when restarted. */
2688 assert(q->tx_waiting);
2689 return;
2690 }
Michael S. Tsirkin783e7702010-11-22 19:52:30 +02002691
Jason Wang0c87e932013-01-30 19:12:38 +08002692 q->tx_waiting = 0;
Alex Williamsona697a332010-09-02 09:01:10 -06002693
2694 /* Just in case the driver is not ready on more */
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002695 if (unlikely(!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))) {
Alex Williamsona697a332010-09-02 09:01:10 -06002696 return;
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02002697 }
Alex Williamsona697a332010-09-02 09:01:10 -06002698
Jason Wang0c87e932013-01-30 19:12:38 +08002699 ret = virtio_net_flush_tx(q);
Greg Kurzfa5e56c2016-09-30 17:13:32 +02002700 if (ret == -EBUSY || ret == -EINVAL) {
2701 return; /* Notification re-enable handled by tx_complete or device
2702 * broken */
Alex Williamsona697a332010-09-02 09:01:10 -06002703 }
2704
2705 /* If we flush a full burst of packets, assume there are
2706 * more coming and immediately reschedule */
2707 if (ret >= n->tx_burst) {
Jason Wang0c87e932013-01-30 19:12:38 +08002708 qemu_bh_schedule(q->tx_bh);
2709 q->tx_waiting = 1;
Alex Williamsona697a332010-09-02 09:01:10 -06002710 return;
2711 }
2712
2713 /* If less than a full burst, re-enable notification and flush
2714 * anything that may have come in while we weren't looking. If
2715 * we find something, assume the guest is still active and reschedule */
Jason Wang0c87e932013-01-30 19:12:38 +08002716 virtio_queue_set_notification(q->tx_vq, 1);
Greg Kurzfa5e56c2016-09-30 17:13:32 +02002717 ret = virtio_net_flush_tx(q);
2718 if (ret == -EINVAL) {
2719 return;
2720 } else if (ret > 0) {
Jason Wang0c87e932013-01-30 19:12:38 +08002721 virtio_queue_set_notification(q->tx_vq, 0);
2722 qemu_bh_schedule(q->tx_bh);
2723 q->tx_waiting = 1;
Alex Williamsona697a332010-09-02 09:01:10 -06002724 }
2725}
2726
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08002727static void virtio_net_add_queue(VirtIONet *n, int index)
2728{
2729 VirtIODevice *vdev = VIRTIO_DEVICE(n);
2730
Michael S. Tsirkin1c0fbfa2016-08-10 17:47:16 +03002731 n->vqs[index].rx_vq = virtio_add_queue(vdev, n->net_conf.rx_queue_size,
2732 virtio_net_handle_rx);
Wei Wang9b02e162017-06-28 10:37:59 +08002733
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08002734 if (n->net_conf.tx && !strcmp(n->net_conf.tx, "timer")) {
2735 n->vqs[index].tx_vq =
Wei Wang9b02e162017-06-28 10:37:59 +08002736 virtio_add_queue(vdev, n->net_conf.tx_queue_size,
2737 virtio_net_handle_tx_timer);
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08002738 n->vqs[index].tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
2739 virtio_net_tx_timer,
2740 &n->vqs[index]);
2741 } else {
2742 n->vqs[index].tx_vq =
Wei Wang9b02e162017-06-28 10:37:59 +08002743 virtio_add_queue(vdev, n->net_conf.tx_queue_size,
2744 virtio_net_handle_tx_bh);
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08002745 n->vqs[index].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[index]);
2746 }
2747
2748 n->vqs[index].tx_waiting = 0;
2749 n->vqs[index].n = n;
2750}
2751
2752static void virtio_net_del_queue(VirtIONet *n, int index)
2753{
2754 VirtIODevice *vdev = VIRTIO_DEVICE(n);
2755 VirtIONetQueue *q = &n->vqs[index];
2756 NetClientState *nc = qemu_get_subqueue(n->nic, index);
2757
2758 qemu_purge_queued_packets(nc);
2759
2760 virtio_del_queue(vdev, index * 2);
2761 if (q->tx_timer) {
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08002762 timer_free(q->tx_timer);
Yunjian Wangf989c302017-04-26 14:45:56 +08002763 q->tx_timer = NULL;
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08002764 } else {
2765 qemu_bh_delete(q->tx_bh);
Yunjian Wangf989c302017-04-26 14:45:56 +08002766 q->tx_bh = NULL;
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08002767 }
Yunjian Wangf989c302017-04-26 14:45:56 +08002768 q->tx_waiting = 0;
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08002769 virtio_del_queue(vdev, index * 2 + 1);
2770}
2771
Jason Wang441537f2021-10-20 12:55:57 +08002772static void virtio_net_change_num_queue_pairs(VirtIONet *n, int new_max_queue_pairs)
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08002773{
2774 VirtIODevice *vdev = VIRTIO_DEVICE(n);
2775 int old_num_queues = virtio_get_num_queues(vdev);
Jason Wang441537f2021-10-20 12:55:57 +08002776 int new_num_queues = new_max_queue_pairs * 2 + 1;
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08002777 int i;
2778
2779 assert(old_num_queues >= 3);
2780 assert(old_num_queues % 2 == 1);
2781
2782 if (old_num_queues == new_num_queues) {
2783 return;
2784 }
2785
2786 /*
2787 * We always need to remove and add ctrl vq if
2788 * old_num_queues != new_num_queues. Remove ctrl_vq first,
Yuval Shaia20f86a72019-03-21 18:18:32 +02002789 * and then we only enter one of the following two loops.
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08002790 */
2791 virtio_del_queue(vdev, old_num_queues - 1);
2792
2793 for (i = new_num_queues - 1; i < old_num_queues - 1; i += 2) {
2794 /* new_num_queues < old_num_queues */
2795 virtio_net_del_queue(n, i / 2);
2796 }
2797
2798 for (i = old_num_queues - 1; i < new_num_queues - 1; i += 2) {
2799 /* new_num_queues > old_num_queues */
2800 virtio_net_add_queue(n, i / 2);
2801 }
2802
2803 /* add ctrl_vq last */
2804 n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
2805}
2806
Jason Wangec57db12013-04-25 15:24:23 +08002807static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue)
Jason Wangfed699f2013-01-30 19:12:39 +08002808{
Jason Wang441537f2021-10-20 12:55:57 +08002809 int max = multiqueue ? n->max_queue_pairs : 1;
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08002810
Jason Wangfed699f2013-01-30 19:12:39 +08002811 n->multiqueue = multiqueue;
Jason Wang441537f2021-10-20 12:55:57 +08002812 virtio_net_change_num_queue_pairs(n, max);
Jason Wangfed699f2013-01-30 19:12:39 +08002813
Jason Wang441537f2021-10-20 12:55:57 +08002814 virtio_net_set_queue_pairs(n);
Jason Wangfed699f2013-01-30 19:12:39 +08002815}
2816
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002817static int virtio_net_post_load_device(void *opaque, int version_id)
Greg Kurz037dab22014-06-24 19:19:03 +02002818{
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002819 VirtIONet *n = opaque;
2820 VirtIODevice *vdev = VIRTIO_DEVICE(n);
Greg Kurz037dab22014-06-24 19:19:03 +02002821 int i, link_down;
aliguorifbe78f42008-12-17 19:13:11 +00002822
Dr. David Alan Gilbert9d8c6a22019-02-27 13:24:07 +00002823 trace_virtio_net_post_load_device();
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002824 virtio_net_set_mrg_rx_bufs(n, n->mergeable_rx_bufs,
Cornelia Huck95129d62015-08-17 11:48:29 +02002825 virtio_vdev_has_feature(vdev,
Yuri Benditoviche22f0602020-05-08 15:59:31 +03002826 VIRTIO_F_VERSION_1),
2827 virtio_vdev_has_feature(vdev,
2828 VIRTIO_NET_F_HASH_REPORT));
aliguorifbe78f42008-12-17 19:13:11 +00002829
Dr. David Alan Gilbert76010cb2016-07-14 18:22:43 +01002830 /* MAC_TABLE_ENTRIES may be different from the saved image */
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002831 if (n->mac_table.in_use > MAC_TABLE_ENTRIES) {
Dr. David Alan Gilbert76010cb2016-07-14 18:22:43 +01002832 n->mac_table.in_use = 0;
aliguorib6503ed2009-02-05 22:36:28 +00002833 }
aliguorif21c0ed2009-02-05 22:36:32 +00002834
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002835 if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS)) {
Michael S. Tsirkin6c666822016-07-04 14:47:37 +03002836 n->curr_guest_offloads = virtio_net_supported_guest_offloads(n);
2837 }
2838
Mikhail Sennikovsky7788c3f2019-10-11 15:58:04 +02002839 /*
2840 * curr_guest_offloads will be later overwritten by the
2841 * virtio_set_features_nocheck call done from the virtio_load.
2842 * Here we make sure it is preserved and restored accordingly
2843 * in the virtio_net_post_load_virtio callback.
2844 */
2845 n->saved_guest_offloads = n->curr_guest_offloads;
Michael S. Tsirkin6c666822016-07-04 14:47:37 +03002846
Jason Wang441537f2021-10-20 12:55:57 +08002847 virtio_net_set_queue_pairs(n);
Jason Wang5f800802013-01-30 19:12:40 +08002848
Alex Williamson2d9aba32009-06-05 14:47:13 -06002849 /* Find the first multicast entry in the saved MAC filter */
2850 for (i = 0; i < n->mac_table.in_use; i++) {
2851 if (n->mac_table.macs[i * ETH_ALEN] & 1) {
2852 break;
2853 }
2854 }
2855 n->mac_table.first_multi = i;
Amos Kong98991482012-09-28 10:06:02 +08002856
2857 /* nc.link_down can't be migrated, so infer link_down according
2858 * to link status bit in n->status */
Jason Wang5f800802013-01-30 19:12:40 +08002859 link_down = (n->status & VIRTIO_NET_S_LINK_UP) == 0;
Jason Wang441537f2021-10-20 12:55:57 +08002860 for (i = 0; i < n->max_queue_pairs; i++) {
Jason Wang5f800802013-01-30 19:12:40 +08002861 qemu_get_subqueue(n->nic, i)->link_down = link_down;
2862 }
Amos Kong98991482012-09-28 10:06:02 +08002863
Michael S. Tsirkin6c666822016-07-04 14:47:37 +03002864 if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) &&
2865 virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) {
Dr. David Alan Gilbert9d8c6a22019-02-27 13:24:07 +00002866 qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(),
2867 QEMU_CLOCK_VIRTUAL,
2868 virtio_net_announce_timer, n);
2869 if (n->announce_timer.round) {
2870 timer_mod(n->announce_timer.tm,
2871 qemu_clock_get_ms(n->announce_timer.type));
2872 } else {
Dr. David Alan Gilbert944458b2019-06-20 19:47:04 +01002873 qemu_announce_timer_del(&n->announce_timer, false);
Dr. David Alan Gilbert9d8c6a22019-02-27 13:24:07 +00002874 }
Michael S. Tsirkin6c666822016-07-04 14:47:37 +03002875 }
2876
Yuri Benditoviche41b7112020-05-08 15:59:33 +03002877 if (n->rss_data.enabled) {
Andrew Melnychenko0145c392021-05-14 14:48:33 +03002878 n->rss_data.enabled_software_rss = n->rss_data.populate_hash;
2879 if (!n->rss_data.populate_hash) {
2880 if (!virtio_net_attach_epbf_rss(n)) {
2881 if (get_vhost_net(qemu_get_queue(n->nic)->peer)) {
2882 warn_report("Can't post-load eBPF RSS for vhost");
2883 } else {
2884 warn_report("Can't post-load eBPF RSS - "
2885 "fallback to software RSS");
2886 n->rss_data.enabled_software_rss = true;
2887 }
2888 }
2889 }
2890
Yuri Benditoviche41b7112020-05-08 15:59:33 +03002891 trace_virtio_net_rss_enable(n->rss_data.hash_types,
2892 n->rss_data.indirections_len,
2893 sizeof(n->rss_data.key));
2894 } else {
2895 trace_virtio_net_rss_disable();
2896 }
aliguorifbe78f42008-12-17 19:13:11 +00002897 return 0;
2898}
2899
Mikhail Sennikovsky7788c3f2019-10-11 15:58:04 +02002900static int virtio_net_post_load_virtio(VirtIODevice *vdev)
2901{
2902 VirtIONet *n = VIRTIO_NET(vdev);
2903 /*
2904 * The actual needed state is now in saved_guest_offloads,
2905 * see virtio_net_post_load_device for detail.
2906 * Restore it back and apply the desired offloads.
2907 */
2908 n->curr_guest_offloads = n->saved_guest_offloads;
2909 if (peer_has_vnet_hdr(n)) {
2910 virtio_net_apply_guest_offloads(n);
2911 }
2912
2913 return 0;
2914}
2915
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002916/* tx_waiting field of a VirtIONetQueue */
2917static const VMStateDescription vmstate_virtio_net_queue_tx_waiting = {
2918 .name = "virtio-net-queue-tx_waiting",
2919 .fields = (VMStateField[]) {
2920 VMSTATE_UINT32(tx_waiting, VirtIONetQueue),
2921 VMSTATE_END_OF_LIST()
2922 },
2923};
2924
Jason Wang441537f2021-10-20 12:55:57 +08002925static bool max_queue_pairs_gt_1(void *opaque, int version_id)
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002926{
Jason Wang441537f2021-10-20 12:55:57 +08002927 return VIRTIO_NET(opaque)->max_queue_pairs > 1;
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002928}
2929
2930static bool has_ctrl_guest_offloads(void *opaque, int version_id)
2931{
2932 return virtio_vdev_has_feature(VIRTIO_DEVICE(opaque),
2933 VIRTIO_NET_F_CTRL_GUEST_OFFLOADS);
2934}
2935
2936static bool mac_table_fits(void *opaque, int version_id)
2937{
2938 return VIRTIO_NET(opaque)->mac_table.in_use <= MAC_TABLE_ENTRIES;
2939}
2940
2941static bool mac_table_doesnt_fit(void *opaque, int version_id)
2942{
2943 return !mac_table_fits(opaque, version_id);
2944}
2945
2946/* This temporary type is shared by all the WITH_TMP methods
2947 * although only some fields are used by each.
2948 */
2949struct VirtIONetMigTmp {
2950 VirtIONet *parent;
2951 VirtIONetQueue *vqs_1;
Jason Wang441537f2021-10-20 12:55:57 +08002952 uint16_t curr_queue_pairs_1;
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002953 uint8_t has_ufo;
2954 uint32_t has_vnet_hdr;
2955};
2956
2957/* The 2nd and subsequent tx_waiting flags are loaded later than
Jason Wang441537f2021-10-20 12:55:57 +08002958 * the 1st entry in the queue_pairs and only if there's more than one
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002959 * entry. We use the tmp mechanism to calculate a temporary
2960 * pointer and count and also validate the count.
2961 */
2962
Dr. David Alan Gilbert44b1ff32017-09-25 12:29:12 +01002963static int virtio_net_tx_waiting_pre_save(void *opaque)
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002964{
2965 struct VirtIONetMigTmp *tmp = opaque;
2966
2967 tmp->vqs_1 = tmp->parent->vqs + 1;
Jason Wang441537f2021-10-20 12:55:57 +08002968 tmp->curr_queue_pairs_1 = tmp->parent->curr_queue_pairs - 1;
2969 if (tmp->parent->curr_queue_pairs == 0) {
2970 tmp->curr_queue_pairs_1 = 0;
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002971 }
Dr. David Alan Gilbert44b1ff32017-09-25 12:29:12 +01002972
2973 return 0;
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002974}
2975
2976static int virtio_net_tx_waiting_pre_load(void *opaque)
2977{
2978 struct VirtIONetMigTmp *tmp = opaque;
2979
2980 /* Reuse the pointer setup from save */
2981 virtio_net_tx_waiting_pre_save(opaque);
2982
Jason Wang441537f2021-10-20 12:55:57 +08002983 if (tmp->parent->curr_queue_pairs > tmp->parent->max_queue_pairs) {
2984 error_report("virtio-net: curr_queue_pairs %x > max_queue_pairs %x",
2985 tmp->parent->curr_queue_pairs, tmp->parent->max_queue_pairs);
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00002986
2987 return -EINVAL;
2988 }
2989
2990 return 0; /* all good */
2991}
2992
2993static const VMStateDescription vmstate_virtio_net_tx_waiting = {
2994 .name = "virtio-net-tx_waiting",
2995 .pre_load = virtio_net_tx_waiting_pre_load,
2996 .pre_save = virtio_net_tx_waiting_pre_save,
2997 .fields = (VMStateField[]) {
2998 VMSTATE_STRUCT_VARRAY_POINTER_UINT16(vqs_1, struct VirtIONetMigTmp,
Jason Wang441537f2021-10-20 12:55:57 +08002999 curr_queue_pairs_1,
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00003000 vmstate_virtio_net_queue_tx_waiting,
3001 struct VirtIONetQueue),
3002 VMSTATE_END_OF_LIST()
3003 },
3004};
3005
3006/* the 'has_ufo' flag is just tested; if the incoming stream has the
3007 * flag set we need to check that we have it
3008 */
3009static int virtio_net_ufo_post_load(void *opaque, int version_id)
3010{
3011 struct VirtIONetMigTmp *tmp = opaque;
3012
3013 if (tmp->has_ufo && !peer_has_ufo(tmp->parent)) {
3014 error_report("virtio-net: saved image requires TUN_F_UFO support");
3015 return -EINVAL;
3016 }
3017
3018 return 0;
3019}
3020
Dr. David Alan Gilbert44b1ff32017-09-25 12:29:12 +01003021static int virtio_net_ufo_pre_save(void *opaque)
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00003022{
3023 struct VirtIONetMigTmp *tmp = opaque;
3024
3025 tmp->has_ufo = tmp->parent->has_ufo;
Dr. David Alan Gilbert44b1ff32017-09-25 12:29:12 +01003026
3027 return 0;
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00003028}
3029
3030static const VMStateDescription vmstate_virtio_net_has_ufo = {
3031 .name = "virtio-net-ufo",
3032 .post_load = virtio_net_ufo_post_load,
3033 .pre_save = virtio_net_ufo_pre_save,
3034 .fields = (VMStateField[]) {
3035 VMSTATE_UINT8(has_ufo, struct VirtIONetMigTmp),
3036 VMSTATE_END_OF_LIST()
3037 },
3038};
3039
3040/* the 'has_vnet_hdr' flag is just tested; if the incoming stream has the
3041 * flag set we need to check that we have it
3042 */
3043static int virtio_net_vnet_post_load(void *opaque, int version_id)
3044{
3045 struct VirtIONetMigTmp *tmp = opaque;
3046
3047 if (tmp->has_vnet_hdr && !peer_has_vnet_hdr(tmp->parent)) {
3048 error_report("virtio-net: saved image requires vnet_hdr=on");
3049 return -EINVAL;
3050 }
3051
3052 return 0;
3053}
3054
Dr. David Alan Gilbert44b1ff32017-09-25 12:29:12 +01003055static int virtio_net_vnet_pre_save(void *opaque)
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00003056{
3057 struct VirtIONetMigTmp *tmp = opaque;
3058
3059 tmp->has_vnet_hdr = tmp->parent->has_vnet_hdr;
Dr. David Alan Gilbert44b1ff32017-09-25 12:29:12 +01003060
3061 return 0;
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00003062}
3063
3064static const VMStateDescription vmstate_virtio_net_has_vnet = {
3065 .name = "virtio-net-vnet",
3066 .post_load = virtio_net_vnet_post_load,
3067 .pre_save = virtio_net_vnet_pre_save,
3068 .fields = (VMStateField[]) {
3069 VMSTATE_UINT32(has_vnet_hdr, struct VirtIONetMigTmp),
3070 VMSTATE_END_OF_LIST()
3071 },
3072};
3073
Yuri Benditoviche41b7112020-05-08 15:59:33 +03003074static bool virtio_net_rss_needed(void *opaque)
3075{
3076 return VIRTIO_NET(opaque)->rss_data.enabled;
3077}
3078
3079static const VMStateDescription vmstate_virtio_net_rss = {
3080 .name = "virtio-net-device/rss",
3081 .version_id = 1,
3082 .minimum_version_id = 1,
3083 .needed = virtio_net_rss_needed,
3084 .fields = (VMStateField[]) {
3085 VMSTATE_BOOL(rss_data.enabled, VirtIONet),
3086 VMSTATE_BOOL(rss_data.redirect, VirtIONet),
3087 VMSTATE_BOOL(rss_data.populate_hash, VirtIONet),
3088 VMSTATE_UINT32(rss_data.hash_types, VirtIONet),
3089 VMSTATE_UINT16(rss_data.indirections_len, VirtIONet),
3090 VMSTATE_UINT16(rss_data.default_queue, VirtIONet),
3091 VMSTATE_UINT8_ARRAY(rss_data.key, VirtIONet,
3092 VIRTIO_NET_RSS_MAX_KEY_SIZE),
3093 VMSTATE_VARRAY_UINT16_ALLOC(rss_data.indirections_table, VirtIONet,
3094 rss_data.indirections_len, 0,
3095 vmstate_info_uint16, uint16_t),
3096 VMSTATE_END_OF_LIST()
3097 },
3098};
3099
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00003100static const VMStateDescription vmstate_virtio_net_device = {
3101 .name = "virtio-net-device",
3102 .version_id = VIRTIO_NET_VM_VERSION,
3103 .minimum_version_id = VIRTIO_NET_VM_VERSION,
3104 .post_load = virtio_net_post_load_device,
3105 .fields = (VMStateField[]) {
3106 VMSTATE_UINT8_ARRAY(mac, VirtIONet, ETH_ALEN),
3107 VMSTATE_STRUCT_POINTER(vqs, VirtIONet,
3108 vmstate_virtio_net_queue_tx_waiting,
3109 VirtIONetQueue),
3110 VMSTATE_UINT32(mergeable_rx_bufs, VirtIONet),
3111 VMSTATE_UINT16(status, VirtIONet),
3112 VMSTATE_UINT8(promisc, VirtIONet),
3113 VMSTATE_UINT8(allmulti, VirtIONet),
3114 VMSTATE_UINT32(mac_table.in_use, VirtIONet),
3115
3116 /* Guarded pair: If it fits we load it, else we throw it away
3117 * - can happen if source has a larger MAC table.; post-load
3118 * sets flags in this case.
3119 */
3120 VMSTATE_VBUFFER_MULTIPLY(mac_table.macs, VirtIONet,
3121 0, mac_table_fits, mac_table.in_use,
3122 ETH_ALEN),
3123 VMSTATE_UNUSED_VARRAY_UINT32(VirtIONet, mac_table_doesnt_fit, 0,
3124 mac_table.in_use, ETH_ALEN),
3125
3126 /* Note: This is an array of uint32's that's always been saved as a
3127 * buffer; hold onto your endiannesses; it's actually used as a bitmap
3128 * but based on the uint.
3129 */
3130 VMSTATE_BUFFER_POINTER_UNSAFE(vlans, VirtIONet, 0, MAX_VLAN >> 3),
3131 VMSTATE_WITH_TMP(VirtIONet, struct VirtIONetMigTmp,
3132 vmstate_virtio_net_has_vnet),
3133 VMSTATE_UINT8(mac_table.multi_overflow, VirtIONet),
3134 VMSTATE_UINT8(mac_table.uni_overflow, VirtIONet),
3135 VMSTATE_UINT8(alluni, VirtIONet),
3136 VMSTATE_UINT8(nomulti, VirtIONet),
3137 VMSTATE_UINT8(nouni, VirtIONet),
3138 VMSTATE_UINT8(nobcast, VirtIONet),
3139 VMSTATE_WITH_TMP(VirtIONet, struct VirtIONetMigTmp,
3140 vmstate_virtio_net_has_ufo),
Jason Wang441537f2021-10-20 12:55:57 +08003141 VMSTATE_SINGLE_TEST(max_queue_pairs, VirtIONet, max_queue_pairs_gt_1, 0,
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00003142 vmstate_info_uint16_equal, uint16_t),
Jason Wang441537f2021-10-20 12:55:57 +08003143 VMSTATE_UINT16_TEST(curr_queue_pairs, VirtIONet, max_queue_pairs_gt_1),
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00003144 VMSTATE_WITH_TMP(VirtIONet, struct VirtIONetMigTmp,
3145 vmstate_virtio_net_tx_waiting),
3146 VMSTATE_UINT64_TEST(curr_guest_offloads, VirtIONet,
3147 has_ctrl_guest_offloads),
3148 VMSTATE_END_OF_LIST()
3149 },
Yuri Benditoviche41b7112020-05-08 15:59:33 +03003150 .subsections = (const VMStateDescription * []) {
3151 &vmstate_virtio_net_rss,
3152 NULL
3153 }
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00003154};
3155
Mark McLoughlineb6b6c12009-11-25 18:49:11 +00003156static NetClientInfo net_virtio_info = {
Eric Blakef394b2e2016-07-13 21:50:23 -06003157 .type = NET_CLIENT_DRIVER_NIC,
Mark McLoughlineb6b6c12009-11-25 18:49:11 +00003158 .size = sizeof(NICState),
3159 .can_receive = virtio_net_can_receive,
3160 .receive = virtio_net_receive,
Mark McLoughlineb6b6c12009-11-25 18:49:11 +00003161 .link_status_changed = virtio_net_set_link_status,
Amos Kongb1be4282013-06-14 15:45:52 +08003162 .query_rx_filter = virtio_net_query_rxfilter,
Dr. David Alan Gilbertb2c929f2019-02-27 13:24:10 +00003163 .announce = virtio_net_announce,
Mark McLoughlineb6b6c12009-11-25 18:49:11 +00003164};
3165
Michael S. Tsirkinf56a1242012-12-24 17:37:01 +02003166static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
3167{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02003168 VirtIONet *n = VIRTIO_NET(vdev);
Jason Wangfed699f2013-01-30 19:12:39 +08003169 NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
Michael S. Tsirkinf56a1242012-12-24 17:37:01 +02003170 assert(n->vhost_started);
Nikolay Nikolaeved8b4af2014-05-27 15:05:08 +03003171 return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx);
Michael S. Tsirkinf56a1242012-12-24 17:37:01 +02003172}
3173
3174static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
3175 bool mask)
3176{
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02003177 VirtIONet *n = VIRTIO_NET(vdev);
Jason Wangfed699f2013-01-30 19:12:39 +08003178 NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
Michael S. Tsirkinf56a1242012-12-24 17:37:01 +02003179 assert(n->vhost_started);
Michael S. Tsirkina882b572022-01-10 00:47:56 -05003180 vhost_net_virtqueue_mask(get_vhost_net(nc->peer),
3181 vdev, idx, mask);
Michael S. Tsirkinf56a1242012-12-24 17:37:01 +02003182}
3183
Gerd Hoffmann019a3ed2015-06-01 10:45:40 +02003184static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features)
aliguorifbe78f42008-12-17 19:13:11 +00003185{
Cornelia Huck0cd09c32014-12-11 14:25:05 +01003186 virtio_add_feature(&host_features, VIRTIO_NET_F_MAC);
Maxime Coquelina93e5992016-12-10 16:30:38 +01003187
Stefano Garzarellaba550852019-02-21 11:33:08 +01003188 n->config_size = virtio_feature_get_config_size(feature_sizes,
3189 host_features);
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003190}
3191
KONRAD Frederic8a253ec2013-05-15 14:12:49 +02003192void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
3193 const char *type)
3194{
3195 /*
3196 * The name can be NULL, the netclient name will be type.x.
3197 */
3198 assert(type != NULL);
3199
Markus Armbruster9e288402014-06-06 18:43:29 +02003200 g_free(n->netclient_name);
Markus Armbruster9e288402014-06-06 18:43:29 +02003201 g_free(n->netclient_type);
Markus Armbruster80e00902014-06-06 18:43:30 +02003202 n->netclient_name = g_strdup(name);
KONRAD Frederic8a253ec2013-05-15 14:12:49 +02003203 n->netclient_type = g_strdup(type);
3204}
3205
Juan Quintela0e9a65c2020-11-18 09:37:46 +01003206static bool failover_unplug_primary(VirtIONet *n, DeviceState *dev)
Jens Freimann9711cd02019-10-29 12:49:04 +01003207{
3208 HotplugHandler *hotplug_ctrl;
3209 PCIDevice *pci_dev;
3210 Error *err = NULL;
3211
Juan Quintela0e9a65c2020-11-18 09:37:46 +01003212 hotplug_ctrl = qdev_get_hotplug_handler(dev);
Jens Freimann9711cd02019-10-29 12:49:04 +01003213 if (hotplug_ctrl) {
Juan Quintela0e9a65c2020-11-18 09:37:46 +01003214 pci_dev = PCI_DEVICE(dev);
Jens Freimann9711cd02019-10-29 12:49:04 +01003215 pci_dev->partially_hotplugged = true;
Juan Quintela0e9a65c2020-11-18 09:37:46 +01003216 hotplug_handler_unplug_request(hotplug_ctrl, dev, &err);
Jens Freimann9711cd02019-10-29 12:49:04 +01003217 if (err) {
3218 error_report_err(err);
3219 return false;
3220 }
3221 } else {
3222 return false;
3223 }
3224 return true;
3225}
3226
Juan Quintela0e9a65c2020-11-18 09:37:46 +01003227static bool failover_replug_primary(VirtIONet *n, DeviceState *dev,
3228 Error **errp)
Jens Freimann9711cd02019-10-29 12:49:04 +01003229{
Markus Armbruster5a0948d2019-11-30 20:42:21 +01003230 Error *err = NULL;
Jens Freimann9711cd02019-10-29 12:49:04 +01003231 HotplugHandler *hotplug_ctrl;
Juan Quintela0e9a65c2020-11-18 09:37:46 +01003232 PCIDevice *pdev = PCI_DEVICE(dev);
Juan Quintela78274682020-11-18 09:37:25 +01003233 BusState *primary_bus;
Jens Freimann9711cd02019-10-29 12:49:04 +01003234
3235 if (!pdev->partially_hotplugged) {
3236 return true;
3237 }
Juan Quintela0e9a65c2020-11-18 09:37:46 +01003238 primary_bus = dev->parent_bus;
Juan Quintela78274682020-11-18 09:37:25 +01003239 if (!primary_bus) {
Jens Freimann150ab542019-11-20 16:49:50 +01003240 error_setg(errp, "virtio_net: couldn't find primary bus");
Markus Armbruster5a0948d2019-11-30 20:42:21 +01003241 return false;
Jens Freimann150ab542019-11-20 16:49:50 +01003242 }
Juan Quintela0e9a65c2020-11-18 09:37:46 +01003243 qdev_set_parent_bus(dev, primary_bus, &error_abort);
Juan Quintelae2bde832020-11-18 09:37:29 +01003244 qatomic_set(&n->failover_primary_hidden, false);
Juan Quintela0e9a65c2020-11-18 09:37:46 +01003245 hotplug_ctrl = qdev_get_hotplug_handler(dev);
Jens Freimann150ab542019-11-20 16:49:50 +01003246 if (hotplug_ctrl) {
Juan Quintela0e9a65c2020-11-18 09:37:46 +01003247 hotplug_handler_pre_plug(hotplug_ctrl, dev, &err);
Markus Armbruster5a0948d2019-11-30 20:42:21 +01003248 if (err) {
3249 goto out;
3250 }
Juan Quintela0e9a65c2020-11-18 09:37:46 +01003251 hotplug_handler_plug(hotplug_ctrl, dev, &err);
Jens Freimann150ab542019-11-20 16:49:50 +01003252 }
Laurent Vivier109c20e2021-06-29 17:29:37 +02003253 pdev->partially_hotplugged = false;
Jens Freimann150ab542019-11-20 16:49:50 +01003254
3255out:
Markus Armbruster5a0948d2019-11-30 20:42:21 +01003256 error_propagate(errp, err);
3257 return !err;
Jens Freimann9711cd02019-10-29 12:49:04 +01003258}
3259
Juan Quintela07a5d812020-11-18 09:37:47 +01003260static void virtio_net_handle_migration_primary(VirtIONet *n, MigrationState *s)
Jens Freimann9711cd02019-10-29 12:49:04 +01003261{
3262 bool should_be_hidden;
3263 Error *err = NULL;
Juan Quintela07a5d812020-11-18 09:37:47 +01003264 DeviceState *dev = failover_find_primary_device(n);
3265
3266 if (!dev) {
3267 return;
3268 }
Jens Freimann9711cd02019-10-29 12:49:04 +01003269
Juan Quintelae2bde832020-11-18 09:37:29 +01003270 should_be_hidden = qatomic_read(&n->failover_primary_hidden);
Jens Freimann9711cd02019-10-29 12:49:04 +01003271
Markus Armbruster4dbac1a2019-11-30 20:42:20 +01003272 if (migration_in_setup(s) && !should_be_hidden) {
Juan Quintela07a5d812020-11-18 09:37:47 +01003273 if (failover_unplug_primary(n, dev)) {
3274 vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev);
3275 qapi_event_send_unplug_primary(dev->id);
Juan Quintelae2bde832020-11-18 09:37:29 +01003276 qatomic_set(&n->failover_primary_hidden, true);
Jens Freimann9711cd02019-10-29 12:49:04 +01003277 } else {
3278 warn_report("couldn't unplug primary device");
3279 }
3280 } else if (migration_has_failed(s)) {
Jens Freimann150ab542019-11-20 16:49:50 +01003281 /* We already unplugged the device let's plug it back */
Juan Quintela07a5d812020-11-18 09:37:47 +01003282 if (!failover_replug_primary(n, dev, &err)) {
Jens Freimann9711cd02019-10-29 12:49:04 +01003283 if (err) {
3284 error_report_err(err);
3285 }
3286 }
3287 }
3288}
3289
3290static void virtio_net_migration_state_notifier(Notifier *notifier, void *data)
3291{
3292 MigrationState *s = data;
3293 VirtIONet *n = container_of(notifier, VirtIONet, migration_state);
3294 virtio_net_handle_migration_primary(n, s);
3295}
3296
Juan Quintelab91ad982020-11-18 09:37:37 +01003297static bool failover_hide_primary_device(DeviceListener *listener,
Kevin Wolff3558b12021-10-08 15:34:41 +02003298 const QDict *device_opts,
3299 bool from_json,
3300 Error **errp)
Jens Freimann9711cd02019-10-29 12:49:04 +01003301{
3302 VirtIONet *n = container_of(listener, VirtIONet, primary_listener);
Juan Quintela4f0303a2020-11-18 09:37:32 +01003303 const char *standby_id;
Jens Freimann9711cd02019-10-29 12:49:04 +01003304
Jens Freimann4d0e59a2019-11-20 16:49:51 +01003305 if (!device_opts) {
Juan Quintela89631fe2020-11-18 09:37:36 +01003306 return false;
Jens Freimann4d0e59a2019-11-20 16:49:51 +01003307 }
Laurent Vivierbcfc9062021-10-19 09:15:32 +02003308
3309 if (!qdict_haskey(device_opts, "failover_pair_id")) {
3310 return false;
3311 }
3312
3313 if (!qdict_haskey(device_opts, "id")) {
3314 error_setg(errp, "Device with failover_pair_id needs to have id");
3315 return false;
3316 }
3317
3318 standby_id = qdict_get_str(device_opts, "failover_pair_id");
Juan Quintela89631fe2020-11-18 09:37:36 +01003319 if (g_strcmp0(standby_id, n->netclient_name) != 0) {
3320 return false;
Jens Freimann9711cd02019-10-29 12:49:04 +01003321 }
3322
Laurent Vivier7fe77912021-10-19 09:15:31 +02003323 /*
3324 * The hide helper can be called several times for a given device.
3325 * Check there is only one primary for a virtio-net device but
3326 * don't duplicate the qdict several times if it's called for the same
3327 * device.
3328 */
Kevin Wolf259a10d2021-10-08 15:34:39 +02003329 if (n->primary_opts) {
Laurent Vivier7fe77912021-10-19 09:15:31 +02003330 const char *old, *new;
3331 /* devices with failover_pair_id always have an id */
3332 old = qdict_get_str(n->primary_opts, "id");
3333 new = qdict_get_str(device_opts, "id");
3334 if (strcmp(old, new) != 0) {
3335 error_setg(errp, "Cannot attach more than one primary device to "
3336 "'%s': '%s' and '%s'", n->netclient_name, old, new);
3337 return false;
3338 }
3339 } else {
3340 n->primary_opts = qdict_clone_shallow(device_opts);
3341 n->primary_opts_from_json = from_json;
Kevin Wolf259a10d2021-10-08 15:34:39 +02003342 }
3343
Juan Quintelae2bde832020-11-18 09:37:29 +01003344 /* failover_primary_hidden is set during feature negotiation */
Juan Quintela3abad4a2020-11-18 09:37:45 +01003345 return qatomic_read(&n->failover_primary_hidden);
Jens Freimann9711cd02019-10-29 12:49:04 +01003346}
3347
Andreas Färbere6f746b2013-07-30 02:36:06 +02003348static void virtio_net_device_realize(DeviceState *dev, Error **errp)
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003349{
Andreas Färbere6f746b2013-07-30 02:36:06 +02003350 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
Andreas Färber284a32f2013-07-30 05:02:48 +02003351 VirtIONet *n = VIRTIO_NET(dev);
3352 NetClientState *nc;
KONRAD Frederic1773d9e2013-04-11 16:30:02 +02003353 int i;
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003354
Maxime Coquelina93e5992016-12-10 16:30:38 +01003355 if (n->net_conf.mtu) {
Jason Baron127833e2018-03-07 22:25:40 -05003356 n->host_features |= (1ULL << VIRTIO_NET_F_MTU);
Maxime Coquelina93e5992016-12-10 16:30:38 +01003357 }
3358
Jason Baron94739392018-03-07 22:25:41 -05003359 if (n->net_conf.duplex_str) {
3360 if (strncmp(n->net_conf.duplex_str, "half", 5) == 0) {
3361 n->net_conf.duplex = DUPLEX_HALF;
3362 } else if (strncmp(n->net_conf.duplex_str, "full", 5) == 0) {
3363 n->net_conf.duplex = DUPLEX_FULL;
3364 } else {
3365 error_setg(errp, "'duplex' must be 'half' or 'full'");
Markus Armbruster843c4cf2020-04-22 15:07:13 +02003366 return;
Jason Baron94739392018-03-07 22:25:41 -05003367 }
3368 n->host_features |= (1ULL << VIRTIO_NET_F_SPEED_DUPLEX);
3369 } else {
3370 n->net_conf.duplex = DUPLEX_UNKNOWN;
3371 }
3372
3373 if (n->net_conf.speed < SPEED_UNKNOWN) {
3374 error_setg(errp, "'speed' must be between 0 and INT_MAX");
Markus Armbruster843c4cf2020-04-22 15:07:13 +02003375 return;
3376 }
3377 if (n->net_conf.speed >= 0) {
Jason Baron94739392018-03-07 22:25:41 -05003378 n->host_features |= (1ULL << VIRTIO_NET_F_SPEED_DUPLEX);
3379 }
3380
Jens Freimann9711cd02019-10-29 12:49:04 +01003381 if (n->failover) {
Juan Quintelab91ad982020-11-18 09:37:37 +01003382 n->primary_listener.hide_device = failover_hide_primary_device;
Juan Quintelae2bde832020-11-18 09:37:29 +01003383 qatomic_set(&n->failover_primary_hidden, true);
Jens Freimann9711cd02019-10-29 12:49:04 +01003384 device_listener_register(&n->primary_listener);
3385 n->migration_state.notify = virtio_net_migration_state_notifier;
3386 add_migration_state_change_notifier(&n->migration_state);
3387 n->host_features |= (1ULL << VIRTIO_NET_F_STANDBY);
3388 }
3389
Shannon Zhaoda3e8a22015-04-28 19:51:12 +08003390 virtio_net_set_config_size(n, n->host_features);
Andreas Färber284a32f2013-07-30 05:02:48 +02003391 virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size);
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003392
Michael S. Tsirkin1c0fbfa2016-08-10 17:47:16 +03003393 /*
3394 * We set a lower limit on RX queue size to what it always was.
3395 * Guests that want a smaller ring can always resize it without
3396 * help from us (using virtio 1 and up).
3397 */
3398 if (n->net_conf.rx_queue_size < VIRTIO_NET_RX_QUEUE_MIN_SIZE ||
3399 n->net_conf.rx_queue_size > VIRTQUEUE_MAX_SIZE ||
Michal Privoznik5f997fd2017-07-13 09:44:38 +02003400 !is_power_of_2(n->net_conf.rx_queue_size)) {
Michael S. Tsirkin1c0fbfa2016-08-10 17:47:16 +03003401 error_setg(errp, "Invalid rx_queue_size (= %" PRIu16 "), "
3402 "must be a power of 2 between %d and %d.",
3403 n->net_conf.rx_queue_size, VIRTIO_NET_RX_QUEUE_MIN_SIZE,
3404 VIRTQUEUE_MAX_SIZE);
3405 virtio_cleanup(vdev);
3406 return;
3407 }
3408
Wei Wang9b02e162017-06-28 10:37:59 +08003409 if (n->net_conf.tx_queue_size < VIRTIO_NET_TX_QUEUE_MIN_SIZE ||
3410 n->net_conf.tx_queue_size > VIRTQUEUE_MAX_SIZE ||
3411 !is_power_of_2(n->net_conf.tx_queue_size)) {
3412 error_setg(errp, "Invalid tx_queue_size (= %" PRIu16 "), "
3413 "must be a power of 2 between %d and %d",
3414 n->net_conf.tx_queue_size, VIRTIO_NET_TX_QUEUE_MIN_SIZE,
3415 VIRTQUEUE_MAX_SIZE);
3416 virtio_cleanup(vdev);
3417 return;
3418 }
3419
Jason Wang22288fe2021-10-20 12:55:59 +08003420 n->max_ncs = MAX(n->nic_conf.peers.queues, 1);
3421
3422 /*
3423 * Figure out the datapath queue pairs since the backend could
3424 * provide control queue via peers as well.
3425 */
3426 if (n->nic_conf.peers.queues) {
3427 for (i = 0; i < n->max_ncs; i++) {
3428 if (n->nic_conf.peers.ncs[i]->is_datapath) {
3429 ++n->max_queue_pairs;
3430 }
3431 }
3432 }
3433 n->max_queue_pairs = MAX(n->max_queue_pairs, 1);
3434
Jason Wang441537f2021-10-20 12:55:57 +08003435 if (n->max_queue_pairs * 2 + 1 > VIRTIO_QUEUE_MAX) {
Jason Wang22288fe2021-10-20 12:55:59 +08003436 error_setg(errp, "Invalid number of queue pairs (= %" PRIu32 "), "
Stefan Weil631b22e2015-04-09 20:32:39 +02003437 "must be a positive integer less than %d.",
Jason Wang441537f2021-10-20 12:55:57 +08003438 n->max_queue_pairs, (VIRTIO_QUEUE_MAX - 1) / 2);
Jason Wang7e0e7362015-03-20 14:07:50 +08003439 virtio_cleanup(vdev);
3440 return;
3441 }
Jason Wang441537f2021-10-20 12:55:57 +08003442 n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queue_pairs);
3443 n->curr_queue_pairs = 1;
KONRAD Frederic1773d9e2013-04-11 16:30:02 +02003444 n->tx_timeout = n->net_conf.txtimer;
Alex Williamsona697a332010-09-02 09:01:10 -06003445
KONRAD Frederic1773d9e2013-04-11 16:30:02 +02003446 if (n->net_conf.tx && strcmp(n->net_conf.tx, "timer")
3447 && strcmp(n->net_conf.tx, "bh")) {
Markus Armbruster07656912018-10-17 10:26:28 +02003448 warn_report("virtio-net: "
3449 "Unknown option tx=%s, valid options: \"timer\" \"bh\"",
3450 n->net_conf.tx);
3451 error_printf("Defaulting to \"bh\"");
Alex Williamsona697a332010-09-02 09:01:10 -06003452 }
3453
Michael S. Tsirkin2eef2782017-07-03 22:25:24 +03003454 n->net_conf.tx_queue_size = MIN(virtio_net_max_tx_queue_size(n),
3455 n->net_conf.tx_queue_size);
Wei Wang9b02e162017-06-28 10:37:59 +08003456
Jason Wang441537f2021-10-20 12:55:57 +08003457 for (i = 0; i < n->max_queue_pairs; i++) {
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08003458 virtio_net_add_queue(n, i);
Alex Williamsona697a332010-09-02 09:01:10 -06003459 }
Jason Wangda51a332015-05-29 14:15:24 +08003460
KONRAD Frederic17a0ca52013-04-11 16:30:01 +02003461 n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
KONRAD Frederic1773d9e2013-04-11 16:30:02 +02003462 qemu_macaddr_default_if_unset(&n->nic_conf.macaddr);
3463 memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac));
aliguori554c97d2009-01-08 19:46:33 +00003464 n->status = VIRTIO_NET_S_LINK_UP;
Dr. David Alan Gilbert9d8c6a22019-02-27 13:24:07 +00003465 qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(),
3466 QEMU_CLOCK_VIRTUAL,
3467 virtio_net_announce_timer, n);
Dr. David Alan Gilbertb2c929f2019-02-27 13:24:10 +00003468 n->announce_timer.round = 0;
aliguorifbe78f42008-12-17 19:13:11 +00003469
KONRAD Frederic8a253ec2013-05-15 14:12:49 +02003470 if (n->netclient_type) {
3471 /*
3472 * Happen when virtio_net_set_netclient_name has been called.
3473 */
3474 n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
3475 n->netclient_type, n->netclient_name, n);
3476 } else {
3477 n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
Andreas Färber284a32f2013-07-30 05:02:48 +02003478 object_get_typename(OBJECT(dev)), dev->id, n);
KONRAD Frederic8a253ec2013-05-15 14:12:49 +02003479 }
3480
Jason Wang441537f2021-10-20 12:55:57 +08003481 for (i = 0; i < n->max_queue_pairs; i++) {
Bin Mengd4c62932021-03-17 14:26:30 +08003482 n->nic->ncs[i].do_not_pad = true;
3483 }
3484
Michael S. Tsirkin6e371ab2012-09-24 17:04:21 +02003485 peer_test_vnet_hdr(n);
3486 if (peer_has_vnet_hdr(n)) {
Jason Wang441537f2021-10-20 12:55:57 +08003487 for (i = 0; i < n->max_queue_pairs; i++) {
Stefan Hajnoczid6085e32014-02-20 12:14:07 +01003488 qemu_using_vnet_hdr(qemu_get_subqueue(n->nic, i)->peer, true);
Jason Wangfed699f2013-01-30 19:12:39 +08003489 }
Michael S. Tsirkin6e371ab2012-09-24 17:04:21 +02003490 n->host_hdr_len = sizeof(struct virtio_net_hdr);
3491 } else {
3492 n->host_hdr_len = 0;
3493 }
Mark McLoughlineb6b6c12009-11-25 18:49:11 +00003494
KONRAD Frederic1773d9e2013-04-11 16:30:02 +02003495 qemu_format_nic_info_str(qemu_get_queue(n->nic), n->nic_conf.macaddr.a);
aliguori96d5e202009-01-07 17:47:15 +00003496
Jason Wangfed699f2013-01-30 19:12:39 +08003497 n->vqs[0].tx_waiting = 0;
KONRAD Frederic1773d9e2013-04-11 16:30:02 +02003498 n->tx_burst = n->net_conf.txburst;
Yuri Benditoviche22f0602020-05-08 15:59:31 +03003499 virtio_net_set_mrg_rx_bufs(n, 0, 0, 0);
aliguori002437c2009-02-05 22:36:20 +00003500 n->promisc = 1; /* for compatibility */
aliguorifbe78f42008-12-17 19:13:11 +00003501
Anthony Liguori7267c092011-08-20 22:09:37 -05003502 n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);
aliguorib6503ed2009-02-05 22:36:28 +00003503
Anthony Liguori7267c092011-08-20 22:09:37 -05003504 n->vlans = g_malloc0(MAX_VLAN >> 3);
aliguorif21c0ed2009-02-05 22:36:32 +00003505
Amos Kongb1be4282013-06-14 15:45:52 +08003506 nc = qemu_get_queue(n->nic);
3507 nc->rxfilter_notify_enabled = 1;
3508
Cindy Lue87936e2020-09-25 23:13:33 +08003509 if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) {
3510 struct virtio_net_config netcfg = {};
3511 memcpy(&netcfg.mac, &n->nic_conf.macaddr, ETH_ALEN);
3512 vhost_net_set_config(get_vhost_net(nc->peer),
3513 (uint8_t *)&netcfg, 0, ETH_ALEN, VHOST_SET_CONFIG_TYPE_MASTER);
3514 }
Yuri Benditovich2974e912019-01-03 15:12:29 +02003515 QTAILQ_INIT(&n->rsc_chains);
Andreas Färber284a32f2013-07-30 05:02:48 +02003516 n->qdev = dev;
Yuri Benditovich4474e372020-05-08 15:59:29 +03003517
3518 net_rx_pkt_init(&n->rx_pkt, false);
Andrew Melnychenko0145c392021-05-14 14:48:33 +03003519
3520 if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) {
3521 virtio_net_load_ebpf(n);
3522 }
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003523}
3524
Markus Armbrusterb69c3c22020-05-05 17:29:24 +02003525static void virtio_net_device_unrealize(DeviceState *dev)
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003526{
Andreas Färber306ec6c2013-07-30 03:50:44 +02003527 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
3528 VirtIONet *n = VIRTIO_NET(dev);
Jason Wang441537f2021-10-20 12:55:57 +08003529 int i, max_queue_pairs;
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003530
Andrew Melnychenko0145c392021-05-14 14:48:33 +03003531 if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) {
3532 virtio_net_unload_ebpf(n);
3533 }
3534
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003535 /* This will stop vhost backend if appropriate. */
3536 virtio_net_set_status(vdev, 0);
3537
Markus Armbruster9e288402014-06-06 18:43:29 +02003538 g_free(n->netclient_name);
3539 n->netclient_name = NULL;
3540 g_free(n->netclient_type);
3541 n->netclient_type = NULL;
KONRAD Frederic8a253ec2013-05-15 14:12:49 +02003542
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003543 g_free(n->mac_table.macs);
3544 g_free(n->vlans);
3545
Jens Freimann9711cd02019-10-29 12:49:04 +01003546 if (n->failover) {
Kevin Wolff3558b12021-10-08 15:34:41 +02003547 qobject_unref(n->primary_opts);
Juan Quintela65018102020-07-03 13:48:13 +02003548 device_listener_unregister(&n->primary_listener);
Laurent Vivier1e157662021-04-27 15:51:47 +02003549 remove_migration_state_change_notifier(&n->migration_state);
Kevin Wolff3558b12021-10-08 15:34:41 +02003550 } else {
3551 assert(n->primary_opts == NULL);
Jens Freimann9711cd02019-10-29 12:49:04 +01003552 }
3553
Jason Wang441537f2021-10-20 12:55:57 +08003554 max_queue_pairs = n->multiqueue ? n->max_queue_pairs : 1;
3555 for (i = 0; i < max_queue_pairs; i++) {
Wen Congyangf9d6dbf2015-07-15 17:20:59 +08003556 virtio_net_del_queue(n, i);
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003557 }
Yuri Benditovichd945d9f2019-12-26 06:36:49 +02003558 /* delete also control vq */
Jason Wang441537f2021-10-20 12:55:57 +08003559 virtio_del_queue(vdev, max_queue_pairs * 2);
Dr. David Alan Gilbert944458b2019-06-20 19:47:04 +01003560 qemu_announce_timer_del(&n->announce_timer, false);
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003561 g_free(n->vqs);
3562 qemu_del_nic(n->nic);
Yuri Benditovich2974e912019-01-03 15:12:29 +02003563 virtio_net_rsc_cleanup(n);
Yuri Benditovich59079022020-05-08 15:59:28 +03003564 g_free(n->rss_data.indirections_table);
Yuri Benditovich4474e372020-05-08 15:59:29 +03003565 net_rx_pkt_uninit(n->rx_pkt);
KONRAD Frederic6a1a8cc2013-04-24 10:21:22 +02003566 virtio_cleanup(vdev);
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003567}
3568
3569static void virtio_net_instance_init(Object *obj)
3570{
3571 VirtIONet *n = VIRTIO_NET(obj);
3572
3573 /*
3574 * The default config_size is sizeof(struct virtio_net_config).
3575 * Can be overriden with virtio_net_set_config_size.
3576 */
3577 n->config_size = sizeof(struct virtio_net_config);
Gongleiaa4197c2014-10-07 16:00:12 +08003578 device_add_bootindex_property(obj, &n->nic_conf.bootindex,
3579 "bootindex", "/ethernet-phy@0",
Markus Armbruster40c22812020-05-05 17:29:23 +02003580 DEVICE(n));
Andrew Melnychenko0145c392021-05-14 14:48:33 +03003581
3582 ebpf_rss_init(&n->ebpf_rss);
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003583}
3584
Dr. David Alan Gilbert44b1ff32017-09-25 12:29:12 +01003585static int virtio_net_pre_save(void *opaque)
Halil Pasic4d45dcf2016-10-06 14:55:41 +02003586{
3587 VirtIONet *n = opaque;
3588
3589 /* At this point, backend must be stopped, otherwise
3590 * it might keep writing to memory. */
3591 assert(!n->vhost_started);
Dr. David Alan Gilbert44b1ff32017-09-25 12:29:12 +01003592
3593 return 0;
Halil Pasic4d45dcf2016-10-06 14:55:41 +02003594}
3595
Jens Freimann9711cd02019-10-29 12:49:04 +01003596static bool primary_unplug_pending(void *opaque)
3597{
3598 DeviceState *dev = opaque;
Juan Quintela21e87092020-11-18 09:37:48 +01003599 DeviceState *primary;
Jens Freimann9711cd02019-10-29 12:49:04 +01003600 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
3601 VirtIONet *n = VIRTIO_NET(vdev);
3602
Jens Freimann284f42a2019-11-20 16:49:48 +01003603 if (!virtio_vdev_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
3604 return false;
3605 }
Juan Quintela21e87092020-11-18 09:37:48 +01003606 primary = failover_find_primary_device(n);
3607 return primary ? primary->pending_deleted_event : false;
Jens Freimann9711cd02019-10-29 12:49:04 +01003608}
3609
3610static bool dev_unplug_pending(void *opaque)
3611{
3612 DeviceState *dev = opaque;
3613 VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev);
3614
3615 return vdc->primary_unplug_pending(dev);
3616}
3617
Halil Pasic4d45dcf2016-10-06 14:55:41 +02003618static const VMStateDescription vmstate_virtio_net = {
3619 .name = "virtio-net",
3620 .minimum_version_id = VIRTIO_NET_VM_VERSION,
3621 .version_id = VIRTIO_NET_VM_VERSION,
3622 .fields = (VMStateField[]) {
3623 VMSTATE_VIRTIO_DEVICE,
3624 VMSTATE_END_OF_LIST()
3625 },
3626 .pre_save = virtio_net_pre_save,
Jens Freimann9711cd02019-10-29 12:49:04 +01003627 .dev_unplug_pending = dev_unplug_pending,
Halil Pasic4d45dcf2016-10-06 14:55:41 +02003628};
Dr. David Alan Gilbert290c2422016-07-14 18:22:50 +01003629
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003630static Property virtio_net_properties[] = {
Jason Baron127833e2018-03-07 22:25:40 -05003631 DEFINE_PROP_BIT64("csum", VirtIONet, host_features,
3632 VIRTIO_NET_F_CSUM, true),
3633 DEFINE_PROP_BIT64("guest_csum", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003634 VIRTIO_NET_F_GUEST_CSUM, true),
Jason Baron127833e2018-03-07 22:25:40 -05003635 DEFINE_PROP_BIT64("gso", VirtIONet, host_features, VIRTIO_NET_F_GSO, true),
3636 DEFINE_PROP_BIT64("guest_tso4", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003637 VIRTIO_NET_F_GUEST_TSO4, true),
Jason Baron127833e2018-03-07 22:25:40 -05003638 DEFINE_PROP_BIT64("guest_tso6", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003639 VIRTIO_NET_F_GUEST_TSO6, true),
Jason Baron127833e2018-03-07 22:25:40 -05003640 DEFINE_PROP_BIT64("guest_ecn", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003641 VIRTIO_NET_F_GUEST_ECN, true),
Jason Baron127833e2018-03-07 22:25:40 -05003642 DEFINE_PROP_BIT64("guest_ufo", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003643 VIRTIO_NET_F_GUEST_UFO, true),
Jason Baron127833e2018-03-07 22:25:40 -05003644 DEFINE_PROP_BIT64("guest_announce", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003645 VIRTIO_NET_F_GUEST_ANNOUNCE, true),
Jason Baron127833e2018-03-07 22:25:40 -05003646 DEFINE_PROP_BIT64("host_tso4", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003647 VIRTIO_NET_F_HOST_TSO4, true),
Jason Baron127833e2018-03-07 22:25:40 -05003648 DEFINE_PROP_BIT64("host_tso6", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003649 VIRTIO_NET_F_HOST_TSO6, true),
Jason Baron127833e2018-03-07 22:25:40 -05003650 DEFINE_PROP_BIT64("host_ecn", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003651 VIRTIO_NET_F_HOST_ECN, true),
Jason Baron127833e2018-03-07 22:25:40 -05003652 DEFINE_PROP_BIT64("host_ufo", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003653 VIRTIO_NET_F_HOST_UFO, true),
Jason Baron127833e2018-03-07 22:25:40 -05003654 DEFINE_PROP_BIT64("mrg_rxbuf", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003655 VIRTIO_NET_F_MRG_RXBUF, true),
Jason Baron127833e2018-03-07 22:25:40 -05003656 DEFINE_PROP_BIT64("status", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003657 VIRTIO_NET_F_STATUS, true),
Jason Baron127833e2018-03-07 22:25:40 -05003658 DEFINE_PROP_BIT64("ctrl_vq", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003659 VIRTIO_NET_F_CTRL_VQ, true),
Jason Baron127833e2018-03-07 22:25:40 -05003660 DEFINE_PROP_BIT64("ctrl_rx", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003661 VIRTIO_NET_F_CTRL_RX, true),
Jason Baron127833e2018-03-07 22:25:40 -05003662 DEFINE_PROP_BIT64("ctrl_vlan", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003663 VIRTIO_NET_F_CTRL_VLAN, true),
Jason Baron127833e2018-03-07 22:25:40 -05003664 DEFINE_PROP_BIT64("ctrl_rx_extra", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003665 VIRTIO_NET_F_CTRL_RX_EXTRA, true),
Jason Baron127833e2018-03-07 22:25:40 -05003666 DEFINE_PROP_BIT64("ctrl_mac_addr", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003667 VIRTIO_NET_F_CTRL_MAC_ADDR, true),
Jason Baron127833e2018-03-07 22:25:40 -05003668 DEFINE_PROP_BIT64("ctrl_guest_offloads", VirtIONet, host_features,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003669 VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, true),
Jason Baron127833e2018-03-07 22:25:40 -05003670 DEFINE_PROP_BIT64("mq", VirtIONet, host_features, VIRTIO_NET_F_MQ, false),
Yuri Benditovich59079022020-05-08 15:59:28 +03003671 DEFINE_PROP_BIT64("rss", VirtIONet, host_features,
3672 VIRTIO_NET_F_RSS, false),
Yuri Benditoviche22f0602020-05-08 15:59:31 +03003673 DEFINE_PROP_BIT64("hash", VirtIONet, host_features,
3674 VIRTIO_NET_F_HASH_REPORT, false),
Yuri Benditovich2974e912019-01-03 15:12:29 +02003675 DEFINE_PROP_BIT64("guest_rsc_ext", VirtIONet, host_features,
3676 VIRTIO_NET_F_RSC_EXT, false),
3677 DEFINE_PROP_UINT32("rsc_interval", VirtIONet, rsc_timeout,
3678 VIRTIO_NET_RSC_DEFAULT_INTERVAL),
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003679 DEFINE_NIC_PROPERTIES(VirtIONet, nic_conf),
3680 DEFINE_PROP_UINT32("x-txtimer", VirtIONet, net_conf.txtimer,
Shannon Zhao87108bb2015-06-10 23:04:30 +08003681 TX_TIMER_INTERVAL),
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003682 DEFINE_PROP_INT32("x-txburst", VirtIONet, net_conf.txburst, TX_BURST),
3683 DEFINE_PROP_STRING("tx", VirtIONet, net_conf.tx),
Michael S. Tsirkin1c0fbfa2016-08-10 17:47:16 +03003684 DEFINE_PROP_UINT16("rx_queue_size", VirtIONet, net_conf.rx_queue_size,
3685 VIRTIO_NET_RX_QUEUE_DEFAULT_SIZE),
Wei Wang9b02e162017-06-28 10:37:59 +08003686 DEFINE_PROP_UINT16("tx_queue_size", VirtIONet, net_conf.tx_queue_size,
3687 VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE),
Maxime Coquelina93e5992016-12-10 16:30:38 +01003688 DEFINE_PROP_UINT16("host_mtu", VirtIONet, net_conf.mtu, 0),
Maxime Coquelin75ebec12017-05-23 14:31:19 +02003689 DEFINE_PROP_BOOL("x-mtu-bypass-backend", VirtIONet, mtu_bypass_backend,
3690 true),
Jason Baron94739392018-03-07 22:25:41 -05003691 DEFINE_PROP_INT32("speed", VirtIONet, net_conf.speed, SPEED_UNKNOWN),
3692 DEFINE_PROP_STRING("duplex", VirtIONet, net_conf.duplex_str),
Jens Freimann9711cd02019-10-29 12:49:04 +01003693 DEFINE_PROP_BOOL("failover", VirtIONet, failover, false),
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003694 DEFINE_PROP_END_OF_LIST(),
3695};
3696
3697static void virtio_net_class_init(ObjectClass *klass, void *data)
3698{
3699 DeviceClass *dc = DEVICE_CLASS(klass);
3700 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
Andreas Färbere6f746b2013-07-30 02:36:06 +02003701
Marc-André Lureau4f67d302020-01-10 19:30:32 +04003702 device_class_set_props(dc, virtio_net_properties);
Dr. David Alan Gilbert290c2422016-07-14 18:22:50 +01003703 dc->vmsd = &vmstate_virtio_net;
Marcel Apfelbaum125ee0e2013-07-29 17:17:45 +03003704 set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
Andreas Färbere6f746b2013-07-30 02:36:06 +02003705 vdc->realize = virtio_net_device_realize;
Andreas Färber306ec6c2013-07-30 03:50:44 +02003706 vdc->unrealize = virtio_net_device_unrealize;
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003707 vdc->get_config = virtio_net_get_config;
3708 vdc->set_config = virtio_net_set_config;
3709 vdc->get_features = virtio_net_get_features;
3710 vdc->set_features = virtio_net_set_features;
3711 vdc->bad_features = virtio_net_bad_features;
3712 vdc->reset = virtio_net_reset;
3713 vdc->set_status = virtio_net_set_status;
3714 vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
3715 vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;
Michael S. Tsirkin2a083ff2016-11-04 12:27:52 +02003716 vdc->legacy_features |= (0x1 << VIRTIO_NET_F_GSO);
Mikhail Sennikovsky7788c3f2019-10-11 15:58:04 +02003717 vdc->post_load = virtio_net_post_load_virtio;
Dr. David Alan Gilbert982b78c2017-02-03 16:06:51 +00003718 vdc->vmsd = &vmstate_virtio_net_device;
Jens Freimann9711cd02019-10-29 12:49:04 +01003719 vdc->primary_unplug_pending = primary_unplug_pending;
KONRAD Frederic17ec5a82013-04-11 16:29:57 +02003720}
3721
3722static const TypeInfo virtio_net_info = {
3723 .name = TYPE_VIRTIO_NET,
3724 .parent = TYPE_VIRTIO_DEVICE,
3725 .instance_size = sizeof(VirtIONet),
3726 .instance_init = virtio_net_instance_init,
3727 .class_init = virtio_net_class_init,
3728};
3729
3730static void virtio_register_types(void)
3731{
3732 type_register_static(&virtio_net_info);
3733}
3734
3735type_init(virtio_register_types)