From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4E131C4332F for ; Sun, 29 Oct 2023 22:17:18 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qxE5D-0002UP-Gc; Sun, 29 Oct 2023 18:16:35 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qxE51-0002Mq-Ul for qemu-devel@nongnu.org; Sun, 29 Oct 2023 18:16:33 -0400 Received: from mail-lj1-x230.google.com ([2a00:1450:4864:20::230]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qxE4v-00026N-71 for qemu-devel@nongnu.org; Sun, 29 Oct 2023 18:16:20 -0400 Received: by mail-lj1-x230.google.com with SMTP id 38308e7fff4ca-2c6b48cb2b6so15683251fa.2 for ; Sun, 29 Oct 2023 15:16:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20230601.gappssmtp.com; s=20230601; t=1698617768; x=1699222568; darn=nongnu.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=BGzCiJmDIETYEQ64pdolEVu3tp3edFoCG5ZkdJdU3FY=; b=p/Yr3IKheln2ytxHyWt+XDcIocW1HyBjtobhEn9lJFwkoJZlW5x0paulxTnco/edMf 75BPTUWo0UACcuKY1GOOHJ5K1w0XPomeIqDOVWY0QNHpFG1lmkzNw7Q2/P0hBCw2NLnf SNpMh9apdggMLuq45i5PieXiEo22UjUzV9wr6MgSNScaXqPTnveih1w0EkxtLAYJb+He KxW9VebifCf7HCN0EvlZ9wsaF4vjY2ss1yF0tektpKadrg8CpBTdGoAd14Mq8pN8NXfp 3IS6vrRc39E/IBZP/DOrq0msfTDcwXcwMQ2arlQO/QO9nQd++/viddKOoHP67nTAwjJF cSWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698617768; x=1699222568; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=BGzCiJmDIETYEQ64pdolEVu3tp3edFoCG5ZkdJdU3FY=; b=l7hpYm8XfPZVDJAZwANRjUE1nIW6hDg4IKUIWgwn2AeHcfWytmF+Ni+6I+QTnQcobo nWAnDS4Kuk2r1oBTzd2PBa/R5DglRgKRrolF8dqo88tI+31HrHsdv6+sybz30s1AOGLx ouLE5aK/+mJ9l8yyAooUzL9Nu/q+VLvk8ULgV1E4ghcd+Xqw3LojJh02QwYBQHnRJuW4 pLhMChv3zsxbRVYEF9e9rH7vJ4ZoumtENDtz0pwBeIdd5xkGBq4ilh9ELzgfIWs3zw+o KhLT1cOQc8T2tUSZvSEiEkKlxaIcR514F7LSsPc7cBunHTSnTmvF8LN6I6RUp3VT1FWs xZqg== X-Gm-Message-State: AOJu0Yz61P3V0Ry/lDXIE+AhXZ8YgWYUk/jgGfHV758ewDVJNVO2IPf3 lZhybKfoBqLdY8y8BlVPwp75n93aZuke+5DIP29N6w== X-Google-Smtp-Source: AGHT+IF/4QT9o4ZnubqPPZXrsAj+k/jBY6eIlUJfL/W767s/xtBlY/H93hxbwJQsYcQX4/hyvGD8wvkMo9eUPF/GT0U= X-Received: by 2002:a2e:9049:0:b0:2bc:db99:1775 with SMTP id n9-20020a2e9049000000b002bcdb991775mr5263639ljg.26.1698617768011; Sun, 29 Oct 2023 15:16:08 -0700 (PDT) MIME-Version: 1.0 References: <20231017040932.62997-1-akihiko.odaki@daynix.com> <20231017040932.62997-12-akihiko.odaki@daynix.com> In-Reply-To: <20231017040932.62997-12-akihiko.odaki@daynix.com> From: Yuri Benditovich Date: Mon, 30 Oct 2023 00:15:56 +0200 Message-ID: Subject: Re: [PATCH v5 11/21] virtio-net: Return an error when vhost cannot enable RSS To: Akihiko Odaki Cc: qemu-devel@nongnu.org, Andrew Melnychenko , "Michael S . Tsirkin" , Jason Wang Content-Type: multipart/alternative; boundary="000000000000abfab00608e244e6" Received-SPF: none client-ip=2a00:1450:4864:20::230; envelope-from=yuri.benditovich@daynix.com; helo=mail-lj1-x230.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --000000000000abfab00608e244e6 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Tue, Oct 17, 2023 at 7:10=E2=80=AFAM Akihiko Odaki wrote: > vhost requires eBPF for RSS. Even when eBPF is not available, virtio-net > reported RSS availability, and raised a warning only after the > guest requested RSS, and the guest could not know that RSS is not > available. > > The existing code suggests the RSS feature for vhost case only when the ebpf is loaded. https://github.com/qemu/qemu/blob/master/hw/net/virtio-net.c#L828 Am I wrong? > Check RSS availability during device realization and return an error > if RSS is requested but not available. Assert RSS availability when > the guest actually requests the feature. > > Signed-off-by: Akihiko Odaki > --- > ebpf/ebpf_rss.h | 2 +- > ebpf/ebpf_rss-stub.c | 4 +- > ebpf/ebpf_rss.c | 68 +++++++++----------------- > hw/net/virtio-net.c | 114 +++++++++++++++++++++---------------------- > 4 files changed, 82 insertions(+), 106 deletions(-) > > diff --git a/ebpf/ebpf_rss.h b/ebpf/ebpf_rss.h > index bf3f2572c7..1128173572 100644 > --- a/ebpf/ebpf_rss.h > +++ b/ebpf/ebpf_rss.h > @@ -36,7 +36,7 @@ bool ebpf_rss_is_loaded(struct EBPFRSSContext *ctx); > > bool ebpf_rss_load(struct EBPFRSSContext *ctx); > > -bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig > *config, > +void ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig > *config, > uint16_t *indirections_table, uint8_t > *toeplitz_key); > > void ebpf_rss_unload(struct EBPFRSSContext *ctx); > diff --git a/ebpf/ebpf_rss-stub.c b/ebpf/ebpf_rss-stub.c > index e71e229190..525b358597 100644 > --- a/ebpf/ebpf_rss-stub.c > +++ b/ebpf/ebpf_rss-stub.c > @@ -28,10 +28,10 @@ bool ebpf_rss_load(struct EBPFRSSContext *ctx) > return false; > } > > -bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig > *config, > +void ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig > *config, > uint16_t *indirections_table, uint8_t *toeplitz_ke= y) > { > - return false; > + g_assert_not_reached(); > } > > void ebpf_rss_unload(struct EBPFRSSContext *ctx) > diff --git a/ebpf/ebpf_rss.c b/ebpf/ebpf_rss.c > index cee658c158..6cdf82d059 100644 > --- a/ebpf/ebpf_rss.c > +++ b/ebpf/ebpf_rss.c > @@ -74,42 +74,32 @@ error: > return false; > } > > -static bool ebpf_rss_set_config(struct EBPFRSSContext *ctx, > +static void ebpf_rss_set_config(struct EBPFRSSContext *ctx, > struct EBPFRSSConfig *config) > { > uint32_t map_key =3D 0; > > - if (!ebpf_rss_is_loaded(ctx)) { > - return false; > - } > - if (bpf_map_update_elem(ctx->map_configuration, > - &map_key, config, 0) < 0) { > - return false; > - } > - return true; > + assert(ebpf_rss_is_loaded(ctx)); > + assert(!bpf_map_update_elem(ctx->map_configuration, &map_key, config= , > 0)); > } > > -static bool ebpf_rss_set_indirections_table(struct EBPFRSSContext *ctx, > +static void ebpf_rss_set_indirections_table(struct EBPFRSSContext *ctx, > uint16_t *indirections_table= , > size_t len) > { > uint32_t i =3D 0; > > - if (!ebpf_rss_is_loaded(ctx) || indirections_table =3D=3D NULL || > - len > VIRTIO_NET_RSS_MAX_TABLE_LEN) { > - return false; > - } > + assert(ebpf_rss_is_loaded(ctx)); > + assert(indirections_table); > + assert(len <=3D VIRTIO_NET_RSS_MAX_TABLE_LEN); > > for (; i < len; ++i) { > - if (bpf_map_update_elem(ctx->map_indirections_table, &i, > - indirections_table + i, 0) < 0) { > - return false; > - } > + assert(!bpf_map_update_elem(ctx->map_indirections_table, &i, > + indirections_table + i, 0)); > } > - return true; > } > > -static bool ebpf_rss_set_toepliz_key(struct EBPFRSSContext *ctx, > +static void ebpf_rss_set_toepliz_key(struct EBPFRSSContext *ctx, > uint8_t *toeplitz_key) > { > uint32_t map_key =3D 0; > @@ -117,41 +107,29 @@ static bool ebpf_rss_set_toepliz_key(struct > EBPFRSSContext *ctx, > /* prepare toeplitz key */ > uint8_t toe[VIRTIO_NET_RSS_MAX_KEY_SIZE] =3D {}; > > - if (!ebpf_rss_is_loaded(ctx) || toeplitz_key =3D=3D NULL) { > - return false; > - } > + assert(ebpf_rss_is_loaded(ctx)); > + assert(toeplitz_key); > + > memcpy(toe, toeplitz_key, VIRTIO_NET_RSS_MAX_KEY_SIZE); > *(uint32_t *)toe =3D ntohl(*(uint32_t *)toe); > > - if (bpf_map_update_elem(ctx->map_toeplitz_key, &map_key, toe, > - 0) < 0) { > - return false; > - } > - return true; > + assert(!bpf_map_update_elem(ctx->map_toeplitz_key, &map_key, toe, 0)= ); > } > > -bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig > *config, > +void ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig > *config, > uint16_t *indirections_table, uint8_t *toeplitz_ke= y) > { > - if (!ebpf_rss_is_loaded(ctx) || config =3D=3D NULL || > - indirections_table =3D=3D NULL || toeplitz_key =3D=3D NULL) { > - return false; > - } > - > - if (!ebpf_rss_set_config(ctx, config)) { > - return false; > - } > + assert(ebpf_rss_is_loaded(ctx)); > + assert(config); > + assert(indirections_table); > + assert(toeplitz_key); > > - if (!ebpf_rss_set_indirections_table(ctx, indirections_table, > - config->indirections_len)) { > - return false; > - } > + ebpf_rss_set_config(ctx, config); > > - if (!ebpf_rss_set_toepliz_key(ctx, toeplitz_key)) { > - return false; > - } > + ebpf_rss_set_indirections_table(ctx, indirections_table, > + config->indirections_len); > > - return true; > + ebpf_rss_set_toepliz_key(ctx, toeplitz_key); > } > > void ebpf_rss_unload(struct EBPFRSSContext *ctx) > diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c > index 25fc06bd93..20feb20bb1 100644 > --- a/hw/net/virtio-net.c > +++ b/hw/net/virtio-net.c > @@ -1242,14 +1242,10 @@ static bool virtio_net_attach_epbf_rss(VirtIONet > *n) > > rss_data_to_rss_config(&n->rss_data, &config); > > - if (!ebpf_rss_set_all(&n->ebpf_rss, &config, > - n->rss_data.indirections_table, > n->rss_data.key)) { > - return false; > - } > + ebpf_rss_set_all(&n->ebpf_rss, &config, > + n->rss_data.indirections_table, n->rss_data.key); > > - if (!virtio_net_attach_ebpf_to_backend(n->nic, > n->ebpf_rss.program_fd)) { > - return false; > - } > + assert(virtio_net_attach_ebpf_to_backend(n->nic, > n->ebpf_rss.program_fd)); > > return true; > } > @@ -1266,12 +1262,7 @@ static void virtio_net_commit_rss_config(VirtIONet > *n) > if (n->rss_data.populate_hash) { > virtio_net_detach_epbf_rss(n); > } else if (!virtio_net_attach_epbf_rss(n)) { > - if (get_vhost_net(qemu_get_queue(n->nic)->peer)) { > - warn_report("Can't use eBPF RSS for vhost"); > - } else { > - warn_report("Can't use eBPF RSS - fallback to software > RSS"); > - n->rss_data.enabled_software_rss =3D true; > - } > + n->rss_data.enabled_software_rss =3D true; > } > > trace_virtio_net_rss_enable(n->rss_data.hash_types, > @@ -3514,6 +3505,50 @@ static bool > failover_hide_primary_device(DeviceListener *listener, > return qatomic_read(&n->failover_primary_hidden); > } > > +static void virtio_net_device_unrealize(DeviceState *dev) > +{ > + VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > + VirtIONet *n =3D VIRTIO_NET(dev); > + int i, max_queue_pairs; > + > + if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) { > + virtio_net_unload_ebpf(n); > + } > + > + /* This will stop vhost backend if appropriate. */ > + virtio_net_set_status(vdev, 0); > + > + g_free(n->netclient_name); > + n->netclient_name =3D NULL; > + g_free(n->netclient_type); > + n->netclient_type =3D NULL; > + > + g_free(n->mac_table.macs); > + g_free(n->vlans); > + > + if (n->failover) { > + qobject_unref(n->primary_opts); > + device_listener_unregister(&n->primary_listener); > + remove_migration_state_change_notifier(&n->migration_state); > + } else { > + assert(n->primary_opts =3D=3D NULL); > + } > + > + max_queue_pairs =3D n->multiqueue ? n->max_queue_pairs : 1; > + for (i =3D 0; i < max_queue_pairs; i++) { > + virtio_net_del_queue(n, i); > + } > + /* delete also control vq */ > + virtio_del_queue(vdev, max_queue_pairs * 2); > + qemu_announce_timer_del(&n->announce_timer, false); > + g_free(n->vqs); > + qemu_del_nic(n->nic); > + virtio_net_rsc_cleanup(n); > + g_free(n->rss_data.indirections_table); > + net_rx_pkt_uninit(n->rx_pkt); > + virtio_cleanup(vdev); > +} > + > static void virtio_net_device_realize(DeviceState *dev, Error **errp) > { > VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > @@ -3685,53 +3720,16 @@ static void virtio_net_device_realize(DeviceState > *dev, Error **errp) > > net_rx_pkt_init(&n->rx_pkt); > > - if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) { > - virtio_net_load_ebpf(n); > - } > -} > - > -static void virtio_net_device_unrealize(DeviceState *dev) > -{ > - VirtIODevice *vdev =3D VIRTIO_DEVICE(dev); > - VirtIONet *n =3D VIRTIO_NET(dev); > - int i, max_queue_pairs; > - > - if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS)) { > - virtio_net_unload_ebpf(n); > - } > - > - /* This will stop vhost backend if appropriate. */ > - virtio_net_set_status(vdev, 0); > - > - g_free(n->netclient_name); > - n->netclient_name =3D NULL; > - g_free(n->netclient_type); > - n->netclient_type =3D NULL; > - > - g_free(n->mac_table.macs); > - g_free(n->vlans); > - > - if (n->failover) { > - qobject_unref(n->primary_opts); > - device_listener_unregister(&n->primary_listener); > - remove_migration_state_change_notifier(&n->migration_state); > - } else { > - assert(n->primary_opts =3D=3D NULL); > - } > + if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS) && > + !virtio_net_load_ebpf(n)) { > + if (get_vhost_net(nc->peer)) { > + error_setg(errp, "Can't load eBPF RSS for vhost"); > + virtio_net_device_unrealize(dev); > + return; > + } > > - max_queue_pairs =3D n->multiqueue ? n->max_queue_pairs : 1; > - for (i =3D 0; i < max_queue_pairs; i++) { > - virtio_net_del_queue(n, i); > + warn_report_once("Can't load eBPF RSS - fallback to software > RSS"); > } > - /* delete also control vq */ > - virtio_del_queue(vdev, max_queue_pairs * 2); > - qemu_announce_timer_del(&n->announce_timer, false); > - g_free(n->vqs); > - qemu_del_nic(n->nic); > - virtio_net_rsc_cleanup(n); > - g_free(n->rss_data.indirections_table); > - net_rx_pkt_uninit(n->rx_pkt); > - virtio_cleanup(vdev); > } > > static void virtio_net_reset(VirtIODevice *vdev) > -- > 2.42.0 > > --000000000000abfab00608e244e6 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


=
On Tue, Oct 17, 2023 at 7:10=E2=80=AF= AM Akihiko Odaki <akihiko.od= aki@daynix.com> wrote:
vhost requires eBPF for RSS. Even when eBPF is not available,= virtio-net
reported RSS availability, and raised a warning only after the
guest requested RSS, and the guest could not know that RSS is not
available.


The existing code suggests the RSS feature= for vhost case only when the ebpf is loaded.
Am I wr= ong?

=C2=A0
Check RSS availability during device realization and retur= n an error
if RSS is requested but not available. Assert RSS availability when
the guest actually requests the feature.

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
---
=C2=A0ebpf/ebpf_rss.h=C2=A0 =C2=A0 =C2=A0 |=C2=A0 =C2=A02 +-
=C2=A0ebpf/ebpf_rss-stub.c |=C2=A0 =C2=A04 +-
=C2=A0ebpf/ebpf_rss.c=C2=A0 =C2=A0 =C2=A0 |=C2=A0 68 +++++++++-------------= ----
=C2=A0hw/net/virtio-net.c=C2=A0 | 114 +++++++++++++++++++++----------------= ------
=C2=A04 files changed, 82 insertions(+), 106 deletions(-)

diff --git a/ebpf/ebpf_rss.h b/ebpf/ebpf_rss.h
index bf3f2572c7..1128173572 100644
--- a/ebpf/ebpf_rss.h
+++ b/ebpf/ebpf_rss.h
@@ -36,7 +36,7 @@ bool ebpf_rss_is_loaded(struct EBPFRSSContext *ctx);

=C2=A0bool ebpf_rss_load(struct EBPFRSSContext *ctx);

-bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *co= nfig,
+void ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *co= nfig,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0uint16_t *indirections_table, uint8_t *toeplitz_key);

