Lines Matching +full:iov +full:- +full:supply
10 * the COPYING file in the top-level directory.
16 #include "qemu/iov.h"
18 #include "qemu/main-loop.h"
24 #include "qemu/error-report.h"
28 #include "qemu/config-file.h"
30 #include "hw/virtio/virtio-net.h"
33 #include "hw/virtio/virtio-bus.h"
35 #include "qapi/qapi-events-net.h"
36 #include "hw/qdev-properties.h"
37 #include "qapi/qapi-types-migration.h"
38 #include "qapi/qapi-events-migration.h"
39 #include "hw/virtio/virtio-access.h"
41 #include "standard-headers/linux/ethtool.h"
58 /* for now, only allow larger queue_pairs; with virtio-1, guest can downsize */
68 #define VIRTIO_NET_MAX_IP4_PAYLOAD (65535 - sizeof(struct ip_header))
119 return &n->vqs[nc->queue_index]; in virtio_net_get_subqueue()
129 if (!nc->peer) { in flush_or_purge_queued_packets()
133 qemu_flush_or_purge_queued_packets(nc->peer, true); in flush_or_purge_queued_packets()
134 assert(!virtio_net_get_subqueue(nc)->async_tx.elem); in flush_or_purge_queued_packets()
138 * - we could suppress RX interrupt if we were so inclined.
145 NetClientState *nc = qemu_get_queue(n->nic); in virtio_net_get_config()
150 virtio_stw_p(vdev, &netcfg.status, n->status); in virtio_net_get_config()
151 virtio_stw_p(vdev, &netcfg.max_virtqueue_pairs, n->max_queue_pairs); in virtio_net_get_config()
152 virtio_stw_p(vdev, &netcfg.mtu, n->net_conf.mtu); in virtio_net_get_config()
153 memcpy(netcfg.mac, n->mac, ETH_ALEN); in virtio_net_get_config()
154 virtio_stl_p(vdev, &netcfg.speed, n->net_conf.speed); in virtio_net_get_config()
155 netcfg.duplex = n->net_conf.duplex; in virtio_net_get_config()
162 memcpy(config, &netcfg, n->config_size); in virtio_net_get_config()
168 if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { in virtio_net_get_config()
169 ret = vhost_net_get_config(get_vhost_net(nc->peer), (uint8_t *)&netcfg, in virtio_net_get_config()
170 n->config_size); in virtio_net_get_config()
171 if (ret == -1) { in virtio_net_get_config()
179 * correctly elsewhere - just not reported by the device. in virtio_net_get_config()
183 memcpy(netcfg.mac, n->mac, ETH_ALEN); in virtio_net_get_config()
187 n->status & VIRTIO_NET_S_ANNOUNCE); in virtio_net_get_config()
188 memcpy(config, &netcfg, n->config_size); in virtio_net_get_config()
196 NetClientState *nc = qemu_get_queue(n->nic); in virtio_net_set_config()
198 memcpy(&netcfg, config, n->config_size); in virtio_net_set_config()
202 memcmp(netcfg.mac, n->mac, ETH_ALEN)) { in virtio_net_set_config()
203 memcpy(n->mac, netcfg.mac, ETH_ALEN); in virtio_net_set_config()
204 qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); in virtio_net_set_config()
211 if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { in virtio_net_set_config()
212 vhost_net_set_config(get_vhost_net(nc->peer), in virtio_net_set_config()
213 (uint8_t *)&netcfg, 0, n->config_size, in virtio_net_set_config()
222 (n->status & VIRTIO_NET_S_LINK_UP) && vdev->vm_running; in virtio_net_started()
230 net->status |= VIRTIO_NET_S_ANNOUNCE; in virtio_net_announce_notify()
237 trace_virtio_net_announce_timer(n->announce_timer.round); in virtio_net_announce_timer()
239 n->announce_timer.round--; in virtio_net_announce_timer()
253 if (n->announce_timer.round) { in virtio_net_announce()
266 NetClientState *nc = qemu_get_queue(n->nic); in virtio_net_vhost_status()
267 int queue_pairs = n->multiqueue ? n->max_queue_pairs : 1; in virtio_net_vhost_status()
269 n->max_ncs - n->max_queue_pairs : 0; in virtio_net_vhost_status()
271 if (!get_vhost_net(nc->peer)) { in virtio_net_vhost_status()
275 if ((virtio_net_started(n, status) && !nc->peer->link_down) == in virtio_net_vhost_status()
276 !!n->vhost_started) { in virtio_net_vhost_status()
279 if (!n->vhost_started) { in virtio_net_vhost_status()
282 if (n->needs_vnet_hdr_swap) { in virtio_net_vhost_status()
293 NetClientState *qnc = qemu_get_subqueue(n->nic, i); in virtio_net_vhost_status()
296 qemu_net_queue_purge(qnc->peer->incoming_queue, qnc); in virtio_net_vhost_status()
297 qemu_net_queue_purge(qnc->incoming_queue, qnc->peer); in virtio_net_vhost_status()
300 if (virtio_has_feature(vdev->guest_features, VIRTIO_NET_F_MTU)) { in virtio_net_vhost_status()
301 r = vhost_net_set_mtu(get_vhost_net(nc->peer), n->net_conf.mtu); in virtio_net_vhost_status()
304 n->net_conf.mtu); in virtio_net_vhost_status()
310 n->vhost_started = 1; in virtio_net_vhost_status()
311 r = vhost_net_start(vdev, n->nic->ncs, queue_pairs, cvq); in virtio_net_vhost_status()
314 "falling back on userspace virtio", -r); in virtio_net_vhost_status()
315 n->vhost_started = 0; in virtio_net_vhost_status()
318 vhost_net_stop(vdev, n->nic->ncs, queue_pairs, cvq); in virtio_net_vhost_status()
319 n->vhost_started = 0; in virtio_net_vhost_status()
342 while (--i >= 0) { in virtio_net_set_vnet_endian()
356 int queue_pairs = n->multiqueue ? n->max_queue_pairs : 1; in virtio_net_vnet_endian_status()
362 * virtio-net code. in virtio_net_vnet_endian_status()
364 n->needs_vnet_hdr_swap = n->has_vnet_hdr && in virtio_net_vnet_endian_status()
365 virtio_net_set_vnet_endian(vdev, n->nic->ncs, in virtio_net_vnet_endian_status()
367 } else if (virtio_net_started(n, vdev->status)) { in virtio_net_vnet_endian_status()
373 virtio_net_set_vnet_endian(vdev, n->nic->ncs, queue_pairs, false); in virtio_net_vnet_endian_status()
395 for (i = 0; i < n->max_queue_pairs; i++) { in virtio_net_set_status()
396 NetClientState *ncs = qemu_get_subqueue(n->nic, i); in virtio_net_set_status()
398 q = &n->vqs[i]; in virtio_net_set_status()
400 if ((!n->multiqueue && i != 0) || i >= n->curr_queue_pairs) { in virtio_net_set_status()
406 virtio_net_started(n, queue_status) && !n->vhost_started; in virtio_net_set_status()
412 if (!q->tx_waiting) { in virtio_net_set_status()
417 if (q->tx_timer) { in virtio_net_set_status()
418 timer_mod(q->tx_timer, in virtio_net_set_status()
419 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout); in virtio_net_set_status()
421 replay_bh_schedule_event(q->tx_bh); in virtio_net_set_status()
424 if (q->tx_timer) { in virtio_net_set_status()
425 timer_del(q->tx_timer); in virtio_net_set_status()
427 qemu_bh_cancel(q->tx_bh); in virtio_net_set_status()
429 if ((n->status & VIRTIO_NET_S_LINK_UP) == 0 && in virtio_net_set_status()
431 vdev->vm_running) { in virtio_net_set_status()
434 q->tx_waiting = 0; in virtio_net_set_status()
435 virtio_queue_set_notification(q->tx_vq, 1); in virtio_net_set_status()
436 virtio_net_drop_tx_queue_data(vdev, q->tx_vq); in virtio_net_set_status()
446 uint16_t old_status = n->status; in virtio_net_set_link_status()
448 if (nc->link_down) in virtio_net_set_link_status()
449 n->status &= ~VIRTIO_NET_S_LINK_UP; in virtio_net_set_link_status()
451 n->status |= VIRTIO_NET_S_LINK_UP; in virtio_net_set_link_status()
453 if (n->status != old_status) in virtio_net_set_link_status()
456 virtio_net_set_status(vdev, vdev->status); in virtio_net_set_link_status()
463 if (nc->rxfilter_notify_enabled) { in rxfilter_notify()
464 char *path = object_get_canonical_path(OBJECT(n->qdev)); in rxfilter_notify()
465 qapi_event_send_nic_rx_filter_changed(n->netclient_name, path); in rxfilter_notify()
469 nc->rxfilter_notify_enabled = 0; in rxfilter_notify()
480 for (j = 0; n->vlans[i] && j <= 0x1f; j++) { in get_vlan_table()
481 if (n->vlans[i] & (1U << j)) { in get_vlan_table()
499 info->name = g_strdup(nc->name); in virtio_net_query_rxfilter()
500 info->promiscuous = n->promisc; in virtio_net_query_rxfilter()
502 if (n->nouni) { in virtio_net_query_rxfilter()
503 info->unicast = RX_STATE_NONE; in virtio_net_query_rxfilter()
504 } else if (n->alluni) { in virtio_net_query_rxfilter()
505 info->unicast = RX_STATE_ALL; in virtio_net_query_rxfilter()
507 info->unicast = RX_STATE_NORMAL; in virtio_net_query_rxfilter()
510 if (n->nomulti) { in virtio_net_query_rxfilter()
511 info->multicast = RX_STATE_NONE; in virtio_net_query_rxfilter()
512 } else if (n->allmulti) { in virtio_net_query_rxfilter()
513 info->multicast = RX_STATE_ALL; in virtio_net_query_rxfilter()
515 info->multicast = RX_STATE_NORMAL; in virtio_net_query_rxfilter()
518 info->broadcast_allowed = n->nobcast; in virtio_net_query_rxfilter()
519 info->multicast_overflow = n->mac_table.multi_overflow; in virtio_net_query_rxfilter()
520 info->unicast_overflow = n->mac_table.uni_overflow; in virtio_net_query_rxfilter()
522 info->main_mac = qemu_mac_strdup_printf(n->mac); in virtio_net_query_rxfilter()
525 for (i = 0; i < n->mac_table.first_multi; i++) { in virtio_net_query_rxfilter()
527 qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN)); in virtio_net_query_rxfilter()
529 info->unicast_table = str_list; in virtio_net_query_rxfilter()
532 for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) { in virtio_net_query_rxfilter()
534 qemu_mac_strdup_printf(n->mac_table.macs + i * ETH_ALEN)); in virtio_net_query_rxfilter()
536 info->multicast_table = str_list; in virtio_net_query_rxfilter()
537 info->vlan_table = get_vlan_table(n); in virtio_net_query_rxfilter()
540 info->vlan = RX_STATE_ALL; in virtio_net_query_rxfilter()
541 } else if (!info->vlan_table) { in virtio_net_query_rxfilter()
542 info->vlan = RX_STATE_NONE; in virtio_net_query_rxfilter()
544 info->vlan = RX_STATE_NORMAL; in virtio_net_query_rxfilter()
548 nc->rxfilter_notify_enabled = 1; in virtio_net_query_rxfilter()
559 if (queue_index >= n->max_queue_pairs * 2) { in virtio_net_queue_reset()
563 nc = qemu_get_subqueue(n->nic, vq2q(queue_index)); in virtio_net_queue_reset()
565 if (!nc->peer) { in virtio_net_queue_reset()
569 if (get_vhost_net(nc->peer) && in virtio_net_queue_reset()
570 nc->peer->info->type == NET_CLIENT_DRIVER_TAP) { in virtio_net_queue_reset()
584 if (queue_index >= n->max_queue_pairs * 2) { in virtio_net_queue_enable()
588 nc = qemu_get_subqueue(n->nic, vq2q(queue_index)); in virtio_net_queue_enable()
590 if (!nc->peer || !vdev->vhost_started) { in virtio_net_queue_enable()
594 if (get_vhost_net(nc->peer) && in virtio_net_queue_enable()
595 nc->peer->info->type == NET_CLIENT_DRIVER_TAP) { in virtio_net_queue_enable()
606 NetClientState *nc = qemu_get_queue(n->nic); in peer_test_vnet_hdr()
607 if (!nc->peer) { in peer_test_vnet_hdr()
611 n->has_vnet_hdr = qemu_has_vnet_hdr(nc->peer); in peer_test_vnet_hdr()
616 return n->has_vnet_hdr; in peer_has_vnet_hdr()
624 n->has_ufo = qemu_has_ufo(qemu_get_queue(n->nic)->peer); in peer_has_ufo()
626 return n->has_ufo; in peer_has_ufo()
635 return qemu_has_uso(qemu_get_queue(n->nic)->peer); in peer_has_uso()
644 n->mergeable_rx_bufs = mergeable_rx_bufs; in virtio_net_set_mrg_rx_bufs()
647 n->guest_hdr_len = hash_report ? in virtio_net_set_mrg_rx_bufs()
650 n->rss_data.populate_hash = !!hash_report; in virtio_net_set_mrg_rx_bufs()
652 n->guest_hdr_len = n->mergeable_rx_bufs ? in virtio_net_set_mrg_rx_bufs()
655 n->rss_data.populate_hash = false; in virtio_net_set_mrg_rx_bufs()
658 for (i = 0; i < n->max_queue_pairs; i++) { in virtio_net_set_mrg_rx_bufs()
659 nc = qemu_get_subqueue(n->nic, i); in virtio_net_set_mrg_rx_bufs()
662 qemu_has_vnet_hdr_len(nc->peer, n->guest_hdr_len)) { in virtio_net_set_mrg_rx_bufs()
663 qemu_set_vnet_hdr_len(nc->peer, n->guest_hdr_len); in virtio_net_set_mrg_rx_bufs()
664 n->host_hdr_len = n->guest_hdr_len; in virtio_net_set_mrg_rx_bufs()
671 NetClientState *peer = n->nic_conf.peers.ncs[0]; in virtio_net_max_tx_queue_size()
674 * Backends other than vhost-user or vhost-vdpa don't support max queue in virtio_net_max_tx_queue_size()
681 switch(peer->info->type) { in virtio_net_max_tx_queue_size()
692 NetClientState *nc = qemu_get_subqueue(n->nic, index); in peer_attach()
694 if (!nc->peer) { in peer_attach()
698 if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) { in peer_attach()
699 vhost_set_vring_enable(nc->peer, 1); in peer_attach()
702 if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) { in peer_attach()
706 if (n->max_queue_pairs == 1) { in peer_attach()
710 return tap_enable(nc->peer); in peer_attach()
715 NetClientState *nc = qemu_get_subqueue(n->nic, index); in peer_detach()
717 if (!nc->peer) { in peer_detach()
721 if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) { in peer_detach()
722 vhost_set_vring_enable(nc->peer, 0); in peer_detach()
725 if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) { in peer_detach()
729 return tap_disable(nc->peer); in peer_detach()
737 if (n->nic->peer_deleted) { in virtio_net_set_queue_pairs()
741 for (i = 0; i < n->max_queue_pairs; i++) { in virtio_net_set_queue_pairs()
742 if (i < n->curr_queue_pairs) { in virtio_net_set_queue_pairs()
758 NetClientState *nc = qemu_get_queue(n->nic); in virtio_net_get_features()
760 /* Firstly sync all virtio-net possible supported features */ in virtio_net_get_features()
761 features |= n->host_features; in virtio_net_get_features()
794 if (!get_vhost_net(nc->peer)) { in virtio_net_get_features()
798 if (!ebpf_rss_is_loaded(&n->ebpf_rss)) { in virtio_net_get_features()
801 features = vhost_net_get_features(get_vhost_net(nc->peer), features); in virtio_net_get_features()
802 vdev->backend_features = features; in virtio_net_get_features()
804 if (n->mtu_bypass_backend && in virtio_net_get_features()
805 (n->host_features & 1ULL << VIRTIO_NET_F_MTU)) { in virtio_net_get_features()
820 if (!virtio_has_feature(vdev->backend_features, VIRTIO_NET_F_CTRL_VQ)) { in virtio_net_get_features()
844 qemu_set_offload(qemu_get_queue(n->nic)->peer, in virtio_net_apply_guest_offloads()
845 !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_CSUM)), in virtio_net_apply_guest_offloads()
846 !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO4)), in virtio_net_apply_guest_offloads()
847 !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO6)), in virtio_net_apply_guest_offloads()
848 !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_ECN)), in virtio_net_apply_guest_offloads()
849 !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_UFO)), in virtio_net_apply_guest_offloads()
850 !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_USO4)), in virtio_net_apply_guest_offloads()
851 !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_USO6))); in virtio_net_apply_guest_offloads()
871 return virtio_net_guest_offloads_by_features(vdev->guest_features); in virtio_net_supported_guest_offloads()
896 if (!g_strcmp0(pci_dev->failover_pair_id, fdev->n->netclient_name)) { in failover_set_primary()
897 fdev->dev = dev; in failover_set_primary()
905 * Find the primary device for this failover virtio-net
930 if (!n->primary_opts) { in failover_add_primary()
932 error_append_hint(errp, "Virtio-net failover will not work. Make " in failover_add_primary()
934 " failover_pair_id=%s\n", n->netclient_name); in failover_add_primary()
938 dev = qdev_device_add_from_qdict(n->primary_opts, in failover_add_primary()
939 n->primary_opts_from_json, in failover_add_primary()
942 qobject_unref(n->primary_opts); in failover_add_primary()
943 n->primary_opts = NULL; in failover_add_primary()
956 if (n->mtu_bypass_backend && in virtio_net_set_features()
957 !virtio_has_feature(vdev->backend_features, VIRTIO_NET_F_MTU)) { in virtio_net_set_features()
973 n->rsc4_enabled = virtio_has_feature(features, VIRTIO_NET_F_RSC_EXT) && in virtio_net_set_features()
975 n->rsc6_enabled = virtio_has_feature(features, VIRTIO_NET_F_RSC_EXT) && in virtio_net_set_features()
977 n->rss_data.redirect = virtio_has_feature(features, VIRTIO_NET_F_RSS); in virtio_net_set_features()
979 if (n->has_vnet_hdr) { in virtio_net_set_features()
980 n->curr_guest_offloads = in virtio_net_set_features()
985 for (i = 0; i < n->max_queue_pairs; i++) { in virtio_net_set_features()
986 NetClientState *nc = qemu_get_subqueue(n->nic, i); in virtio_net_set_features()
988 if (!get_vhost_net(nc->peer)) { in virtio_net_set_features()
991 vhost_net_ack_features(get_vhost_net(nc->peer), features); in virtio_net_set_features()
994 * keep acked_features in NetVhostUserState up-to-date so it in virtio_net_set_features()
997 vhost_net_save_acked_features(nc->peer); in virtio_net_set_features()
1001 memset(n->vlans, 0xff, MAX_VLAN >> 3); in virtio_net_set_features()
1005 qapi_event_send_failover_negotiated(n->netclient_name); in virtio_net_set_features()
1006 qatomic_set(&n->failover_primary_hidden, false); in virtio_net_set_features()
1019 struct iovec *iov, unsigned int iov_cnt) in virtio_net_handle_rx_mode() argument
1023 NetClientState *nc = qemu_get_queue(n->nic); in virtio_net_handle_rx_mode()
1025 s = iov_to_buf(iov, iov_cnt, 0, &on, sizeof(on)); in virtio_net_handle_rx_mode()
1031 n->promisc = on; in virtio_net_handle_rx_mode()
1033 n->allmulti = on; in virtio_net_handle_rx_mode()
1035 n->alluni = on; in virtio_net_handle_rx_mode()
1037 n->nomulti = on; in virtio_net_handle_rx_mode()
1039 n->nouni = on; in virtio_net_handle_rx_mode()
1041 n->nobcast = on; in virtio_net_handle_rx_mode()
1052 struct iovec *iov, unsigned int iov_cnt) in virtio_net_handle_offloads() argument
1062 s = iov_to_buf(iov, iov_cnt, 0, &offloads, sizeof(offloads)); in virtio_net_handle_offloads()
1072 if (!n->has_vnet_hdr) { in virtio_net_handle_offloads()
1076 n->rsc4_enabled = virtio_has_feature(offloads, VIRTIO_NET_F_RSC_EXT) && in virtio_net_handle_offloads()
1078 n->rsc6_enabled = virtio_has_feature(offloads, VIRTIO_NET_F_RSC_EXT) && in virtio_net_handle_offloads()
1087 n->curr_guest_offloads = offloads; in virtio_net_handle_offloads()
1097 struct iovec *iov, unsigned int iov_cnt) in virtio_net_handle_mac() argument
1102 NetClientState *nc = qemu_get_queue(n->nic); in virtio_net_handle_mac()
1105 if (iov_size(iov, iov_cnt) != sizeof(n->mac)) { in virtio_net_handle_mac()
1108 s = iov_to_buf(iov, iov_cnt, 0, &n->mac, sizeof(n->mac)); in virtio_net_handle_mac()
1109 assert(s == sizeof(n->mac)); in virtio_net_handle_mac()
1110 qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); in virtio_net_handle_mac()
1126 s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries, in virtio_net_handle_mac()
1132 iov_discard_front(&iov, &iov_cnt, s); in virtio_net_handle_mac()
1134 if (mac_data.entries * ETH_ALEN > iov_size(iov, iov_cnt)) { in virtio_net_handle_mac()
1139 s = iov_to_buf(iov, iov_cnt, 0, macs, in virtio_net_handle_mac()
1149 iov_discard_front(&iov, &iov_cnt, mac_data.entries * ETH_ALEN); in virtio_net_handle_mac()
1153 s = iov_to_buf(iov, iov_cnt, 0, &mac_data.entries, in virtio_net_handle_mac()
1160 iov_discard_front(&iov, &iov_cnt, s); in virtio_net_handle_mac()
1162 if (mac_data.entries * ETH_ALEN != iov_size(iov, iov_cnt)) { in virtio_net_handle_mac()
1166 if (mac_data.entries <= MAC_TABLE_ENTRIES - in_use) { in virtio_net_handle_mac()
1167 s = iov_to_buf(iov, iov_cnt, 0, &macs[in_use * ETH_ALEN], in virtio_net_handle_mac()
1177 n->mac_table.in_use = in_use; in virtio_net_handle_mac()
1178 n->mac_table.first_multi = first_multi; in virtio_net_handle_mac()
1179 n->mac_table.uni_overflow = uni_overflow; in virtio_net_handle_mac()
1180 n->mac_table.multi_overflow = multi_overflow; in virtio_net_handle_mac()
1181 memcpy(n->mac_table.macs, macs, MAC_TABLE_ENTRIES * ETH_ALEN); in virtio_net_handle_mac()
1193 struct iovec *iov, unsigned int iov_cnt) in virtio_net_handle_vlan_table() argument
1198 NetClientState *nc = qemu_get_queue(n->nic); in virtio_net_handle_vlan_table()
1200 s = iov_to_buf(iov, iov_cnt, 0, &vid, sizeof(vid)); in virtio_net_handle_vlan_table()
1210 n->vlans[vid >> 5] |= (1U << (vid & 0x1f)); in virtio_net_handle_vlan_table()
1212 n->vlans[vid >> 5] &= ~(1U << (vid & 0x1f)); in virtio_net_handle_vlan_table()
1222 struct iovec *iov, unsigned int iov_cnt) in virtio_net_handle_announce() argument
1224 trace_virtio_net_handle_announce(n->announce_timer.round); in virtio_net_handle_announce()
1226 n->status & VIRTIO_NET_S_ANNOUNCE) { in virtio_net_handle_announce()
1227 n->status &= ~VIRTIO_NET_S_ANNOUNCE; in virtio_net_handle_announce()
1228 if (n->announce_timer.round) { in virtio_net_handle_announce()
1229 qemu_announce_timer_step(&n->announce_timer); in virtio_net_handle_announce()
1240 if (nc == NULL || nc->info->set_steering_ebpf == NULL) { in virtio_net_attach_ebpf_to_backend()
1245 return nc->info->set_steering_ebpf(nc, prog_fd); in virtio_net_attach_ebpf_to_backend()
1251 config->redirect = data->redirect; in rss_data_to_rss_config()
1252 config->populate_hash = data->populate_hash; in rss_data_to_rss_config()
1253 config->hash_types = data->hash_types; in rss_data_to_rss_config()
1254 config->indirections_len = data->indirections_len; in rss_data_to_rss_config()
1255 config->default_queue = data->default_queue; in rss_data_to_rss_config()
1262 if (!ebpf_rss_is_loaded(&n->ebpf_rss)) { in virtio_net_attach_ebpf_rss()
1266 rss_data_to_rss_config(&n->rss_data, &config); in virtio_net_attach_ebpf_rss()
1268 if (!ebpf_rss_set_all(&n->ebpf_rss, &config, in virtio_net_attach_ebpf_rss()
1269 n->rss_data.indirections_table, n->rss_data.key, in virtio_net_attach_ebpf_rss()
1274 if (!virtio_net_attach_ebpf_to_backend(n->nic, n->ebpf_rss.program_fd)) { in virtio_net_attach_ebpf_rss()
1283 virtio_net_attach_ebpf_to_backend(n->nic, -1); in virtio_net_detach_ebpf_rss()
1288 if (n->rss_data.enabled) { in virtio_net_commit_rss_config()
1289 n->rss_data.enabled_software_rss = n->rss_data.populate_hash; in virtio_net_commit_rss_config()
1290 if (n->rss_data.populate_hash) { in virtio_net_commit_rss_config()
1293 if (get_vhost_net(qemu_get_queue(n->nic)->peer)) { in virtio_net_commit_rss_config()
1296 warn_report("Can't load eBPF RSS - fallback to software RSS"); in virtio_net_commit_rss_config()
1297 n->rss_data.enabled_software_rss = true; in virtio_net_commit_rss_config()
1302 n->rss_data.hash_types, in virtio_net_commit_rss_config()
1303 n->rss_data.indirections_len, in virtio_net_commit_rss_config()
1304 sizeof(n->rss_data.key)); in virtio_net_commit_rss_config()
1313 if (!n->rss_data.enabled) { in virtio_net_disable_rss()
1317 n->rss_data.enabled = false; in virtio_net_disable_rss()
1323 int fds[EBPF_RSS_MAX_FDS] = { [0 ... EBPF_RSS_MAX_FDS - 1] = -1}; in virtio_net_load_ebpf_fds()
1327 if (n->nr_ebpf_rss_fds != EBPF_RSS_MAX_FDS) { in virtio_net_load_ebpf_fds()
1329 EBPF_RSS_MAX_FDS, n->nr_ebpf_rss_fds); in virtio_net_load_ebpf_fds()
1333 for (i = 0; i < n->nr_ebpf_rss_fds; i++) { in virtio_net_load_ebpf_fds()
1334 fds[i] = monitor_fd_param(monitor_cur(), n->ebpf_rss_fds[i], errp); in virtio_net_load_ebpf_fds()
1341 ret = ebpf_rss_load_fds(&n->ebpf_rss, fds[0], fds[1], fds[2], fds[3], errp); in virtio_net_load_ebpf_fds()
1345 for (i = 0; i < n->nr_ebpf_rss_fds && fds[i] != -1; i++) { in virtio_net_load_ebpf_fds()
1357 if (virtio_net_attach_ebpf_to_backend(n->nic, -1)) { in virtio_net_load_ebpf()
1358 trace_virtio_net_rss_load(n, n->nr_ebpf_rss_fds, n->ebpf_rss_fds); in virtio_net_load_ebpf()
1359 if (n->ebpf_rss_fds) { in virtio_net_load_ebpf()
1362 ret = ebpf_rss_load(&n->ebpf_rss, errp); in virtio_net_load_ebpf()
1371 virtio_net_attach_ebpf_to_backend(n->nic, -1); in virtio_net_unload_ebpf()
1372 ebpf_rss_unload(&n->ebpf_rss); in virtio_net_unload_ebpf()
1376 struct iovec *iov, in virtio_net_handle_rss() argument
1400 s = iov_to_buf(iov, iov_cnt, offset, &cfg, size_get); in virtio_net_handle_rss()
1406 n->rss_data.hash_types = virtio_ldl_p(vdev, &cfg.hash_types); in virtio_net_handle_rss()
1407 n->rss_data.indirections_len = in virtio_net_handle_rss()
1410 n->rss_data.indirections_len = 0; in virtio_net_handle_rss()
1412 if (n->rss_data.indirections_len >= VIRTIO_NET_RSS_MAX_TABLE_LEN) { in virtio_net_handle_rss()
1414 err_value = n->rss_data.indirections_len; in virtio_net_handle_rss()
1417 n->rss_data.indirections_len++; in virtio_net_handle_rss()
1418 if (!is_power_of_2(n->rss_data.indirections_len)) { in virtio_net_handle_rss()
1420 err_value = n->rss_data.indirections_len; in virtio_net_handle_rss()
1423 n->rss_data.default_queue = do_rss ? in virtio_net_handle_rss()
1425 if (n->rss_data.default_queue >= n->max_queue_pairs) { in virtio_net_handle_rss()
1427 err_value = n->rss_data.default_queue; in virtio_net_handle_rss()
1431 size_get = sizeof(uint16_t) * n->rss_data.indirections_len; in virtio_net_handle_rss()
1432 g_free(n->rss_data.indirections_table); in virtio_net_handle_rss()
1433 n->rss_data.indirections_table = g_malloc(size_get); in virtio_net_handle_rss()
1434 if (!n->rss_data.indirections_table) { in virtio_net_handle_rss()
1436 err_value = n->rss_data.indirections_len; in virtio_net_handle_rss()
1439 s = iov_to_buf(iov, iov_cnt, offset, in virtio_net_handle_rss()
1440 n->rss_data.indirections_table, size_get); in virtio_net_handle_rss()
1446 for (i = 0; i < n->rss_data.indirections_len; ++i) { in virtio_net_handle_rss()
1447 uint16_t val = n->rss_data.indirections_table[i]; in virtio_net_handle_rss()
1448 n->rss_data.indirections_table[i] = virtio_lduw_p(vdev, &val); in virtio_net_handle_rss()
1452 s = iov_to_buf(iov, iov_cnt, offset, &temp, size_get); in virtio_net_handle_rss()
1458 queue_pairs = do_rss ? virtio_lduw_p(vdev, &temp.us) : n->curr_queue_pairs; in virtio_net_handle_rss()
1459 if (queue_pairs == 0 || queue_pairs > n->max_queue_pairs) { in virtio_net_handle_rss()
1469 if (!temp.b && n->rss_data.hash_types) { in virtio_net_handle_rss()
1474 if (!temp.b && !n->rss_data.hash_types) { in virtio_net_handle_rss()
1480 s = iov_to_buf(iov, iov_cnt, offset, n->rss_data.key, size_get); in virtio_net_handle_rss()
1486 n->rss_data.enabled = true; in virtio_net_handle_rss()
1496 struct iovec *iov, unsigned int iov_cnt) in virtio_net_handle_mq() argument
1500 NetClientState *nc = qemu_get_queue(n->nic); in virtio_net_handle_mq()
1504 queue_pairs = virtio_net_handle_rss(n, iov, iov_cnt, false); in virtio_net_handle_mq()
1508 queue_pairs = virtio_net_handle_rss(n, iov, iov_cnt, true); in virtio_net_handle_mq()
1515 s = iov_to_buf(iov, iov_cnt, 0, &mq, sizeof(mq)); in virtio_net_handle_mq()
1527 queue_pairs > n->max_queue_pairs || in virtio_net_handle_mq()
1528 !n->multiqueue) { in virtio_net_handle_mq()
1532 n->curr_queue_pairs = queue_pairs; in virtio_net_handle_mq()
1533 if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { in virtio_net_handle_mq()
1542 virtio_net_set_status(vdev, vdev->status); in virtio_net_handle_mq()
1557 struct iovec *iov, *iov2; in virtio_net_handle_ctrl_iov() local
1561 virtio_error(vdev, "virtio-net ctrl missing headers"); in virtio_net_handle_ctrl_iov()
1565 iov2 = iov = g_memdup2(out_sg, sizeof(struct iovec) * out_num); in virtio_net_handle_ctrl_iov()
1566 s = iov_to_buf(iov, out_num, 0, &ctrl, sizeof(ctrl)); in virtio_net_handle_ctrl_iov()
1567 iov_discard_front(&iov, &out_num, sizeof(ctrl)); in virtio_net_handle_ctrl_iov()
1571 status = virtio_net_handle_rx_mode(n, ctrl.cmd, iov, out_num); in virtio_net_handle_ctrl_iov()
1573 status = virtio_net_handle_mac(n, ctrl.cmd, iov, out_num); in virtio_net_handle_ctrl_iov()
1575 status = virtio_net_handle_vlan_table(n, ctrl.cmd, iov, out_num); in virtio_net_handle_ctrl_iov()
1577 status = virtio_net_handle_announce(n, ctrl.cmd, iov, out_num); in virtio_net_handle_ctrl_iov()
1579 status = virtio_net_handle_mq(n, ctrl.cmd, iov, out_num); in virtio_net_handle_ctrl_iov()
1581 status = virtio_net_handle_offloads(n, ctrl.cmd, iov, out_num); in virtio_net_handle_ctrl_iov()
1602 written = virtio_net_handle_ctrl_iov(vdev, elem->in_sg, elem->in_num, in virtio_net_handle_ctrl()
1603 elem->out_sg, elem->out_num); in virtio_net_handle_ctrl()
1623 qemu_flush_queued_packets(qemu_get_subqueue(n->nic, queue_index)); in virtio_net_handle_rx()
1632 if (!vdev->vm_running) { in virtio_net_can_receive()
1636 if (nc->queue_index >= n->curr_queue_pairs) { in virtio_net_can_receive()
1640 if (!virtio_queue_ready(q->rx_vq) || in virtio_net_can_receive()
1641 !(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) { in virtio_net_can_receive()
1652 VirtIONet *n = q->n; in virtio_net_has_buffers()
1654 while (virtio_queue_empty(q->rx_vq) || n->mergeable_rx_bufs) { in virtio_net_has_buffers()
1655 opaque = virtqueue_get_avail_bytes(q->rx_vq, &in_bytes, NULL, in virtio_net_has_buffers()
1662 if (virtio_queue_enable_notification_and_check(q->rx_vq, opaque)) { in virtio_net_has_buffers()
1670 virtio_queue_set_notification(q->rx_vq, 0); in virtio_net_has_buffers()
1677 virtio_tswap16s(vdev, &hdr->hdr_len); in virtio_net_hdr_swap()
1678 virtio_tswap16s(vdev, &hdr->gso_size); in virtio_net_hdr_swap()
1679 virtio_tswap16s(vdev, &hdr->csum_start); in virtio_net_hdr_swap()
1680 virtio_tswap16s(vdev, &hdr->csum_offset); in virtio_net_hdr_swap()
1693 * N.B. if we introduce a zero-copy API, this operation is no longer free so
1705 buf_size -= *buf_offset; in work_around_broken_dhclient()
1707 if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */ in work_around_broken_dhclient()
1714 hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM; in work_around_broken_dhclient()
1724 size_t hdr_len = n->guest_hdr_len; in receive_header()
1728 *buf_offset = n->host_hdr_len; in receive_header()
1731 if (n->needs_vnet_hdr_swap) { in receive_header()
1745 if (n->promisc) in receive_filter()
1748 ptr += n->host_hdr_len; in receive_filter()
1752 if (!(n->vlans[vid >> 5] & (1U << (vid & 0x1f)))) in receive_filter()
1758 return !n->nobcast; in receive_filter()
1759 } else if (n->nomulti) { in receive_filter()
1761 } else if (n->allmulti || n->mac_table.multi_overflow) { in receive_filter()
1765 for (i = n->mac_table.first_multi; i < n->mac_table.in_use; i++) { in receive_filter()
1766 if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) { in receive_filter()
1771 if (n->nouni) { in receive_filter()
1773 } else if (n->alluni || n->mac_table.uni_overflow) { in receive_filter()
1775 } else if (!memcmp(ptr, n->mac, ETH_ALEN)) { in receive_filter()
1779 for (i = 0; i < n->mac_table.first_multi; i++) { in receive_filter()
1780 if (!memcmp(ptr, &n->mac_table.macs[i * ETH_ALEN], ETH_ALEN)) { in receive_filter()
1854 unsigned int index = nc->queue_index, new_index = index; in virtio_net_process_rss()
1855 struct NetRxPkt *pkt = n->rx_pkt; in virtio_net_process_rss()
1871 struct iovec iov = { in virtio_net_process_rss() local
1876 net_rx_pkt_set_protocols(pkt, &iov, 1, n->host_hdr_len); in virtio_net_process_rss()
1879 n->rss_data.hash_types); in virtio_net_process_rss()
1881 if (n->rss_data.populate_hash) { in virtio_net_process_rss()
1882 hdr->hash_value = VIRTIO_NET_HASH_REPORT_NONE; in virtio_net_process_rss()
1883 hdr->hash_report = 0; in virtio_net_process_rss()
1885 return n->rss_data.redirect ? n->rss_data.default_queue : -1; in virtio_net_process_rss()
1888 hash = net_rx_pkt_calc_rss_hash(pkt, net_hash_type, n->rss_data.key); in virtio_net_process_rss()
1890 if (n->rss_data.populate_hash) { in virtio_net_process_rss()
1891 hdr->hash_value = hash; in virtio_net_process_rss()
1892 hdr->hash_report = reports[net_hash_type]; in virtio_net_process_rss()
1895 if (n->rss_data.redirect) { in virtio_net_process_rss()
1896 new_index = hash & (n->rss_data.indirections_len - 1); in virtio_net_process_rss()
1897 new_index = n->rss_data.indirections_table[new_index]; in virtio_net_process_rss()
1900 return (index == new_index) ? -1 : new_index; in virtio_net_process_rss()
1926 if (n->rss_data.enabled && n->rss_data.enabled_software_rss) { in virtio_net_receive_rcu()
1929 nc = qemu_get_subqueue(n->nic, index % n->curr_queue_pairs); in virtio_net_receive_rcu()
1934 return -1; in virtio_net_receive_rcu()
1939 /* hdr_len refers to the header we supply to the guest */ in virtio_net_receive_rcu()
1940 if (!virtio_net_has_buffers(q, size + n->guest_hdr_len - n->host_hdr_len)) { in virtio_net_receive_rcu()
1957 virtio_error(vdev, "virtio-net unexpected long buffer chain"); in virtio_net_receive_rcu()
1962 elem = virtqueue_pop(q->rx_vq, sizeof(VirtQueueElement)); in virtio_net_receive_rcu()
1965 virtio_error(vdev, "virtio-net unexpected empty queue: " in virtio_net_receive_rcu()
1969 i, n->mergeable_rx_bufs, offset, size, in virtio_net_receive_rcu()
1970 n->guest_hdr_len, n->host_hdr_len, in virtio_net_receive_rcu()
1971 vdev->guest_features); in virtio_net_receive_rcu()
1973 err = -1; in virtio_net_receive_rcu()
1977 if (elem->in_num < 1) { in virtio_net_receive_rcu()
1979 "virtio-net receive queue contains no in buffers"); in virtio_net_receive_rcu()
1980 virtqueue_detach_element(q->rx_vq, elem, 0); in virtio_net_receive_rcu()
1982 err = -1; in virtio_net_receive_rcu()
1986 sg = elem->in_sg; in virtio_net_receive_rcu()
1989 if (n->mergeable_rx_bufs) { in virtio_net_receive_rcu()
1991 sg, elem->in_num, in virtio_net_receive_rcu()
1997 guest_offset = n->has_vnet_hdr ? in virtio_net_receive_rcu()
2000 n->guest_hdr_len; in virtio_net_receive_rcu()
2002 iov_from_buf(sg, elem->in_num, 0, &hdr, guest_offset); in virtio_net_receive_rcu()
2009 len = iov_from_buf(sg, elem->in_num, guest_offset, in virtio_net_receive_rcu()
2010 buf + offset, size - offset); in virtio_net_receive_rcu()
2016 if (!n->mergeable_rx_bufs && offset < size) { in virtio_net_receive_rcu()
2017 virtqueue_unpop(q->rx_vq, elem, total); in virtio_net_receive_rcu()
2038 virtqueue_fill(q->rx_vq, elems[j], lens[j], j); in virtio_net_receive_rcu()
2042 virtqueue_flush(q->rx_vq, i); in virtio_net_receive_rcu()
2043 virtio_notify(vdev, q->rx_vq); in virtio_net_receive_rcu()
2049 virtqueue_detach_element(q->rx_vq, elems[j], lens[j]); in virtio_net_receive_rcu()
2066 * is a potentially unaligned network-byte-order 16 bit unsigned integer
2067 * pointed to by unit->ip_len.
2071 return lduw_be_p(unit->ip_plen); in read_unit_ip_len()
2076 stw_be_p(unit->ip_plen, l); in write_unit_ip_len()
2086 ip = (struct ip_header *)(buf + chain->n->guest_hdr_len in virtio_net_rsc_extract_unit4()
2088 unit->ip = (void *)ip; in virtio_net_rsc_extract_unit4()
2089 ip_hdrlen = (ip->ip_ver_len & 0xF) << 2; in virtio_net_rsc_extract_unit4()
2090 unit->ip_plen = &ip->ip_len; in virtio_net_rsc_extract_unit4()
2091 unit->tcp = (struct tcp_header *)(((uint8_t *)unit->ip) + ip_hdrlen); in virtio_net_rsc_extract_unit4()
2092 unit->tcp_hdrlen = (htons(unit->tcp->th_offset_flags) & 0xF000) >> 10; in virtio_net_rsc_extract_unit4()
2093 unit->payload = read_unit_ip_len(unit) - ip_hdrlen - unit->tcp_hdrlen; in virtio_net_rsc_extract_unit4()
2102 ip6 = (struct ip6_header *)(buf + chain->n->guest_hdr_len in virtio_net_rsc_extract_unit6()
2104 unit->ip = ip6; in virtio_net_rsc_extract_unit6()
2105 unit->ip_plen = &(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); in virtio_net_rsc_extract_unit6()
2106 unit->tcp = (struct tcp_header *)(((uint8_t *)unit->ip) in virtio_net_rsc_extract_unit6()
2108 unit->tcp_hdrlen = (htons(unit->tcp->th_offset_flags) & 0xF000) >> 10; in virtio_net_rsc_extract_unit6()
2112 unit->payload = read_unit_ip_len(unit) - unit->tcp_hdrlen; in virtio_net_rsc_extract_unit6()
2121 h = (struct virtio_net_hdr_v1 *)seg->buf; in virtio_net_rsc_drain_seg()
2122 h->flags = 0; in virtio_net_rsc_drain_seg()
2123 h->gso_type = VIRTIO_NET_HDR_GSO_NONE; in virtio_net_rsc_drain_seg()
2125 if (seg->is_coalesced) { in virtio_net_rsc_drain_seg()
2126 h->rsc.segments = seg->packets; in virtio_net_rsc_drain_seg()
2127 h->rsc.dup_acks = seg->dup_ack; in virtio_net_rsc_drain_seg()
2128 h->flags = VIRTIO_NET_HDR_F_RSC_INFO; in virtio_net_rsc_drain_seg()
2129 if (chain->proto == ETH_P_IP) { in virtio_net_rsc_drain_seg()
2130 h->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; in virtio_net_rsc_drain_seg()
2132 h->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; in virtio_net_rsc_drain_seg()
2136 ret = virtio_net_do_receive(seg->nc, seg->buf, seg->size); in virtio_net_rsc_drain_seg()
2137 QTAILQ_REMOVE(&chain->buffers, seg, next); in virtio_net_rsc_drain_seg()
2138 g_free(seg->buf); in virtio_net_rsc_drain_seg()
2149 QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, rn) { in virtio_net_rsc_purge()
2151 chain->stat.purge_failed++; in virtio_net_rsc_purge()
2156 chain->stat.timer++; in virtio_net_rsc_purge()
2157 if (!QTAILQ_EMPTY(&chain->buffers)) { in virtio_net_rsc_purge()
2158 timer_mod(chain->drain_timer, in virtio_net_rsc_purge()
2159 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + chain->n->rsc_timeout); in virtio_net_rsc_purge()
2168 QTAILQ_FOREACH_SAFE(chain, &n->rsc_chains, next, rn_chain) { in virtio_net_rsc_cleanup()
2169 QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, rn_seg) { in virtio_net_rsc_cleanup()
2170 QTAILQ_REMOVE(&chain->buffers, seg, next); in virtio_net_rsc_cleanup()
2171 g_free(seg->buf); in virtio_net_rsc_cleanup()
2175 timer_free(chain->drain_timer); in virtio_net_rsc_cleanup()
2176 QTAILQ_REMOVE(&n->rsc_chains, chain, next); in virtio_net_rsc_cleanup()
2188 hdr_len = chain->n->guest_hdr_len; in virtio_net_rsc_cache_buf()
2190 seg->buf = g_malloc(hdr_len + sizeof(struct eth_header) in virtio_net_rsc_cache_buf()
2192 memcpy(seg->buf, buf, size); in virtio_net_rsc_cache_buf()
2193 seg->size = size; in virtio_net_rsc_cache_buf()
2194 seg->packets = 1; in virtio_net_rsc_cache_buf()
2195 seg->dup_ack = 0; in virtio_net_rsc_cache_buf()
2196 seg->is_coalesced = 0; in virtio_net_rsc_cache_buf()
2197 seg->nc = nc; in virtio_net_rsc_cache_buf()
2199 QTAILQ_INSERT_TAIL(&chain->buffers, seg, next); in virtio_net_rsc_cache_buf()
2200 chain->stat.cache++; in virtio_net_rsc_cache_buf()
2202 switch (chain->proto) { in virtio_net_rsc_cache_buf()
2204 virtio_net_rsc_extract_unit4(chain, seg->buf, &seg->unit); in virtio_net_rsc_cache_buf()
2207 virtio_net_rsc_extract_unit6(chain, seg->buf, &seg->unit); in virtio_net_rsc_cache_buf()
2223 nack = htonl(n_tcp->th_ack); in virtio_net_rsc_handle_ack()
2224 nwin = htons(n_tcp->th_win); in virtio_net_rsc_handle_ack()
2225 oack = htonl(o_tcp->th_ack); in virtio_net_rsc_handle_ack()
2226 owin = htons(o_tcp->th_win); in virtio_net_rsc_handle_ack()
2228 if ((nack - oack) >= VIRTIO_NET_MAX_TCP_PAYLOAD) { in virtio_net_rsc_handle_ack()
2229 chain->stat.ack_out_of_win++; in virtio_net_rsc_handle_ack()
2235 chain->stat.dup_ack++; in virtio_net_rsc_handle_ack()
2239 o_tcp->th_win = n_tcp->th_win; in virtio_net_rsc_handle_ack()
2240 chain->stat.win_update++; in virtio_net_rsc_handle_ack()
2245 chain->stat.pure_ack++; in virtio_net_rsc_handle_ack()
2260 o_unit = &seg->unit; in virtio_net_rsc_coalesce_data()
2262 nseq = htonl(n_unit->tcp->th_seq); in virtio_net_rsc_coalesce_data()
2263 oseq = htonl(o_unit->tcp->th_seq); in virtio_net_rsc_coalesce_data()
2266 if ((nseq - oseq) > VIRTIO_NET_MAX_TCP_PAYLOAD) { in virtio_net_rsc_coalesce_data()
2267 chain->stat.data_out_of_win++; in virtio_net_rsc_coalesce_data()
2271 data = ((uint8_t *)n_unit->tcp) + n_unit->tcp_hdrlen; in virtio_net_rsc_coalesce_data()
2273 if ((o_unit->payload == 0) && n_unit->payload) { in virtio_net_rsc_coalesce_data()
2275 chain->stat.data_after_pure_ack++; in virtio_net_rsc_coalesce_data()
2279 n_unit->tcp, o_unit->tcp); in virtio_net_rsc_coalesce_data()
2281 } else if ((nseq - oseq) != o_unit->payload) { in virtio_net_rsc_coalesce_data()
2283 chain->stat.data_out_of_order++; in virtio_net_rsc_coalesce_data()
2287 if ((o_ip_len + n_unit->payload) > chain->max_payload) { in virtio_net_rsc_coalesce_data()
2288 chain->stat.over_size++; in virtio_net_rsc_coalesce_data()
2294 o_unit->payload += n_unit->payload; /* update new data len */ in virtio_net_rsc_coalesce_data()
2297 write_unit_ip_len(o_unit, o_ip_len + n_unit->payload); in virtio_net_rsc_coalesce_data()
2302 o_unit->tcp->th_offset_flags = n_unit->tcp->th_offset_flags; in virtio_net_rsc_coalesce_data()
2304 o_unit->tcp->th_ack = n_unit->tcp->th_ack; in virtio_net_rsc_coalesce_data()
2305 o_unit->tcp->th_win = n_unit->tcp->th_win; in virtio_net_rsc_coalesce_data()
2307 memmove(seg->buf + seg->size, data, n_unit->payload); in virtio_net_rsc_coalesce_data()
2308 seg->size += n_unit->payload; in virtio_net_rsc_coalesce_data()
2309 seg->packets++; in virtio_net_rsc_coalesce_data()
2310 chain->stat.coalesced++; in virtio_net_rsc_coalesce_data()
2322 ip1 = (struct ip_header *)(unit->ip); in virtio_net_rsc_coalesce4()
2323 ip2 = (struct ip_header *)(seg->unit.ip); in virtio_net_rsc_coalesce4()
2324 if ((ip1->ip_src ^ ip2->ip_src) || (ip1->ip_dst ^ ip2->ip_dst) in virtio_net_rsc_coalesce4()
2325 || (unit->tcp->th_sport ^ seg->unit.tcp->th_sport) in virtio_net_rsc_coalesce4()
2326 || (unit->tcp->th_dport ^ seg->unit.tcp->th_dport)) { in virtio_net_rsc_coalesce4()
2327 chain->stat.no_match++; in virtio_net_rsc_coalesce4()
2341 ip1 = (struct ip6_header *)(unit->ip); in virtio_net_rsc_coalesce6()
2342 ip2 = (struct ip6_header *)(seg->unit.ip); in virtio_net_rsc_coalesce6()
2343 if (memcmp(&ip1->ip6_src, &ip2->ip6_src, sizeof(struct in6_address)) in virtio_net_rsc_coalesce6()
2344 || memcmp(&ip1->ip6_dst, &ip2->ip6_dst, sizeof(struct in6_address)) in virtio_net_rsc_coalesce6()
2345 || (unit->tcp->th_sport ^ seg->unit.tcp->th_sport) in virtio_net_rsc_coalesce6()
2346 || (unit->tcp->th_dport ^ seg->unit.tcp->th_dport)) { in virtio_net_rsc_coalesce6()
2347 chain->stat.no_match++; in virtio_net_rsc_coalesce6()
2362 tcp_flag = htons(tcp->th_offset_flags); in virtio_net_rsc_tcp_ctrl_check()
2366 chain->stat.tcp_syn++; in virtio_net_rsc_tcp_ctrl_check()
2371 chain->stat.tcp_ctrl_drain++; in virtio_net_rsc_tcp_ctrl_check()
2376 chain->stat.tcp_all_opt++; in virtio_net_rsc_tcp_ctrl_check()
2391 if (QTAILQ_EMPTY(&chain->buffers)) { in virtio_net_rsc_do_coalesce()
2392 chain->stat.empty_cache++; in virtio_net_rsc_do_coalesce()
2394 timer_mod(chain->drain_timer, in virtio_net_rsc_do_coalesce()
2395 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + chain->n->rsc_timeout); in virtio_net_rsc_do_coalesce()
2399 QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, nseg) { in virtio_net_rsc_do_coalesce()
2400 if (chain->proto == ETH_P_IP) { in virtio_net_rsc_do_coalesce()
2409 chain->stat.final_failed++; in virtio_net_rsc_do_coalesce()
2419 seg->is_coalesced = 1; in virtio_net_rsc_do_coalesce()
2424 chain->stat.no_match_cache++; in virtio_net_rsc_do_coalesce()
2440 QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, nseg) { in virtio_net_rsc_drain_flow()
2441 ppair2 = *(uint32_t *)(seg->buf + tcp_port); in virtio_net_rsc_drain_flow()
2442 if (memcmp(buf + ip_start, seg->buf + ip_start, ip_size) in virtio_net_rsc_drain_flow()
2447 chain->stat.drain_failed++; in virtio_net_rsc_drain_flow()
2463 if (((ip->ip_ver_len & 0xF0) >> 4) != IP_HEADER_VERSION_4) { in virtio_net_rsc_sanity_check4()
2464 chain->stat.ip_option++; in virtio_net_rsc_sanity_check4()
2469 if ((ip->ip_ver_len & 0xF) != VIRTIO_NET_IP4_HEADER_LENGTH) { in virtio_net_rsc_sanity_check4()
2470 chain->stat.ip_option++; in virtio_net_rsc_sanity_check4()
2474 if (ip->ip_p != IPPROTO_TCP) { in virtio_net_rsc_sanity_check4()
2475 chain->stat.bypass_not_tcp++; in virtio_net_rsc_sanity_check4()
2480 if (!(htons(ip->ip_off) & IP_DF)) { in virtio_net_rsc_sanity_check4()
2481 chain->stat.ip_frag++; in virtio_net_rsc_sanity_check4()
2486 if (IPTOS_ECN(ip->ip_tos)) { in virtio_net_rsc_sanity_check4()
2487 chain->stat.ip_ecn++; in virtio_net_rsc_sanity_check4()
2491 ip_len = htons(ip->ip_len); in virtio_net_rsc_sanity_check4()
2493 || ip_len > (size - chain->n->guest_hdr_len - in virtio_net_rsc_sanity_check4()
2495 chain->stat.ip_hacked++; in virtio_net_rsc_sanity_check4()
2510 hdr_len = ((VirtIONet *)(chain->n))->guest_hdr_len; in virtio_net_rsc_receive4()
2514 chain->stat.bypass_not_tcp++; in virtio_net_rsc_receive4()
2543 if (((ip6->ip6_ctlun.ip6_un1.ip6_un1_flow & 0xF0) >> 4) in virtio_net_rsc_sanity_check6()
2549 if (ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt != IPPROTO_TCP) { in virtio_net_rsc_sanity_check6()
2550 chain->stat.bypass_not_tcp++; in virtio_net_rsc_sanity_check6()
2554 ip_len = htons(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen); in virtio_net_rsc_sanity_check6()
2556 ip_len > (size - chain->n->guest_hdr_len - sizeof(struct eth_header) in virtio_net_rsc_sanity_check6()
2557 - sizeof(struct ip6_header))) { in virtio_net_rsc_sanity_check6()
2558 chain->stat.ip_hacked++; in virtio_net_rsc_sanity_check6()
2563 if (IP6_ECN(ip6->ip6_ctlun.ip6_un3.ip6_un3_ecn)) { in virtio_net_rsc_sanity_check6()
2564 chain->stat.ip_ecn++; in virtio_net_rsc_sanity_check6()
2580 hdr_len = ((VirtIONet *)(chain->n))->guest_hdr_len; in virtio_net_rsc_receive6()
2617 QTAILQ_FOREACH(chain, &n->rsc_chains, next) { in virtio_net_rsc_lookup_chain()
2618 if (chain->proto == proto) { in virtio_net_rsc_lookup_chain()
2624 chain->n = n; in virtio_net_rsc_lookup_chain()
2625 chain->proto = proto; in virtio_net_rsc_lookup_chain()
2627 chain->max_payload = VIRTIO_NET_MAX_IP4_PAYLOAD; in virtio_net_rsc_lookup_chain()
2628 chain->gso_type = VIRTIO_NET_HDR_GSO_TCPV4; in virtio_net_rsc_lookup_chain()
2630 chain->max_payload = VIRTIO_NET_MAX_IP6_PAYLOAD; in virtio_net_rsc_lookup_chain()
2631 chain->gso_type = VIRTIO_NET_HDR_GSO_TCPV6; in virtio_net_rsc_lookup_chain()
2633 chain->drain_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, in virtio_net_rsc_lookup_chain()
2635 memset(&chain->stat, 0, sizeof(chain->stat)); in virtio_net_rsc_lookup_chain()
2637 QTAILQ_INIT(&chain->buffers); in virtio_net_rsc_lookup_chain()
2638 QTAILQ_INSERT_TAIL(&n->rsc_chains, chain, next); in virtio_net_rsc_lookup_chain()
2653 if (size < (n->host_hdr_len + sizeof(struct eth_header))) { in virtio_net_rsc_receive()
2657 eth = (struct eth_header *)(buf + n->guest_hdr_len); in virtio_net_rsc_receive()
2658 proto = htons(eth->h_proto); in virtio_net_rsc_receive()
2662 chain->stat.received++; in virtio_net_rsc_receive()
2663 if (proto == (uint16_t)ETH_P_IP && n->rsc4_enabled) { in virtio_net_rsc_receive()
2665 } else if (proto == (uint16_t)ETH_P_IPV6 && n->rsc6_enabled) { in virtio_net_rsc_receive()
2676 if ((n->rsc4_enabled || n->rsc6_enabled)) { in virtio_net_receive()
2692 virtqueue_push(q->tx_vq, q->async_tx.elem, 0); in virtio_net_tx_complete()
2693 virtio_notify(vdev, q->tx_vq); in virtio_net_tx_complete()
2695 g_free(q->async_tx.elem); in virtio_net_tx_complete()
2696 q->async_tx.elem = NULL; in virtio_net_tx_complete()
2698 virtio_queue_set_notification(q->tx_vq, 1); in virtio_net_tx_complete()
2700 if (ret >= n->tx_burst) { in virtio_net_tx_complete()
2704 * remainining part, so re-schedule in virtio_net_tx_complete()
2706 virtio_queue_set_notification(q->tx_vq, 0); in virtio_net_tx_complete()
2707 if (q->tx_bh) { in virtio_net_tx_complete()
2708 replay_bh_schedule_event(q->tx_bh); in virtio_net_tx_complete()
2710 timer_mod(q->tx_timer, in virtio_net_tx_complete()
2711 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout); in virtio_net_tx_complete()
2713 q->tx_waiting = 1; in virtio_net_tx_complete()
2720 VirtIONet *n = q->n; in virtio_net_flush_tx()
2724 int queue_index = vq2q(virtio_get_queue_index(q->tx_vq)); in virtio_net_flush_tx()
2725 if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) { in virtio_net_flush_tx()
2729 if (q->async_tx.elem) { in virtio_net_flush_tx()
2730 virtio_queue_set_notification(q->tx_vq, 0); in virtio_net_flush_tx()
2740 elem = virtqueue_pop(q->tx_vq, sizeof(VirtQueueElement)); in virtio_net_flush_tx()
2745 out_num = elem->out_num; in virtio_net_flush_tx()
2746 out_sg = elem->out_sg; in virtio_net_flush_tx()
2748 virtio_error(vdev, "virtio-net header not in first element"); in virtio_net_flush_tx()
2752 if (n->needs_vnet_hdr_swap) { in virtio_net_flush_tx()
2755 virtio_error(vdev, "virtio-net header incorrect"); in virtio_net_flush_tx()
2761 out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1, out_sg, out_num, in virtio_net_flush_tx()
2762 sizeof(vhdr), -1); in virtio_net_flush_tx()
2774 assert(n->host_hdr_len <= n->guest_hdr_len); in virtio_net_flush_tx()
2775 if (n->host_hdr_len != n->guest_hdr_len) { in virtio_net_flush_tx()
2776 if (iov_size(out_sg, out_num) < n->guest_hdr_len) { in virtio_net_flush_tx()
2777 virtio_error(vdev, "virtio-net header is invalid"); in virtio_net_flush_tx()
2782 0, n->host_hdr_len); in virtio_net_flush_tx()
2783 sg_num += iov_copy(sg + sg_num, ARRAY_SIZE(sg) - sg_num, in virtio_net_flush_tx()
2785 n->guest_hdr_len, -1); in virtio_net_flush_tx()
2790 virtio_error(vdev, "virtio-net nothing to send"); in virtio_net_flush_tx()
2795 ret = qemu_sendv_packet_async(qemu_get_subqueue(n->nic, queue_index), in virtio_net_flush_tx()
2798 virtio_queue_set_notification(q->tx_vq, 0); in virtio_net_flush_tx()
2799 q->async_tx.elem = elem; in virtio_net_flush_tx()
2800 return -EBUSY; in virtio_net_flush_tx()
2804 virtqueue_push(q->tx_vq, elem, 0); in virtio_net_flush_tx()
2805 virtio_notify(vdev, q->tx_vq); in virtio_net_flush_tx()
2808 if (++num_packets >= n->tx_burst) { in virtio_net_flush_tx()
2815 virtqueue_detach_element(q->tx_vq, elem, 0); in virtio_net_flush_tx()
2817 return -EINVAL; in virtio_net_flush_tx()
2825 VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))]; in virtio_net_handle_tx_timer()
2827 if (unlikely((n->status & VIRTIO_NET_S_LINK_UP) == 0)) { in virtio_net_handle_tx_timer()
2833 if (!vdev->vm_running) { in virtio_net_handle_tx_timer()
2834 q->tx_waiting = 1; in virtio_net_handle_tx_timer()
2838 if (q->tx_waiting) { in virtio_net_handle_tx_timer()
2840 timer_del(q->tx_timer); in virtio_net_handle_tx_timer()
2843 /* re-arm timer to flush it (and more) on next tick */ in virtio_net_handle_tx_timer()
2844 timer_mod(q->tx_timer, in virtio_net_handle_tx_timer()
2845 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout); in virtio_net_handle_tx_timer()
2846 q->tx_waiting = 1; in virtio_net_handle_tx_timer()
2854 VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))]; in virtio_net_handle_tx_bh()
2856 if (unlikely(n->vhost_started)) { in virtio_net_handle_tx_bh()
2860 if (unlikely((n->status & VIRTIO_NET_S_LINK_UP) == 0)) { in virtio_net_handle_tx_bh()
2865 if (unlikely(q->tx_waiting)) { in virtio_net_handle_tx_bh()
2868 q->tx_waiting = 1; in virtio_net_handle_tx_bh()
2870 if (!vdev->vm_running) { in virtio_net_handle_tx_bh()
2874 replay_bh_schedule_event(q->tx_bh); in virtio_net_handle_tx_bh()
2880 VirtIONet *n = q->n; in virtio_net_tx_timer()
2885 if (!vdev->vm_running) { in virtio_net_tx_timer()
2887 assert(q->tx_waiting); in virtio_net_tx_timer()
2891 q->tx_waiting = 0; in virtio_net_tx_timer()
2894 if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) { in virtio_net_tx_timer()
2899 if (ret == -EBUSY || ret == -EINVAL) { in virtio_net_tx_timer()
2906 if (ret >= n->tx_burst) { in virtio_net_tx_timer()
2907 q->tx_waiting = 1; in virtio_net_tx_timer()
2908 timer_mod(q->tx_timer, in virtio_net_tx_timer()
2909 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout); in virtio_net_tx_timer()
2913 * If less than a full burst, re-enable notification and flush in virtio_net_tx_timer()
2917 virtio_queue_set_notification(q->tx_vq, 1); in virtio_net_tx_timer()
2920 virtio_queue_set_notification(q->tx_vq, 0); in virtio_net_tx_timer()
2921 q->tx_waiting = 1; in virtio_net_tx_timer()
2922 timer_mod(q->tx_timer, in virtio_net_tx_timer()
2923 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout); in virtio_net_tx_timer()
2930 VirtIONet *n = q->n; in virtio_net_tx_bh()
2935 if (!vdev->vm_running) { in virtio_net_tx_bh()
2937 assert(q->tx_waiting); in virtio_net_tx_bh()
2941 q->tx_waiting = 0; in virtio_net_tx_bh()
2944 if (unlikely(!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))) { in virtio_net_tx_bh()
2949 if (ret == -EBUSY || ret == -EINVAL) { in virtio_net_tx_bh()
2950 return; /* Notification re-enable handled by tx_complete or device in virtio_net_tx_bh()
2956 if (ret >= n->tx_burst) { in virtio_net_tx_bh()
2957 replay_bh_schedule_event(q->tx_bh); in virtio_net_tx_bh()
2958 q->tx_waiting = 1; in virtio_net_tx_bh()
2962 /* If less than a full burst, re-enable notification and flush in virtio_net_tx_bh()
2965 virtio_queue_set_notification(q->tx_vq, 1); in virtio_net_tx_bh()
2967 if (ret == -EINVAL) { in virtio_net_tx_bh()
2970 virtio_queue_set_notification(q->tx_vq, 0); in virtio_net_tx_bh()
2971 replay_bh_schedule_event(q->tx_bh); in virtio_net_tx_bh()
2972 q->tx_waiting = 1; in virtio_net_tx_bh()
2980 n->vqs[index].rx_vq = virtio_add_queue(vdev, n->net_conf.rx_queue_size, in virtio_net_add_queue()
2983 if (n->net_conf.tx && !strcmp(n->net_conf.tx, "timer")) { in virtio_net_add_queue()
2984 n->vqs[index].tx_vq = in virtio_net_add_queue()
2985 virtio_add_queue(vdev, n->net_conf.tx_queue_size, in virtio_net_add_queue()
2987 n->vqs[index].tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, in virtio_net_add_queue()
2989 &n->vqs[index]); in virtio_net_add_queue()
2991 n->vqs[index].tx_vq = in virtio_net_add_queue()
2992 virtio_add_queue(vdev, n->net_conf.tx_queue_size, in virtio_net_add_queue()
2994 n->vqs[index].tx_bh = qemu_bh_new_guarded(virtio_net_tx_bh, &n->vqs[index], in virtio_net_add_queue()
2995 &DEVICE(vdev)->mem_reentrancy_guard); in virtio_net_add_queue()
2998 n->vqs[index].tx_waiting = 0; in virtio_net_add_queue()
2999 n->vqs[index].n = n; in virtio_net_add_queue()
3005 VirtIONetQueue *q = &n->vqs[index]; in virtio_net_del_queue()
3006 NetClientState *nc = qemu_get_subqueue(n->nic, index); in virtio_net_del_queue()
3011 if (q->tx_timer) { in virtio_net_del_queue()
3012 timer_free(q->tx_timer); in virtio_net_del_queue()
3013 q->tx_timer = NULL; in virtio_net_del_queue()
3015 qemu_bh_delete(q->tx_bh); in virtio_net_del_queue()
3016 q->tx_bh = NULL; in virtio_net_del_queue()
3018 q->tx_waiting = 0; in virtio_net_del_queue()
3041 virtio_del_queue(vdev, old_num_queues - 1); in virtio_net_change_num_queue_pairs()
3043 for (i = new_num_queues - 1; i < old_num_queues - 1; i += 2) { in virtio_net_change_num_queue_pairs()
3048 for (i = old_num_queues - 1; i < new_num_queues - 1; i += 2) { in virtio_net_change_num_queue_pairs()
3054 n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl); in virtio_net_change_num_queue_pairs()
3059 int max = multiqueue ? n->max_queue_pairs : 1; in virtio_net_set_multiqueue()
3061 n->multiqueue = multiqueue; in virtio_net_set_multiqueue()
3070 virtio_has_feature(vdev->guest_features, VIRTIO_NET_F_RSS) || in virtio_net_pre_load_queues()
3071 virtio_has_feature(vdev->guest_features, VIRTIO_NET_F_MQ)); in virtio_net_pre_load_queues()
3083 virtio_net_set_mrg_rx_bufs(n, n->mergeable_rx_bufs, in virtio_net_post_load_device()
3090 if (n->mac_table.in_use > MAC_TABLE_ENTRIES) { in virtio_net_post_load_device()
3091 n->mac_table.in_use = 0; in virtio_net_post_load_device()
3095 n->curr_guest_offloads = virtio_net_supported_guest_offloads(n); in virtio_net_post_load_device()
3104 n->saved_guest_offloads = n->curr_guest_offloads; in virtio_net_post_load_device()
3109 for (i = 0; i < n->mac_table.in_use; i++) { in virtio_net_post_load_device()
3110 if (n->mac_table.macs[i * ETH_ALEN] & 1) { in virtio_net_post_load_device()
3114 n->mac_table.first_multi = i; in virtio_net_post_load_device()
3117 * to link status bit in n->status */ in virtio_net_post_load_device()
3118 link_down = (n->status & VIRTIO_NET_S_LINK_UP) == 0; in virtio_net_post_load_device()
3119 for (i = 0; i < n->max_queue_pairs; i++) { in virtio_net_post_load_device()
3120 qemu_get_subqueue(n->nic, i)->link_down = link_down; in virtio_net_post_load_device()
3125 qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(), in virtio_net_post_load_device()
3128 if (n->announce_timer.round) { in virtio_net_post_load_device()
3129 timer_mod(n->announce_timer.tm, in virtio_net_post_load_device()
3130 qemu_clock_get_ms(n->announce_timer.type)); in virtio_net_post_load_device()
3132 qemu_announce_timer_del(&n->announce_timer, false); in virtio_net_post_load_device()
3148 n->curr_guest_offloads = n->saved_guest_offloads; in virtio_net_post_load_virtio()
3158 .name = "virtio-net-queue-tx_waiting",
3167 return VIRTIO_NET(opaque)->max_queue_pairs > 1; in max_queue_pairs_gt_1()
3178 return VIRTIO_NET(opaque)->mac_table.in_use <= MAC_TABLE_ENTRIES; in mac_table_fits()
3207 tmp->vqs_1 = tmp->parent->vqs + 1; in virtio_net_tx_waiting_pre_save()
3208 tmp->curr_queue_pairs_1 = tmp->parent->curr_queue_pairs - 1; in virtio_net_tx_waiting_pre_save()
3209 if (tmp->parent->curr_queue_pairs == 0) { in virtio_net_tx_waiting_pre_save()
3210 tmp->curr_queue_pairs_1 = 0; in virtio_net_tx_waiting_pre_save()
3223 if (tmp->parent->curr_queue_pairs > tmp->parent->max_queue_pairs) { in virtio_net_tx_waiting_pre_load()
3224 error_report("virtio-net: curr_queue_pairs %x > max_queue_pairs %x", in virtio_net_tx_waiting_pre_load()
3225 tmp->parent->curr_queue_pairs, tmp->parent->max_queue_pairs); in virtio_net_tx_waiting_pre_load()
3227 return -EINVAL; in virtio_net_tx_waiting_pre_load()
3234 .name = "virtio-net-tx_waiting",
3253 if (tmp->has_ufo && !peer_has_ufo(tmp->parent)) { in virtio_net_ufo_post_load()
3254 error_report("virtio-net: saved image requires TUN_F_UFO support"); in virtio_net_ufo_post_load()
3255 return -EINVAL; in virtio_net_ufo_post_load()
3265 tmp->has_ufo = tmp->parent->has_ufo; in virtio_net_ufo_pre_save()
3271 .name = "virtio-net-ufo",
3287 if (tmp->has_vnet_hdr && !peer_has_vnet_hdr(tmp->parent)) { in virtio_net_vnet_post_load()
3288 error_report("virtio-net: saved image requires vnet_hdr=on"); in virtio_net_vnet_post_load()
3289 return -EINVAL; in virtio_net_vnet_post_load()
3299 tmp->has_vnet_hdr = tmp->parent->has_vnet_hdr; in virtio_net_vnet_pre_save()
3305 .name = "virtio-net-vnet",
3316 return VIRTIO_NET(opaque)->rss_data.enabled; in virtio_net_rss_needed()
3320 .name = "virtio-net-device/rss",
3341 .name = "virtio-net-device",
3357 * - can happen if source has a larger MAC table.; post-load
3410 assert(n->vhost_started); in virtio_net_guest_notifier_pending()
3411 if (!n->multiqueue && idx == 2) { in virtio_net_guest_notifier_pending()
3421 nc = qemu_get_subqueue(n->nic, n->max_queue_pairs); in virtio_net_guest_notifier_pending()
3423 nc = qemu_get_subqueue(n->nic, vq2q(idx)); in virtio_net_guest_notifier_pending()
3426 * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 in virtio_net_guest_notifier_pending()
3432 return vhost_net_config_pending(get_vhost_net(nc->peer)); in virtio_net_guest_notifier_pending()
3434 return vhost_net_virtqueue_pending(get_vhost_net(nc->peer), idx); in virtio_net_guest_notifier_pending()
3442 assert(n->vhost_started); in virtio_net_guest_notifier_mask()
3443 if (!n->multiqueue && idx == 2) { in virtio_net_guest_notifier_mask()
3453 nc = qemu_get_subqueue(n->nic, n->max_queue_pairs); in virtio_net_guest_notifier_mask()
3455 nc = qemu_get_subqueue(n->nic, vq2q(idx)); in virtio_net_guest_notifier_mask()
3458 *Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1 in virtio_net_guest_notifier_mask()
3464 vhost_net_config_mask(get_vhost_net(nc->peer), vdev, mask); in virtio_net_guest_notifier_mask()
3467 vhost_net_virtqueue_mask(get_vhost_net(nc->peer), vdev, idx, mask); in virtio_net_guest_notifier_mask()
3474 n->config_size = virtio_get_config_size(&cfg_size_params, host_features); in virtio_net_set_config_size()
3485 g_free(n->netclient_name); in virtio_net_set_netclient_name()
3486 g_free(n->netclient_type); in virtio_net_set_netclient_name()
3487 n->netclient_name = g_strdup(name); in virtio_net_set_netclient_name()
3488 n->netclient_type = g_strdup(type); in virtio_net_set_netclient_name()
3500 pci_dev->partially_hotplugged = true; in failover_unplug_primary()
3520 if (!pdev->partially_hotplugged) { in failover_replug_primary()
3523 primary_bus = dev->parent_bus; in failover_replug_primary()
3529 qatomic_set(&n->failover_primary_hidden, false); in failover_replug_primary()
3538 pdev->partially_hotplugged = false; in failover_replug_primary()
3555 should_be_hidden = qatomic_read(&n->failover_primary_hidden); in virtio_net_handle_migration_primary()
3557 if (e->type == MIG_EVENT_PRECOPY_SETUP && !should_be_hidden) { in virtio_net_handle_migration_primary()
3560 qapi_event_send_unplug_primary(dev->id); in virtio_net_handle_migration_primary()
3561 qatomic_set(&n->failover_primary_hidden, true); in virtio_net_handle_migration_primary()
3565 } else if (e->type == MIG_EVENT_PRECOPY_FAILED) { in virtio_net_handle_migration_primary()
3605 if (g_strcmp0(standby_id, n->netclient_name) != 0) { in failover_hide_primary_device()
3611 * Check there is only one primary for a virtio-net device but in failover_hide_primary_device()
3615 if (n->primary_opts) { in failover_hide_primary_device()
3618 old = qdict_get_str(n->primary_opts, "id"); in failover_hide_primary_device()
3622 "'%s': '%s' and '%s'", n->netclient_name, old, new); in failover_hide_primary_device()
3626 n->primary_opts = qdict_clone_shallow(device_opts); in failover_hide_primary_device()
3627 n->primary_opts_from_json = from_json; in failover_hide_primary_device()
3631 return qatomic_read(&n->failover_primary_hidden); in failover_hide_primary_device()
3641 if (n->net_conf.mtu) { in virtio_net_device_realize()
3642 n->host_features |= (1ULL << VIRTIO_NET_F_MTU); in virtio_net_device_realize()
3645 if (n->net_conf.duplex_str) { in virtio_net_device_realize()
3646 if (strncmp(n->net_conf.duplex_str, "half", 5) == 0) { in virtio_net_device_realize()
3647 n->net_conf.duplex = DUPLEX_HALF; in virtio_net_device_realize()
3648 } else if (strncmp(n->net_conf.duplex_str, "full", 5) == 0) { in virtio_net_device_realize()
3649 n->net_conf.duplex = DUPLEX_FULL; in virtio_net_device_realize()
3654 n->host_features |= (1ULL << VIRTIO_NET_F_SPEED_DUPLEX); in virtio_net_device_realize()
3656 n->net_conf.duplex = DUPLEX_UNKNOWN; in virtio_net_device_realize()
3659 if (n->net_conf.speed < SPEED_UNKNOWN) { in virtio_net_device_realize()
3663 if (n->net_conf.speed >= 0) { in virtio_net_device_realize()
3664 n->host_features |= (1ULL << VIRTIO_NET_F_SPEED_DUPLEX); in virtio_net_device_realize()
3667 if (n->failover) { in virtio_net_device_realize()
3668 n->primary_listener.hide_device = failover_hide_primary_device; in virtio_net_device_realize()
3669 qatomic_set(&n->failover_primary_hidden, true); in virtio_net_device_realize()
3670 device_listener_register(&n->primary_listener); in virtio_net_device_realize()
3671 migration_add_notifier(&n->migration_state, in virtio_net_device_realize()
3673 n->host_features |= (1ULL << VIRTIO_NET_F_STANDBY); in virtio_net_device_realize()
3676 virtio_net_set_config_size(n, n->host_features); in virtio_net_device_realize()
3677 virtio_init(vdev, VIRTIO_ID_NET, n->config_size); in virtio_net_device_realize()
3684 if (n->net_conf.rx_queue_size < VIRTIO_NET_RX_QUEUE_MIN_SIZE || in virtio_net_device_realize()
3685 n->net_conf.rx_queue_size > VIRTQUEUE_MAX_SIZE || in virtio_net_device_realize()
3686 !is_power_of_2(n->net_conf.rx_queue_size)) { in virtio_net_device_realize()
3689 n->net_conf.rx_queue_size, VIRTIO_NET_RX_QUEUE_MIN_SIZE, in virtio_net_device_realize()
3695 if (n->net_conf.tx_queue_size < VIRTIO_NET_TX_QUEUE_MIN_SIZE || in virtio_net_device_realize()
3696 n->net_conf.tx_queue_size > virtio_net_max_tx_queue_size(n) || in virtio_net_device_realize()
3697 !is_power_of_2(n->net_conf.tx_queue_size)) { in virtio_net_device_realize()
3700 n->net_conf.tx_queue_size, VIRTIO_NET_TX_QUEUE_MIN_SIZE, in virtio_net_device_realize()
3706 n->max_ncs = MAX(n->nic_conf.peers.queues, 1); in virtio_net_device_realize()
3712 if (n->nic_conf.peers.queues) { in virtio_net_device_realize()
3713 for (i = 0; i < n->max_ncs; i++) { in virtio_net_device_realize()
3714 if (n->nic_conf.peers.ncs[i]->is_datapath) { in virtio_net_device_realize()
3715 ++n->max_queue_pairs; in virtio_net_device_realize()
3719 n->max_queue_pairs = MAX(n->max_queue_pairs, 1); in virtio_net_device_realize()
3721 if (n->max_queue_pairs * 2 + 1 > VIRTIO_QUEUE_MAX) { in virtio_net_device_realize()
3724 n->max_queue_pairs, (VIRTIO_QUEUE_MAX - 1) / 2); in virtio_net_device_realize()
3728 n->vqs = g_new0(VirtIONetQueue, n->max_queue_pairs); in virtio_net_device_realize()
3729 n->curr_queue_pairs = 1; in virtio_net_device_realize()
3730 n->tx_timeout = n->net_conf.txtimer; in virtio_net_device_realize()
3732 if (n->net_conf.tx && strcmp(n->net_conf.tx, "timer") in virtio_net_device_realize()
3733 && strcmp(n->net_conf.tx, "bh")) { in virtio_net_device_realize()
3734 warn_report("virtio-net: " in virtio_net_device_realize()
3736 n->net_conf.tx); in virtio_net_device_realize()
3740 n->net_conf.tx_queue_size = MIN(virtio_net_max_tx_queue_size(n), in virtio_net_device_realize()
3741 n->net_conf.tx_queue_size); in virtio_net_device_realize()
3745 n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl); in virtio_net_device_realize()
3746 qemu_macaddr_default_if_unset(&n->nic_conf.macaddr); in virtio_net_device_realize()
3747 memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac)); in virtio_net_device_realize()
3748 n->status = VIRTIO_NET_S_LINK_UP; in virtio_net_device_realize()
3749 qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(), in virtio_net_device_realize()
3752 n->announce_timer.round = 0; in virtio_net_device_realize()
3754 if (n->netclient_type) { in virtio_net_device_realize()
3758 n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf, in virtio_net_device_realize()
3759 n->netclient_type, n->netclient_name, in virtio_net_device_realize()
3760 &dev->mem_reentrancy_guard, n); in virtio_net_device_realize()
3762 n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf, in virtio_net_device_realize()
3763 object_get_typename(OBJECT(dev)), dev->id, in virtio_net_device_realize()
3764 &dev->mem_reentrancy_guard, n); in virtio_net_device_realize()
3767 for (i = 0; i < n->max_queue_pairs; i++) { in virtio_net_device_realize()
3768 n->nic->ncs[i].do_not_pad = true; in virtio_net_device_realize()
3773 n->host_hdr_len = sizeof(struct virtio_net_hdr); in virtio_net_device_realize()
3775 n->host_hdr_len = 0; in virtio_net_device_realize()
3778 qemu_format_nic_info_str(qemu_get_queue(n->nic), n->nic_conf.macaddr.a); in virtio_net_device_realize()
3780 n->vqs[0].tx_waiting = 0; in virtio_net_device_realize()
3781 n->tx_burst = n->net_conf.txburst; in virtio_net_device_realize()
3783 n->promisc = 1; /* for compatibility */ in virtio_net_device_realize()
3785 n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN); in virtio_net_device_realize()
3787 n->vlans = g_malloc0(MAX_VLAN >> 3); in virtio_net_device_realize()
3789 nc = qemu_get_queue(n->nic); in virtio_net_device_realize()
3790 nc->rxfilter_notify_enabled = 1; in virtio_net_device_realize()
3792 if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { in virtio_net_device_realize()
3794 memcpy(&netcfg.mac, &n->nic_conf.macaddr, ETH_ALEN); in virtio_net_device_realize()
3795 vhost_net_set_config(get_vhost_net(nc->peer), in virtio_net_device_realize()
3798 QTAILQ_INIT(&n->rsc_chains); in virtio_net_device_realize()
3799 n->qdev = dev; in virtio_net_device_realize()
3801 net_rx_pkt_init(&n->rx_pkt); in virtio_net_device_realize()
3803 if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) { in virtio_net_device_realize()
3813 if (n->ebpf_rss_fds) { in virtio_net_device_realize()
3830 if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) { in virtio_net_device_unrealize()
3837 g_free(n->netclient_name); in virtio_net_device_unrealize()
3838 n->netclient_name = NULL; in virtio_net_device_unrealize()
3839 g_free(n->netclient_type); in virtio_net_device_unrealize()
3840 n->netclient_type = NULL; in virtio_net_device_unrealize()
3842 g_free(n->mac_table.macs); in virtio_net_device_unrealize()
3843 g_free(n->vlans); in virtio_net_device_unrealize()
3845 if (n->failover) { in virtio_net_device_unrealize()
3846 qobject_unref(n->primary_opts); in virtio_net_device_unrealize()
3847 device_listener_unregister(&n->primary_listener); in virtio_net_device_unrealize()
3848 migration_remove_notifier(&n->migration_state); in virtio_net_device_unrealize()
3850 assert(n->primary_opts == NULL); in virtio_net_device_unrealize()
3853 max_queue_pairs = n->multiqueue ? n->max_queue_pairs : 1; in virtio_net_device_unrealize()
3859 qemu_announce_timer_del(&n->announce_timer, false); in virtio_net_device_unrealize()
3860 g_free(n->vqs); in virtio_net_device_unrealize()
3861 qemu_del_nic(n->nic); in virtio_net_device_unrealize()
3863 g_free(n->rss_data.indirections_table); in virtio_net_device_unrealize()
3864 net_rx_pkt_uninit(n->rx_pkt); in virtio_net_device_unrealize()
3874 n->promisc = 1; in virtio_net_reset()
3875 n->allmulti = 0; in virtio_net_reset()
3876 n->alluni = 0; in virtio_net_reset()
3877 n->nomulti = 0; in virtio_net_reset()
3878 n->nouni = 0; in virtio_net_reset()
3879 n->nobcast = 0; in virtio_net_reset()
3881 n->curr_queue_pairs = 1; in virtio_net_reset()
3882 timer_del(n->announce_timer.tm); in virtio_net_reset()
3883 n->announce_timer.round = 0; in virtio_net_reset()
3884 n->status &= ~VIRTIO_NET_S_ANNOUNCE; in virtio_net_reset()
3887 n->mac_table.in_use = 0; in virtio_net_reset()
3888 n->mac_table.first_multi = 0; in virtio_net_reset()
3889 n->mac_table.multi_overflow = 0; in virtio_net_reset()
3890 n->mac_table.uni_overflow = 0; in virtio_net_reset()
3891 memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN); in virtio_net_reset()
3892 memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac)); in virtio_net_reset()
3893 qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac); in virtio_net_reset()
3894 memset(n->vlans, 0, MAX_VLAN >> 3); in virtio_net_reset()
3897 for (i = 0; i < n->max_queue_pairs; i++) { in virtio_net_reset()
3898 flush_or_purge_queued_packets(qemu_get_subqueue(n->nic, i)); in virtio_net_reset()
3912 n->config_size = sizeof(struct virtio_net_config); in virtio_net_instance_init()
3913 device_add_bootindex_property(obj, &n->nic_conf.bootindex, in virtio_net_instance_init()
3914 "bootindex", "/ethernet-phy@0", in virtio_net_instance_init()
3917 ebpf_rss_init(&n->ebpf_rss); in virtio_net_instance_init()
3926 assert(!n->vhost_started); in virtio_net_pre_save()
3942 return primary ? primary->pending_deleted_event : false; in primary_unplug_pending()
3950 return vdc->primary_unplug_pending(dev); in dev_unplug_pending()
3959 if (!n->nic) { in virtio_net_get_vhost()
3963 nc = qemu_get_queue(n->nic); in virtio_net_get_vhost()
3968 net = get_vhost_net(nc->peer); in virtio_net_get_vhost()
3973 return &net->dev; in virtio_net_get_vhost()
3977 .name = "virtio-net",
4033 DEFINE_PROP_ARRAY("ebpf-rss-fds", VirtIONet, nr_ebpf_rss_fds,
4040 DEFINE_PROP_UINT32("x-txtimer", VirtIONet, net_conf.txtimer,
4042 DEFINE_PROP_INT32("x-txburst", VirtIONet, net_conf.txburst, TX_BURST),
4049 DEFINE_PROP_BOOL("x-mtu-bypass-backend", VirtIONet, mtu_bypass_backend,
4069 dc->vmsd = &vmstate_virtio_net; in virtio_net_class_init()
4070 set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); in virtio_net_class_init()
4071 vdc->realize = virtio_net_device_realize; in virtio_net_class_init()
4072 vdc->unrealize = virtio_net_device_unrealize; in virtio_net_class_init()
4073 vdc->get_config = virtio_net_get_config; in virtio_net_class_init()
4074 vdc->set_config = virtio_net_set_config; in virtio_net_class_init()
4075 vdc->get_features = virtio_net_get_features; in virtio_net_class_init()
4076 vdc->set_features = virtio_net_set_features; in virtio_net_class_init()
4077 vdc->bad_features = virtio_net_bad_features; in virtio_net_class_init()
4078 vdc->reset = virtio_net_reset; in virtio_net_class_init()
4079 vdc->queue_reset = virtio_net_queue_reset; in virtio_net_class_init()
4080 vdc->queue_enable = virtio_net_queue_enable; in virtio_net_class_init()
4081 vdc->set_status = virtio_net_set_status; in virtio_net_class_init()
4082 vdc->guest_notifier_mask = virtio_net_guest_notifier_mask; in virtio_net_class_init()
4083 vdc->guest_notifier_pending = virtio_net_guest_notifier_pending; in virtio_net_class_init()
4084 vdc->legacy_features |= (0x1 << VIRTIO_NET_F_GSO); in virtio_net_class_init()
4085 vdc->pre_load_queues = virtio_net_pre_load_queues; in virtio_net_class_init()
4086 vdc->post_load = virtio_net_post_load_virtio; in virtio_net_class_init()
4087 vdc->vmsd = &vmstate_virtio_net_device; in virtio_net_class_init()
4088 vdc->primary_unplug_pending = primary_unplug_pending; in virtio_net_class_init()
4089 vdc->get_vhost = virtio_net_get_vhost; in virtio_net_class_init()
4090 vdc->toggle_device_iotlb = vhost_toggle_device_iotlb; in virtio_net_class_init()