The set_offload() argument list is already pretty long and
we are going to introduce soon a bunch of additional offloads.
Replace the offload arguments with a single struct and update
all the relevant call-sites.
No functional changes intended.
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
Note: I maintained the struct usage as opposed to uint64_t bitmask usage
as suggested by Akihiko, because the latter feel a bit more invasive.
v1 -> v2:
- drop unneeded 'struct' keywords
- moved to series start
---
hw/net/e1000e_core.c | 5 +++--
hw/net/igb_core.c | 5 +++--
hw/net/virtio-net.c | 19 +++++++++++--------
hw/net/vmxnet3.c | 13 +++++--------
include/net/net.h | 15 ++++++++++++---
net/net.c | 5 ++---
net/netmap.c | 3 +--
net/tap-bsd.c | 3 +--
net/tap-linux.c | 21 ++++++++++++---------
net/tap-solaris.c | 4 ++--
net/tap-stub.c | 3 +--
net/tap.c | 8 ++++----
net/tap_int.h | 4 ++--
13 files changed, 59 insertions(+), 49 deletions(-)
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 2413858790..27599a0dc2 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -2827,8 +2827,9 @@ e1000e_update_rx_offloads(E1000ECore *core)
trace_e1000e_rx_set_cso(cso_state);
if (core->has_vnet) {
- qemu_set_offload(qemu_get_queue(core->owner_nic)->peer,
- cso_state, 0, 0, 0, 0, 0, 0);
+ NetOffloads ol = {.csum = cso_state };
+
+ qemu_set_offload(qemu_get_queue(core->owner_nic)->peer, &ol);
}
}
diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c
index 39e3ce1c8f..45d8fd795b 100644
--- a/hw/net/igb_core.c
+++ b/hw/net/igb_core.c
@@ -3058,8 +3058,9 @@ igb_update_rx_offloads(IGBCore *core)
trace_e1000e_rx_set_cso(cso_state);
if (core->has_vnet) {
- qemu_set_offload(qemu_get_queue(core->owner_nic)->peer,
- cso_state, 0, 0, 0, 0, 0, 0);
+ NetOffloads ol = {.csum = cso_state };
+
+ qemu_set_offload(qemu_get_queue(core->owner_nic)->peer, &ol);
}
}
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index eb93607b8c..16df9e85c8 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -842,14 +842,17 @@ static uint64_t virtio_net_bad_features(VirtIODevice *vdev)
static void virtio_net_apply_guest_offloads(VirtIONet *n)
{
- qemu_set_offload(qemu_get_queue(n->nic)->peer,
- !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_CSUM)),
- !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO4)),
- !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO6)),
- !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_ECN)),
- !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_UFO)),
- !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_USO4)),
- !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_USO6)));
+ NetOffloads ol = {
+ .csum = !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_CSUM)),
+ .tso4 = !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO4)),
+ .tso6 = !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO6)),
+ .ecn = !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_ECN)),
+ .ufo = !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_UFO)),
+ .uso4 = !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_USO4)),
+ .uso6 = !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_USO6)),
+ };
+
+ qemu_set_offload(qemu_get_queue(n->nic)->peer, &ol);
}
static uint64_t virtio_net_guest_offloads_by_features(uint64_t features)
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 7c0ca56b7c..57e457e758 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -1323,14 +1323,11 @@ static void vmxnet3_update_features(VMXNET3State *s)
s->lro_supported, rxcso_supported,
s->rx_vlan_stripping);
if (s->peer_has_vhdr) {
- qemu_set_offload(qemu_get_queue(s->nic)->peer,
- rxcso_supported,
- s->lro_supported,
- s->lro_supported,
- 0,
- 0,
- 0,
- 0);
+ NetOffloads ol = { .csum = rxcso_supported,
+ .tso4 = s->lro_supported,
+ .tso6 = s->lro_supported };
+
+ qemu_set_offload(qemu_get_queue(s->nic)->peer, &ol);
}
}
diff --git a/include/net/net.h b/include/net/net.h
index cdd5b109b0..5edea7671a 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -35,6 +35,16 @@ typedef struct NICConf {
int32_t bootindex;
} NICConf;
+typedef struct NetOffloads {
+ bool csum;
+ bool tso4;
+ bool tso6;
+ bool ecn;
+ bool ufo;
+ bool uso4;
+ bool uso6;
+} NetOffloads;
+
#define DEFINE_NIC_PROPERTIES(_state, _conf) \
DEFINE_PROP_MACADDR("mac", _state, _conf.macaddr), \
DEFINE_PROP_NETDEV("netdev", _state, _conf.peers)
@@ -57,7 +67,7 @@ typedef bool (HasUfo)(NetClientState *);
typedef bool (HasUso)(NetClientState *);
typedef bool (HasVnetHdr)(NetClientState *);
typedef bool (HasVnetHdrLen)(NetClientState *, int);
-typedef void (SetOffload)(NetClientState *, int, int, int, int, int, int, int);
+typedef void (SetOffload)(NetClientState *, const NetOffloads *);
typedef int (GetVnetHdrLen)(NetClientState *);
typedef void (SetVnetHdrLen)(NetClientState *, int);
typedef int (SetVnetLE)(NetClientState *, bool);
@@ -185,8 +195,7 @@ bool qemu_has_ufo(NetClientState *nc);
bool qemu_has_uso(NetClientState *nc);
bool qemu_has_vnet_hdr(NetClientState *nc);
bool qemu_has_vnet_hdr_len(NetClientState *nc, int len);
-void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
- int ecn, int ufo, int uso4, int uso6);
+void qemu_set_offload(NetClientState *nc, const NetOffloads *ol);
int qemu_get_vnet_hdr_len(NetClientState *nc);
void qemu_set_vnet_hdr_len(NetClientState *nc, int len);
int qemu_set_vnet_le(NetClientState *nc, bool is_le);
diff --git a/net/net.c b/net/net.c
index 39d6f28158..053db7c314 100644
--- a/net/net.c
+++ b/net/net.c
@@ -540,14 +540,13 @@ bool qemu_has_vnet_hdr_len(NetClientState *nc, int len)
return nc->info->has_vnet_hdr_len(nc, len);
}
-void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
- int ecn, int ufo, int uso4, int uso6)
+void qemu_set_offload(NetClientState *nc, const NetOffloads *ol)
{
if (!nc || !nc->info->set_offload) {
return;
}
- nc->info->set_offload(nc, csum, tso4, tso6, ecn, ufo, uso4, uso6);
+ nc->info->set_offload(nc, ol);
}
int qemu_get_vnet_hdr_len(NetClientState *nc)
diff --git a/net/netmap.c b/net/netmap.c
index 297510e190..6cd8f2bdc5 100644
--- a/net/netmap.c
+++ b/net/netmap.c
@@ -366,8 +366,7 @@ static void netmap_set_vnet_hdr_len(NetClientState *nc, int len)
}
}
-static void netmap_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
- int ecn, int ufo, int uso4, int uso6)
+static void netmap_set_offload(NetClientState *nc, const NetOffloads *ol)
{
NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
diff --git a/net/tap-bsd.c b/net/tap-bsd.c
index b4c84441ba..86b6edee94 100644
--- a/net/tap-bsd.c
+++ b/net/tap-bsd.c
@@ -231,8 +231,7 @@ int tap_fd_set_vnet_be(int fd, int is_be)
return -EINVAL;
}
-void tap_fd_set_offload(int fd, int csum, int tso4,
- int tso6, int ecn, int ufo, int uso4, int uso6)
+void tap_fd_set_offload(int fd, const NetOffloads *ol)
{
}
diff --git a/net/tap-linux.c b/net/tap-linux.c
index 22ec2f45d2..a1c58f74f5 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -239,8 +239,7 @@ int tap_fd_set_vnet_be(int fd, int is_be)
abort();
}
-void tap_fd_set_offload(int fd, int csum, int tso4,
- int tso6, int ecn, int ufo, int uso4, int uso6)
+void tap_fd_set_offload(int fd, const NetOffloads *ol)
{
unsigned int offload = 0;
@@ -249,20 +248,24 @@ void tap_fd_set_offload(int fd, int csum, int tso4,
return;
}
- if (csum) {
+ if (ol->csum) {
offload |= TUN_F_CSUM;
- if (tso4)
+ if (ol->tso4) {
offload |= TUN_F_TSO4;
- if (tso6)
+ }
+ if (ol->tso6) {
offload |= TUN_F_TSO6;
- if ((tso4 || tso6) && ecn)
+ }
+ if ((ol->tso4 || ol->tso6) && ol->ecn) {
offload |= TUN_F_TSO_ECN;
- if (ufo)
+ }
+ if (ol->ufo) {
offload |= TUN_F_UFO;
- if (uso4) {
+ }
+ if (ol->uso4) {
offload |= TUN_F_USO4;
}
- if (uso6) {
+ if (ol->uso6) {
offload |= TUN_F_USO6;
}
}
diff --git a/net/tap-solaris.c b/net/tap-solaris.c
index 51b7830bef..833c066bee 100644
--- a/net/tap-solaris.c
+++ b/net/tap-solaris.c
@@ -27,6 +27,7 @@
#include "tap_int.h"
#include "qemu/ctype.h"
#include "qemu/cutils.h"
+#include "net/net.h"
#include <sys/ethernet.h>
#include <sys/sockio.h>
@@ -235,8 +236,7 @@ int tap_fd_set_vnet_be(int fd, int is_be)
return -EINVAL;
}
-void tap_fd_set_offload(int fd, int csum, int tso4,
- int tso6, int ecn, int ufo, int uso4, int uso6)
+void tap_fd_set_offload(int fd, const NetOffloads *ol)
{
}
diff --git a/net/tap-stub.c b/net/tap-stub.c
index 38673434cb..67d14ad4d5 100644
--- a/net/tap-stub.c
+++ b/net/tap-stub.c
@@ -66,8 +66,7 @@ int tap_fd_set_vnet_be(int fd, int is_be)
return -EINVAL;
}
-void tap_fd_set_offload(int fd, int csum, int tso4,
- int tso6, int ecn, int ufo, int uso4, int uso6)
+void tap_fd_set_offload(int fd, const NetOffloads *ol)
{
}
diff --git a/net/tap.c b/net/tap.c
index ae1c7e3983..13e19130ce 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -262,15 +262,14 @@ static int tap_set_vnet_be(NetClientState *nc, bool is_be)
return tap_fd_set_vnet_be(s->fd, is_be);
}
-static void tap_set_offload(NetClientState *nc, int csum, int tso4,
- int tso6, int ecn, int ufo, int uso4, int uso6)
+static void tap_set_offload(NetClientState *nc, const NetOffloads *ol)
{
TAPState *s = DO_UPCAST(TAPState, nc, nc);
if (s->fd < 0) {
return;
}
- tap_fd_set_offload(s->fd, csum, tso4, tso6, ecn, ufo, uso4, uso6);
+ tap_fd_set_offload(s->fd, ol);
}
static void tap_exit_notify(Notifier *notifier, void *data)
@@ -355,6 +354,7 @@ static TAPState *net_tap_fd_init(NetClientState *peer,
int fd,
int vnet_hdr)
{
+ NetOffloads ol = {};
NetClientState *nc;
TAPState *s;
@@ -368,7 +368,7 @@ static TAPState *net_tap_fd_init(NetClientState *peer,
s->has_ufo = tap_probe_has_ufo(s->fd);
s->has_uso = tap_probe_has_uso(s->fd);
s->enabled = true;
- tap_set_offload(&s->nc, 0, 0, 0, 0, 0, 0, 0);
+ tap_set_offload(&s->nc, &ol);
/*
* Make sure host header length is set correctly in tap:
* it might have been modified by another instance of qemu.
diff --git a/net/tap_int.h b/net/tap_int.h
index 8857ff299d..f8bbe1cb0c 100644
--- a/net/tap_int.h
+++ b/net/tap_int.h
@@ -27,6 +27,7 @@
#define NET_TAP_INT_H
#include "qapi/qapi-types-net.h"
+#include "net/net.h"
int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
int vnet_hdr_required, int mq_required, Error **errp);
@@ -37,8 +38,7 @@ void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp);
int tap_probe_vnet_hdr(int fd, Error **errp);
int tap_probe_has_ufo(int fd);
int tap_probe_has_uso(int fd);
-void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo,
- int uso4, int uso6);
+void tap_fd_set_offload(int fd, const NetOffloads *ol);
void tap_fd_set_vnet_hdr_len(int fd, int len);
int tap_fd_set_vnet_le(int fd, int vnet_is_le);
int tap_fd_set_vnet_be(int fd, int vnet_is_be);
--
2.50.0
On 2025/07/11 22:02, Paolo Abeni wrote: > The set_offload() argument list is already pretty long and > we are going to introduce soon a bunch of additional offloads. > > Replace the offload arguments with a single struct and update > all the relevant call-sites. > > No functional changes intended. > > Signed-off-by: Paolo Abeni <pabeni@redhat.com> > --- > Note: I maintained the struct usage as opposed to uint64_t bitmask usage > as suggested by Akihiko, because the latter feel a bit more invasive. I think a bitmask will be invasive to the same extent with the current version; most part of this change comes from the parameter passing, which does not depend on the representation of the parameter.
On 7/15/25 8:36 AM, Akihiko Odaki wrote: > On 2025/07/11 22:02, Paolo Abeni wrote: >> The set_offload() argument list is already pretty long and >> we are going to introduce soon a bunch of additional offloads. >> >> Replace the offload arguments with a single struct and update >> all the relevant call-sites. >> >> No functional changes intended. >> >> Signed-off-by: Paolo Abeni <pabeni@redhat.com> >> --- >> Note: I maintained the struct usage as opposed to uint64_t bitmask usage >> as suggested by Akihiko, because the latter feel a bit more invasive. > > I think a bitmask will be invasive to the same extent with the current > version; most part of this change comes from the parameter passing, > which does not depend on the representation of the parameter. Do you have strong feeling WRT the bitmask usage? Another argument vs the bitmask usage is that it will requires some extra input validation of the selected offload bits (most of them don't make sense in this context). Thanks, Paolo
On 2025/07/15 23:52, Paolo Abeni wrote: > On 7/15/25 8:36 AM, Akihiko Odaki wrote: >> On 2025/07/11 22:02, Paolo Abeni wrote: >>> The set_offload() argument list is already pretty long and >>> we are going to introduce soon a bunch of additional offloads. >>> >>> Replace the offload arguments with a single struct and update >>> all the relevant call-sites. >>> >>> No functional changes intended. >>> >>> Signed-off-by: Paolo Abeni <pabeni@redhat.com> >>> --- >>> Note: I maintained the struct usage as opposed to uint64_t bitmask usage >>> as suggested by Akihiko, because the latter feel a bit more invasive. >> >> I think a bitmask will be invasive to the same extent with the current >> version; most part of this change comes from the parameter passing, >> which does not depend on the representation of the parameter. > > Do you have strong feeling WRT the bitmask usage? > > Another argument vs the bitmask usage is that it will requires some > extra input validation of the selected offload bits (most of them don't > make sense in this context). I don't think such a validation is necessary. There is practically no chance to have a wrong bit set by mistake when callers specify bits with macros prefixed with VIRTIO_NET_O_GUEST_. There will be a compilation error if the caller specify a offload bit that doesn't exist. It is also obvious if a caller specified something unrelated (i.e., not prefixed with VIRTIO_NET_O_GUEST_). A real downside here would be that we will need to type VIRTIO_NET_O_GUEST_ each time referring an offload bit; such a redundancy does not exist with struct because the type system knows the bits bound to the type. That said, 1) I prefer bitmasks much over struct though 2) I will be in favor of merging this series if everything else gets sorted out while the struct remains. I'll explain the reason for 1) first: There are both a downside and an upside with bitmasks. The downside is the redundancy of syntax, which I have just pointed out. The upside is the consistency with virtio's offload configuration, which defines the functionality of set_offload(). I consider the following two factors in such a trade-off scenario: a) The balance between the downside and upside b) Prior examples in the code base Regarding a), I think the upside outweighs the downside but its extent is small. b) matters more for this particular case; there are bunch of examples that use bitmasks in "include", excluding "include/hw" but there are none of structs that are dedicated for bools. Consistency matters for a big code base like QEMU so I want a good reason when making an exception. The reasoning behind 2) is that having this patch is still better than the status quo. Regards, Akihiko Odaki
© 2016 - 2025 Red Hat, Inc.