=C2=A0void ebpf_rss_unload(struct EBPFRSSContext *ctx);
diff --git a/ebpf/ebpf_rss-stub.c b/ebpf/ebpf_rss-stub.c
index e71e229190..525b358597 100644
--- a/ebpf/ebpf_rss-stub.c
+++ b/ebpf/ebpf_rss-stub.c
@@ -28,10 +28,10 @@ bool ebpf_rss_load(struct EBPFRSSContext *ctx)
=C2=A0 =C2=A0 =C2=A0return false;
=C2=A0}

-bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *co= nfig,
+void ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *co= nfig,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0uint16_t *indirections_table, uint8_t *toeplitz_key)
=C2=A0{
-=C2=A0 =C2=A0 return false;
+=C2=A0 =C2=A0 g_assert_not_reached();
=C2=A0}

=C2=A0void ebpf_rss_unload(struct EBPFRSSContext *ctx)
diff --git a/ebpf/ebpf_rss.c b/ebpf/ebpf_rss.c
index cee658c158..6cdf82d059 100644
--- a/ebpf/ebpf_rss.c
+++ b/ebpf/ebpf_rss.c
@@ -74,42 +74,32 @@ error:
=C2=A0 =C2=A0 =C2=A0return false;
=C2=A0}

-static bool ebpf_rss_set_config(struct EBPFRSSContext *ctx,
+static void ebpf_rss_set_config(struct EBPFRSSContext *ctx,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0struct EBPFRSSConfig *config)<= br> =C2=A0{
=C2=A0 =C2=A0 =C2=A0uint32_t map_key =3D 0;

-=C2=A0 =C2=A0 if (!ebpf_rss_is_loaded(ctx)) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
-=C2=A0 =C2=A0 }
-=C2=A0 =C2=A0 if (bpf_map_update_elem(ctx->map_configuration,
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 &map_key, config, 0) < 0) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
-=C2=A0 =C2=A0 }
-=C2=A0 =C2=A0 return true;
+=C2=A0 =C2=A0 assert(ebpf_rss_is_loaded(ctx));
+=C2=A0 =C2=A0 assert(!bpf_map_update_elem(ctx->map_configuration, &= map_key, config, 0));
=C2=A0}

