From 5fe19fb81839ea42b592b409f725349cf3c73551 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Mon, 11 May 2020 12:04:53 +0800 Subject: net: use peer when purging queue in qemu_flush_or_purge_queue_packets() The sender of packet will be checked in the qemu_net_queue_purge() but we use NetClientState not its peer when trying to purge the incoming queue in qemu_flush_or_purge_packets(). This will trigger the assert in virtio_net_reset since we can't pass the sender check: hw/net/virtio-net.c:533: void virtio_net_reset(VirtIODevice *): Assertion `!virtio_net_get_subqueue(nc)->async_tx.elem' failed. #9 0x55a33fa31b78 in virtio_net_reset hw/net/virtio-net.c:533:13 #10 0x55a33fc88412 in virtio_reset hw/virtio/virtio.c:1919:9 #11 0x55a341d82764 in virtio_bus_reset hw/virtio/virtio-bus.c:95:9 #12 0x55a341dba2de in virtio_pci_reset hw/virtio/virtio-pci.c:1824:5 #13 0x55a341db3e02 in virtio_pci_common_write hw/virtio/virtio-pci.c:1252:13 #14 0x55a33f62117b in memory_region_write_accessor memory.c:496:5 #15 0x55a33f6205e4 in access_with_adjusted_size memory.c:557:18 #16 0x55a33f61e177 in memory_region_dispatch_write memory.c:1488:16 Reproducer: https://www.mail-archive.com/qemu-devel@nongnu.org/msg701914.html Fix by using the peer. Reported-by: "Alexander Bulekov" Acked-by: Alexander Bulekov Fixes: ca77d85e1dbf9 ("net: complete all queued packets on VM stop") Cc: qemu-stable@nongnu.org Signed-off-by: Jason Wang --- net/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/net.c') diff --git a/net/net.c b/net/net.c index cbeeeadff8..4c62b10acd 100644 --- a/net/net.c +++ b/net/net.c @@ -610,7 +610,7 @@ void qemu_flush_or_purge_queued_packets(NetClientState *nc, bool purge) qemu_notify_event(); } else if (purge) { /* Unable to empty the queue, purge remaining packets */ - qemu_net_queue_purge(nc->incoming_queue, nc); + qemu_net_queue_purge(nc->incoming_queue, nc->peer); } } -- cgit v1.2.3-55-g7522 From 9d903f30cb37eb2f7aec53ab58cd869f48ec16d5 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 18 May 2020 20:01:02 +0200 Subject: net: Drop the legacy "name" parameter from the -net option It's been deprecated since QEMU v3.1, so it's time to finally remove it. The "id" parameter can simply be used instead. Reviewed-by: Eric Blake Signed-off-by: Thomas Huth Signed-off-by: Jason Wang --- docs/system/deprecated.rst | 15 +++++++++------ net/net.c | 10 +--------- qapi/net.json | 3 --- 3 files changed, 10 insertions(+), 18 deletions(-) (limited to 'net/net.c') diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst index 544ece0a45..3a255591c3 100644 --- a/docs/system/deprecated.rst +++ b/docs/system/deprecated.rst @@ -47,12 +47,6 @@ The 'file' driver for drives is no longer appropriate for character or host devices and will only accept regular files (S_IFREG). The correct driver for these file types is 'host_cdrom' or 'host_device' as appropriate. -``-net ...,name=``\ *name* (since 3.1) -'''''''''''''''''''''''''''''''''''''' - -The ``name`` parameter of the ``-net`` option is a synonym -for the ``id`` parameter, which should now be used instead. - ``-smp`` (invalid topologies) (since 3.1) ''''''''''''''''''''''''''''''''''''''''' @@ -441,6 +435,15 @@ What follows is a record of recently removed, formerly deprecated features that serves as a record for users who have encountered trouble after a recent upgrade. +System emulator command line arguments +-------------------------------------- + +``-net ...,name=``\ *name* (removed in 5.1) +''''''''''''''''''''''''''''''''''''''''''' + +The ``name`` parameter of the ``-net`` option was a synonym +for the ``id`` parameter, which should now be used instead. + QEMU Machine Protocol (QMP) commands ------------------------------------ diff --git a/net/net.c b/net/net.c index 4c62b10acd..e55d3572a4 100644 --- a/net/net.c +++ b/net/net.c @@ -969,12 +969,10 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp) { Netdev legacy = {0}; const Netdev *netdev; - const char *name; NetClientState *peer = NULL; if (is_netdev) { netdev = object; - name = netdev->id; if (netdev->type == NET_CLIENT_DRIVER_NIC || !net_client_init_fun[netdev->type]) { @@ -987,12 +985,6 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp) const NetLegacyOptions *opts = net->opts; legacy.id = net->id; netdev = &legacy; - /* missing optional values have been initialized to "all bits zero" */ - name = net->has_id ? net->id : net->name; - - if (net->has_name) { - warn_report("The 'name' parameter is deprecated, use 'id' instead"); - } /* Map the old options to the new flat type */ switch (opts->type) { @@ -1052,7 +1044,7 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp) } } - if (net_client_init_fun[netdev->type](netdev, name, peer, errp) < 0) { + if (net_client_init_fun[netdev->type](netdev, netdev->id, peer, errp) < 0) { /* FIXME drop when all init functions store an Error */ if (errp && !*errp) { error_setg(errp, QERR_DEVICE_INIT_FAILED, diff --git a/qapi/net.json b/qapi/net.json index cebb1b52e3..fc7c95f6d8 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -474,8 +474,6 @@ # # @id: identifier for monitor commands # -# @name: identifier for monitor commands, ignored if @id is present -# # @opts: device type specific properties (legacy) # # Since: 1.2 @@ -483,7 +481,6 @@ { 'struct': 'NetLegacy', 'data': { '*id': 'str', - '*name': 'str', 'opts': 'NetLegacyOptions' } } ## -- cgit v1.2.3-55-g7522 From 71830d8430e65dd20aec4765d87e60336148e1a6 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 18 May 2020 20:01:03 +0200 Subject: net: Drop the NetLegacy structure, always use Netdev instead Now that the "name" parameter is gone, there is hardly any difference between NetLegacy and Netdev anymore, so we can drop NetLegacy and always use Netdev to simplify the code quite a bit. The only two differences that were really left between Netdev and NetLegacy: 1) NetLegacy does not allow a "hubport" type. We can continue to block this with a simple check in net_client_init1() for this type. 2) The "id" parameter was optional in NetLegacy (and an internal id was chosen via assign_name() during initialization), but it is mandatory for Netdev. To avoid that the visitor code bails out here, we have to add an internal id to the QemuOpts already earlier now. Signed-off-by: Thomas Huth Reviewed-by: Eric Blake Signed-off-by: Jason Wang --- net/net.c | 77 ++++++++++------------------------------------------------- qapi/net.json | 46 ----------------------------------- 2 files changed, 13 insertions(+), 110 deletions(-) (limited to 'net/net.c') diff --git a/net/net.c b/net/net.c index e55d3572a4..d1130296e1 100644 --- a/net/net.c +++ b/net/net.c @@ -965,15 +965,11 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])( }; -static int net_client_init1(const void *object, bool is_netdev, Error **errp) +static int net_client_init1(const Netdev *netdev, bool is_netdev, Error **errp) { - Netdev legacy = {0}; - const Netdev *netdev; NetClientState *peer = NULL; if (is_netdev) { - netdev = object; - if (netdev->type == NET_CLIENT_DRIVER_NIC || !net_client_init_fun[netdev->type]) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", @@ -981,56 +977,11 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp) return -1; } } else { - const NetLegacy *net = object; - const NetLegacyOptions *opts = net->opts; - legacy.id = net->id; - netdev = &legacy; - - /* Map the old options to the new flat type */ - switch (opts->type) { - case NET_LEGACY_OPTIONS_TYPE_NONE: + if (netdev->type == NET_CLIENT_DRIVER_NONE) { return 0; /* nothing to do */ - case NET_LEGACY_OPTIONS_TYPE_NIC: - legacy.type = NET_CLIENT_DRIVER_NIC; - legacy.u.nic = opts->u.nic; - break; - case NET_LEGACY_OPTIONS_TYPE_USER: - legacy.type = NET_CLIENT_DRIVER_USER; - legacy.u.user = opts->u.user; - break; - case NET_LEGACY_OPTIONS_TYPE_TAP: - legacy.type = NET_CLIENT_DRIVER_TAP; - legacy.u.tap = opts->u.tap; - break; - case NET_LEGACY_OPTIONS_TYPE_L2TPV3: - legacy.type = NET_CLIENT_DRIVER_L2TPV3; - legacy.u.l2tpv3 = opts->u.l2tpv3; - break; - case NET_LEGACY_OPTIONS_TYPE_SOCKET: - legacy.type = NET_CLIENT_DRIVER_SOCKET; - legacy.u.socket = opts->u.socket; - break; - case NET_LEGACY_OPTIONS_TYPE_VDE: - legacy.type = NET_CLIENT_DRIVER_VDE; - legacy.u.vde = opts->u.vde; - break; - case NET_LEGACY_OPTIONS_TYPE_BRIDGE: - legacy.type = NET_CLIENT_DRIVER_BRIDGE; - legacy.u.bridge = opts->u.bridge; - break; - case NET_LEGACY_OPTIONS_TYPE_NETMAP: - legacy.type = NET_CLIENT_DRIVER_NETMAP; - legacy.u.netmap = opts->u.netmap; - break; - case NET_LEGACY_OPTIONS_TYPE_VHOST_USER: - legacy.type = NET_CLIENT_DRIVER_VHOST_USER; - legacy.u.vhost_user = opts->u.vhost_user; - break; - default: - abort(); } - - if (!net_client_init_fun[netdev->type]) { + if (netdev->type == NET_CLIENT_DRIVER_HUBPORT || + !net_client_init_fun[netdev->type]) { error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type", "a net backend type (maybe it is not compiled " "into this binary)"); @@ -1039,7 +990,7 @@ static int net_client_init1(const void *object, bool is_netdev, Error **errp) /* Do not add to a hub if it's a nic with a netdev= parameter. */ if (netdev->type != NET_CLIENT_DRIVER_NIC || - !opts->u.nic.has_netdev) { + !netdev->u.nic.has_netdev) { peer = net_hub_add_port(0, NULL, NULL); } } @@ -1100,7 +1051,7 @@ static void show_netdevs(void) static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) { gchar **substrings = NULL; - void *object = NULL; + Netdev *object = NULL; Error *err = NULL; int ret = -1; Visitor *v = opts_visitor_new(opts); @@ -1143,21 +1094,19 @@ static int net_client_init(QemuOpts *opts, bool is_netdev, Error **errp) } } - if (is_netdev) { - visit_type_Netdev(v, NULL, (Netdev **)&object, &err); - } else { - visit_type_NetLegacy(v, NULL, (NetLegacy **)&object, &err); + /* Create an ID for -net if the user did not specify one */ + if (!is_netdev && !qemu_opts_id(opts)) { + static int idx; + qemu_opts_set_id(opts, g_strdup_printf("__org.qemu.net%i", idx++)); } + visit_type_Netdev(v, NULL, &object, &err); + if (!err) { ret = net_client_init1(object, is_netdev, &err); } - if (is_netdev) { - qapi_free_Netdev(object); - } else { - qapi_free_NetLegacy(object); - } + qapi_free_Netdev(object); out: error_propagate(errp, err); diff --git a/qapi/net.json b/qapi/net.json index fc7c95f6d8..9244c9af56 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -467,52 +467,6 @@ 'netmap': 'NetdevNetmapOptions', 'vhost-user': 'NetdevVhostUserOptions' } } -## -# @NetLegacy: -# -# Captures the configuration of a network device; legacy. -# -# @id: identifier for monitor commands -# -# @opts: device type specific properties (legacy) -# -# Since: 1.2 -## -{ 'struct': 'NetLegacy', - 'data': { - '*id': 'str', - 'opts': 'NetLegacyOptions' } } - -## -# @NetLegacyOptionsType: -# -# Since: 1.2 -## -{ 'enum': 'NetLegacyOptionsType', - 'data': ['none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde', - 'bridge', 'netmap', 'vhost-user'] } - -## -# @NetLegacyOptions: -# -# Like Netdev, but for use only by the legacy command line options -# -# Since: 1.2 -## -{ 'union': 'NetLegacyOptions', - 'base': { 'type': 'NetLegacyOptionsType' }, - 'discriminator': 'type', - 'data': { - 'nic': 'NetLegacyNicOptions', - 'user': 'NetdevUserOptions', - 'tap': 'NetdevTapOptions', - 'l2tpv3': 'NetdevL2TPv3Options', - 'socket': 'NetdevSocketOptions', - 'vde': 'NetdevVdeOptions', - 'bridge': 'NetdevBridgeOptions', - 'netmap': 'NetdevNetmapOptions', - 'vhost-user': 'NetdevVhostUserOptions' } } - ## # @NetFilterDirection: # -- cgit v1.2.3-55-g7522