-static bool ebpf_rss_set_indirections_table(struct EBPFRSSContext *ctx, +static void ebpf_rss_set_indirections_table(struct EBPFRSSContext *ctx, =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0uint16_t *indirections_table,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0size_t len)
=C2=A0{
=C2=A0 =C2=A0 =C2=A0uint32_t i =3D 0;

-=C2=A0 =C2=A0 if (!ebpf_rss_is_loaded(ctx) || indirections_table =3D=3D NU= LL ||
-=C2=A0 =C2=A0 =C2=A0 =C2=A0len > VIRTIO_NET_RSS_MAX_TABLE_LEN) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
-=C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 assert(ebpf_rss_is_loaded(ctx));
+=C2=A0 =C2=A0 assert(indirections_table);
+=C2=A0 =C2=A0 assert(len <=3D VIRTIO_NET_RSS_MAX_TABLE_LEN);

=C2=A0 =C2=A0 =C2=A0for (; i < len; ++i) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (bpf_map_update_elem(ctx->map_indirectio= ns_table, &i,
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 indirections_table + i, 0) < 0) {=
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 assert(!bpf_map_update_elem(ctx->map_indire= ctions_table, &i,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 indirections_table + i= , 0));
=C2=A0 =C2=A0 =C2=A0}
-=C2=A0 =C2=A0 return true;
=C2=A0}

-static bool ebpf_rss_set_toepliz_key(struct EBPFRSSContext *ctx,
+static void ebpf_rss_set_toepliz_key(struct EBPFRSSContext *ctx,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 uint8_t *toepli= tz_key)
=C2=A0{
=C2=A0 =C2=A0 =C2=A0uint32_t map_key =3D 0;
@@ -117,41 +107,29 @@ static bool ebpf_rss_set_toepliz_key(struct EBPFRSSCo= ntext *ctx,
=C2=A0 =C2=A0 =C2=A0/* prepare toeplitz key */
=C2=A0 =C2=A0 =C2=A0uint8_t toe[VIRTIO_NET_RSS_MAX_KEY_SIZE] =3D {};

-=C2=A0 =C2=A0 if (!ebpf_rss_is_loaded(ctx) || toeplitz_key =3D=3D NULL) {<= br> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
-=C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 assert(ebpf_rss_is_loaded(ctx));
+=C2=A0 =C2=A0 assert(toeplitz_key);
+
=C2=A0 =C2=A0 =C2=A0memcpy(toe, toeplitz_key, VIRTIO_NET_RSS_MAX_KEY_SIZE);=
=C2=A0 =C2=A0 =C2=A0*(uint32_t *)toe =3D ntohl(*(uint32_t *)toe);

-=C2=A0 =C2=A0 if (bpf_map_update_elem(ctx->map_toeplitz_key, &map_k= ey, toe,
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 0) < 0) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
-=C2=A0 =C2=A0 }
-=C2=A0 =C2=A0 return true;
+=C2=A0 =C2=A0 assert(!bpf_map_update_elem(ctx->map_toeplitz_key, &m= ap_key, toe, 0));
=C2=A0}

-bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *co= nfig,
+void ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *co= nfig,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0uint16_t *indirections_table, uint8_t *toeplitz_key)
=C2=A0{
-=C2=A0 =C2=A0 if (!ebpf_rss_is_loaded(ctx) || config =3D=3D NULL ||
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 indirections_table =3D=3D NULL || toeplitz_key= =3D=3D NULL) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
-=C2=A0 =C2=A0 }
-
-=C2=A0 =C2=A0 if (!ebpf_rss_set_config(ctx, config)) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
-=C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 assert(ebpf_rss_is_loaded(ctx));
+=C2=A0 =C2=A0 assert(config);
+=C2=A0 =C2=A0 assert(indirections_table);
+=C2=A0 =C2=A0 assert(toeplitz_key);

-=C2=A0 =C2=A0 if (!ebpf_rss_set_indirections_table(ctx, indirections_table= ,
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 config->indi= rections_len)) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
-=C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 ebpf_rss_set_config(ctx, config);

-=C2=A0 =C2=A0 if (!ebpf_rss_set_toepliz_key(ctx, toeplitz_key)) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
-=C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 ebpf_rss_set_indirections_table(ctx, indirections_table,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 config->indirection= s_len);

-=C2=A0 =C2=A0 return true;
+=C2=A0 =C2=A0 ebpf_rss_set_toepliz_key(ctx, toeplitz_key);
=C2=A0}

=C2=A0void ebpf_rss_unload(struct EBPFRSSContext *ctx)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 25fc06bd93..20feb20bb1 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1242,14 +1242,10 @@ static bool virtio_net_attach_epbf_rss(VirtIONet *n= )

=C2=A0 =C2=A0 =C2=A0rss_data_to_rss_config(&n->rss_data, &config= );

-=C2=A0 =C2=A0 if (!ebpf_rss_set_all(&n->ebpf_rss, &config,
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 n->rss_data.indirections_table, n->rss_data.key)) {=
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
-=C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 ebpf_rss_set_all(&n->ebpf_rss, &config,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0n->rss_data.indirections_table, n->rss_data.key);

-=C2=A0 =C2=A0 if (!virtio_net_attach_ebpf_to_backend(n->nic, n->ebpf= _rss.program_fd)) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 return false;
-=C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 assert(virtio_net_attach_ebpf_to_backend(n->nic, n->eb= pf_rss.program_fd));

=C2=A0 =C2=A0 =C2=A0return true;
=C2=A0}
@@ -1266,12 +1262,7 @@ static void virtio_net_commit_rss_config(VirtIONet *= n)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (n->rss_data.populate_hash) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0virtio_net_detach_epbf_rss(= n);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else if (!virtio_net_attach_epbf_rss(n)= ) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (get_vhost_net(qemu_get_queue= (n->nic)->peer)) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 warn_report("= Can't use eBPF RSS for vhost");
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 warn_report("= Can't use eBPF RSS - fallback to software RSS");
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 n->rss_data.ena= bled_software_rss =3D true;
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 n->rss_data.enabled_software_= rss =3D true;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0trace_virtio_net_rss_enable(n->rss_dat= a.hash_types,
@@ -3514,6 +3505,50 @@ static bool failover_hide_primary_device(DeviceListe= ner *listener,
=C2=A0 =C2=A0 =C2=A0return qatomic_read(&n->failover_primary_hidden)= ;
=C2=A0}

+static void virtio_net_device_unrealize(DeviceState *dev)
+{
+=C2=A0 =C2=A0 VirtIODevice *vdev =3D VIRTIO_DEVICE(dev);
+=C2=A0 =C2=A0 VirtIONet *n =3D VIRTIO_NET(dev);
+=C2=A0 =C2=A0 int i, max_queue_pairs;
+
+=C2=A0 =C2=A0 if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS= )) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 virtio_net_unload_ebpf(n);
+=C2=A0 =C2=A0 }
+
+=C2=A0 =C2=A0 /* This will stop vhost backend if appropriate. */
+=C2=A0 =C2=A0 virtio_net_set_status(vdev, 0);
+
+=C2=A0 =C2=A0 g_free(n->netclient_name);
+=C2=A0 =C2=A0 n->netclient_name =3D NULL;
+=C2=A0 =C2=A0 g_free(n->netclient_type);
+=C2=A0 =C2=A0 n->netclient_type =3D NULL;
+
+=C2=A0 =C2=A0 g_free(n->mac_table.macs);
+=C2=A0 =C2=A0 g_free(n->vlans);
+
+=C2=A0 =C2=A0 if (n->failover) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 qobject_unref(n->primary_opts);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 device_listener_unregister(&n->primary_= listener);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 remove_migration_state_change_notifier(&n-= >migration_state);
+=C2=A0 =C2=A0 } else {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 assert(n->primary_opts =3D=3D NULL);
+=C2=A0 =C2=A0 }
+
+=C2=A0 =C2=A0 max_queue_pairs =3D n->multiqueue ? n->max_queue_pairs= : 1;
+=C2=A0 =C2=A0 for (i =3D 0; i < max_queue_pairs; i++) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 virtio_net_del_queue(n, i);
+=C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 /* delete also control vq */
+=C2=A0 =C2=A0 virtio_del_queue(vdev, max_queue_pairs * 2);
+=C2=A0 =C2=A0 qemu_announce_timer_del(&n->announce_timer, false); +=C2=A0 =C2=A0 g_free(n->vqs);
+=C2=A0 =C2=A0 qemu_del_nic(n->nic);
+=C2=A0 =C2=A0 virtio_net_rsc_cleanup(n);
+=C2=A0 =C2=A0 g_free(n->rss_data.indirections_table);
+=C2=A0 =C2=A0 net_rx_pkt_uninit(n->rx_pkt);
+=C2=A0 =C2=A0 virtio_cleanup(vdev);
+}
+
=C2=A0static void virtio_net_device_realize(DeviceState *dev, Error **errp)=
=C2=A0{
=C2=A0 =C2=A0 =C2=A0VirtIODevice *vdev =3D VIRTIO_DEVICE(dev);
@@ -3685,53 +3720,16 @@ static void virtio_net_device_realize(DeviceState *= dev, Error **errp)

=C2=A0 =C2=A0 =C2=A0net_rx_pkt_init(&n->rx_pkt);

-=C2=A0 =C2=A0 if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS= )) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 virtio_net_load_ebpf(n);
-=C2=A0 =C2=A0 }
-}
-
-static void virtio_net_device_unrealize(DeviceState *dev)
-{
-=C2=A0 =C2=A0 VirtIODevice *vdev =3D VIRTIO_DEVICE(dev);
-=C2=A0 =C2=A0 VirtIONet *n =3D VIRTIO_NET(dev);
-=C2=A0 =C2=A0 int i, max_queue_pairs;
-
-=C2=A0 =C2=A0 if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS= )) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 virtio_net_unload_ebpf(n);
-=C2=A0 =C2=A0 }
-
-=C2=A0 =C2=A0 /* This will stop vhost backend if appropriate. */
-=C2=A0 =C2=A0 virtio_net_set_status(vdev, 0);
-
-=C2=A0 =C2=A0 g_free(n->netclient_name);
-=C2=A0 =C2=A0 n->netclient_name =3D NULL;
-=C2=A0 =C2=A0 g_free(n->netclient_type);
-=C2=A0 =C2=A0 n->netclient_type =3D NULL;
-
-=C2=A0 =C2=A0 g_free(n->mac_table.macs);
-=C2=A0 =C2=A0 g_free(n->vlans);
-
-=C2=A0 =C2=A0 if (n->failover) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 qobject_unref(n->primary_opts);
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 device_listener_unregister(&n->primary_= listener);
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 remove_migration_state_change_notifier(&n-= >migration_state);
-=C2=A0 =C2=A0 } else {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 assert(n->primary_opts =3D=3D NULL);
-=C2=A0 =C2=A0 }
+=C2=A0 =C2=A0 if (virtio_has_feature(n->host_features, VIRTIO_NET_F_RSS= ) &&
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 !virtio_net_load_ebpf(n)) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (get_vhost_net(nc->peer)) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 error_setg(errp, "Can't= load eBPF RSS for vhost");
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 virtio_net_device_unrealize(dev)= ;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return;
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

-=C2=A0 =C2=A0 max_queue_pairs =3D n->multiqueue ? n->max_queue_pairs= : 1;
-=C2=A0 =C2=A0 for (i =3D 0; i < max_queue_pairs; i++) {
-=C2=A0 =C2=A0 =C2=A0 =C2=A0 virtio_net_del_queue(n, i);
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 warn_report_once("Can't load eBPF RSS= - fallback to software RSS");
=C2=A0 =C2=A0 =C2=A0}
-=C2=A0 =C2=A0 /* delete also control vq */
-=C2=A0 =C2=A0 virtio_del_queue(vdev, max_queue_pairs * 2);
-=C2=A0 =C2=A0 qemu_announce_timer_del(&n->announce_timer, false); -=C2=A0 =C2=A0 g_free(n->vqs);
-=C2=A0 =C2=A0 qemu_del_nic(n->nic);
-=C2=A0 =C2=A0 virtio_net_rsc_cleanup(n);
-=C2=A0 =C2=A0 g_free(n->rss_data.indirections_table);
-=C2=A0 =C2=A0 net_rx_pkt_uninit(n->rx_pkt);
-=C2=A0 =C2=A0 virtio_cleanup(vdev);
=C2=A0}

=C2=A0static void virtio_net_reset(VirtIODevice *vdev)
--
2.42.0

--000000000000abfab00608e244e6--