On Sun, 01 Nov 2026 15:46:24 +0100,
Brad Smith <[email protected]> wrote:
>
> Here is an update to QEMU 11.1.3.
>
> Add QEMU guest agent patches for OpenBSD:
> - guest-get-users support
> - guest-network-get-route support
> - guest-get-diskstats support
> - don't try to run the Linux hwclock(8) from guest-set-time on
> non-Linux systems
>
Thanks, commited
>
> Index: Makefile
> ===================================================================
> RCS file: /cvs/ports/emulators/qemu/Makefile,v
> retrieving revision 1.269
> diff -u -p -u -p -r1.269 Makefile
> --- Makefile 24 Oct 2026 22:55:20 -0000 1.269
> +++ Makefile 1 Nov 2026 14:37:09 -0000
> @@ -6,9 +6,8 @@ USE_NOBTCFI= Yes
> COMMENT-main= multi system emulator
> COMMENT-ga= QEMU guest agent
>
> -VERSION= 11.1.1
> +VERSION= 11.1.3
> DISTNAME= qemu-${VERSION}
> -REVISION= 2
> CATEGORIES= emulators
> SITES= https://download.qemu.org/
> EXTRACT_SUFX= .tar.xz
> Index: distinfo
> ===================================================================
> RCS file: /cvs/ports/emulators/qemu/distinfo,v
> retrieving revision 1.89
> diff -u -p -u -p -r1.89 distinfo
> --- distinfo 3 Sep 2026 08:58:14 -0000 1.89
> +++ distinfo 1 Nov 2026 14:37:09 -0000
> @@ -1,2 +1,2 @@
> -SHA256 (qemu-11.1.1.tar.xz) = B5/7/4pxEbvIkCIQfLq/O7/WFNX8nXzGdZkRlqyhJII=
> -SIZE (qemu-11.1.1.tar.xz) = 141888716
> +SHA256 (qemu-11.1.3.tar.xz) = WoKJx5QNx304c8gabCm6Ov4URvydNud/oWWM2+y4SyI=
> +SIZE (qemu-11.1.3.tar.xz) = 141819712
> Index: patches/patch-hw_usb_hcd-xhci_c
> ===================================================================
> RCS file: /cvs/ports/emulators/qemu/patches/patch-hw_usb_hcd-xhci_c,v
> retrieving revision 1.1
> diff -u -p -u -p -r1.1 patch-hw_usb_hcd-xhci_c
> --- patches/patch-hw_usb_hcd-xhci_c 20 Aug 2026 08:46:20 -0000 1.1
> +++ patches/patch-hw_usb_hcd-xhci_c 1 Nov 2026 14:37:09 -0000
> @@ -24,7 +24,7 @@ Index: hw/usb/hcd-xhci.c
> static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v);
> static USBEndpoint *xhci_epid_to_usbep(XHCIEPContext *epctx);
>
> -@@ -602,6 +608,304 @@ static inline int xhci_running(XHCIState *xhci)
> +@@ -608,6 +614,304 @@ static inline int xhci_running(XHCIState *xhci)
> return !(xhci->usbsts & USBSTS_HCH);
> }
>
> @@ -329,7 +329,7 @@ Index: hw/usb/hcd-xhci.c
> static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v)
> {
> XHCIInterrupter *intr = &xhci->intr[v];
> -@@ -636,7 +940,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEven
> +@@ -643,7 +947,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEven
> }
> }
>
> @@ -338,7 +338,7 @@ Index: hw/usb/hcd-xhci.c
> {
> XHCIInterrupter *intr;
> dma_addr_t erdp;
> -@@ -649,10 +953,15 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *eve
> +@@ -656,10 +960,15 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *eve
>
> if (v >= xhci->numintrs) {
> DPRINTF("intr nr out of range (%d >= %d)\n", v, xhci->numintrs);
> @@ -355,7 +355,7 @@ Index: hw/usb/hcd-xhci.c
> erdp = xhci_addr64(intr->erdp_low, intr->erdp_high);
> if (erdp < intr->er_start ||
> erdp >= (intr->er_start + TRB_SIZE*intr->er_size)) {
> -@@ -660,25 +969,86 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *eve
> +@@ -667,25 +976,86 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *eve
> DPRINTF("xhci: ER[%d] at "DMA_ADDR_FMT" len %d\n",
> v, intr->er_start, intr->er_size);
> xhci_die(xhci);
> @@ -448,7 +448,7 @@ Index: hw/usb/hcd-xhci.c
> static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring,
> dma_addr_t base)
> {
> -@@ -802,6 +1172,7 @@ static void xhci_er_reset(XHCIState *xhci, int v)
> +@@ -809,6 +1179,7 @@ static void xhci_er_reset(XHCIState *xhci, int v)
> XHCIInterrupter *intr = &xhci->intr[v];
> XHCIEvRingSeg seg;
> dma_addr_t erstba = xhci_addr64(intr->erstba_low, intr->erstba_high);
> @@ -456,7 +456,7 @@ Index: hw/usb/hcd-xhci.c
>
> if (intr->erstsz == 0 || erstba == 0) {
> /* disabled */
> -@@ -839,13 +1210,25 @@ static void xhci_er_reset(XHCIState *xhci, int v)
> +@@ -846,13 +1217,25 @@ static void xhci_er_reset(XHCIState *xhci, int v)
>
> DPRINTF("xhci: event ring[%d]:" DMA_ADDR_FMT " [%d]\n",
> v, intr->er_start, intr->er_size);
> @@ -482,7 +482,7 @@ Index: hw/usb/hcd-xhci.c
> }
>
> static void xhci_stop(XHCIState *xhci)
> -@@ -853,6 +1236,7 @@ static void xhci_stop(XHCIState *xhci)
> +@@ -860,6 +1243,7 @@ static void xhci_stop(XHCIState *xhci)
> trace_usb_xhci_stop();
> xhci->usbsts |= USBSTS_HCH;
> xhci->crcr_low &= ~CRCR_CRR;
> @@ -490,7 +490,7 @@ Index: hw/usb/hcd-xhci.c
> }
>
> static XHCIStreamContext *xhci_alloc_stream_contexts(unsigned count,
> -@@ -1287,6 +1671,7 @@ static TRBCCode xhci_disable_ep(XHCIState *xhci, unsig
> +@@ -1301,6 +1685,7 @@ static TRBCCode xhci_disable_ep(XHCIState *xhci, unsig
> return CC_SUCCESS;
> }
>
> @@ -498,7 +498,7 @@ Index: hw/usb/hcd-xhci.c
> xhci_ep_nuke_xfers(xhci, slotid, epid, 0);
>
> epctx = slot->eps[epid-1];
> -@@ -1328,6 +1713,7 @@ static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned
> +@@ -1342,6 +1727,7 @@ static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned
> return CC_EP_NOT_ENABLED_ERROR;
> }
>
> @@ -506,7 +506,7 @@ Index: hw/usb/hcd-xhci.c
> if (xhci_ep_nuke_xfers(xhci, slotid, epid, CC_STOPPED) > 0) {
> DPRINTF("xhci: FIXME: endpoint stopped w/ xfers running, "
> "data might be lost\n");
> -@@ -1373,6 +1759,7 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigne
> +@@ -1387,6 +1773,7 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigne
> return CC_CONTEXT_STATE_ERROR;
> }
>
> @@ -514,7 +514,7 @@ Index: hw/usb/hcd-xhci.c
> if (xhci_ep_nuke_xfers(xhci, slotid, epid, 0) > 0) {
> DPRINTF("xhci: FIXME: endpoint reset w/ xfers running, "
> "data might be lost\n");
> -@@ -1893,6 +2280,11 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsi
> +@@ -1905,6 +2292,11 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsi
> trace_usb_xhci_ep_kick(epctx->slotid, epctx->epid, streamid);
> assert(!epctx->kick_active);
>
> @@ -526,7 +526,7 @@ Index: hw/usb/hcd-xhci.c
> /* If the device has been detached, but the guest has not noticed this
> yet the 2 above checks will succeed, but we must NOT continue */
> if (!xhci_slot_ok(xhci, epctx->slotid)) {
> -@@ -1943,6 +2335,11 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsi
> +@@ -1944,6 +2336,11 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsi
> epctx->retry = NULL;
> }
>
> @@ -538,7 +538,7 @@ Index: hw/usb/hcd-xhci.c
> if (epctx->state == EP_HALTED) {
> DPRINTF("xhci: ep halted, not running schedule\n");
> return;
> -@@ -2015,6 +2412,11 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsi
> +@@ -2016,6 +2413,11 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsi
> xfer = NULL;
> }
>
> @@ -550,7 +550,7 @@ Index: hw/usb/hcd-xhci.c
> if (epctx->state == EP_HALTED) {
> break;
> }
> -@@ -2490,6 +2892,9 @@ static void xhci_process_commands(XHCIState *xhci)
> +@@ -2492,6 +2894,9 @@ static void xhci_process_commands(XHCIState *xhci)
> }
>
> xhci->crcr_low |= CRCR_CRR;
> @@ -560,7 +560,7 @@ Index: hw/usb/hcd-xhci.c
>
> while ((type = xhci_ring_fetch(xhci, &xhci->cmd_ring, &trb, &addr))) {
> event.ptr = addr;
> -@@ -2600,7 +3005,9 @@ static void xhci_process_commands(XHCIState *xhci)
> +@@ -2602,7 +3007,9 @@ static void xhci_process_commands(XHCIState *xhci)
> break;
> }
> event.slotid = slotid;
> @@ -571,7 +571,7 @@ Index: hw/usb/hcd-xhci.c
>
> if (count++ > COMMAND_LIMIT) {
> trace_usb_xhci_enforced_limit("commands");
> -@@ -2716,6 +3123,8 @@ static void xhci_reset(DeviceState *dev)
> +@@ -2718,6 +3125,8 @@ static void xhci_reset(DeviceState *dev)
> xhci->dcbaap_low = 0;
> xhci->dcbaap_high = 0;
> xhci->config = 0;
> @@ -580,7 +580,7 @@ Index: hw/usb/hcd-xhci.c
>
> for (i = 0; i < xhci->numslots; i++) {
> xhci_disable_slot(xhci, i+1);
> -@@ -2736,6 +3145,11 @@ static void xhci_reset(DeviceState *dev)
> +@@ -2738,6 +3147,11 @@ static void xhci_reset(DeviceState *dev)
>
> xhci->intr[i].er_ep_idx = 0;
> xhci->intr[i].er_pcs = 1;
> @@ -592,7 +592,7 @@ Index: hw/usb/hcd-xhci.c
> xhci->intr[i].ev_buffer_put = 0;
> xhci->intr[i].ev_buffer_get = 0;
> }
> -@@ -3139,6 +3553,11 @@ static void xhci_runtime_write(void *ptr, hwaddr reg,
> +@@ -3141,6 +3555,11 @@ static void xhci_runtime_write(void *ptr, hwaddr reg,
> intr->erdp_low &= ~ERDP_EHB;
> }
> intr->erdp_low = (val & ~ERDP_EHB) | (intr->erdp_low & ERDP_EHB);
> @@ -604,7 +604,7 @@ Index: hw/usb/hcd-xhci.c
> if (val & ERDP_EHB) {
> dma_addr_t erdp = xhci_addr64(intr->erdp_low, intr->erdp_high);
> unsigned int dp_idx = (erdp - intr->er_start) / TRB_SIZE;
> -@@ -3151,6 +3570,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg,
> +@@ -3153,6 +3572,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg,
> break;
> case 0x1c: /* ERDP high */
> intr->erdp_high = val;
> @@ -612,7 +612,7 @@ Index: hw/usb/hcd-xhci.c
> break;
> default:
> trace_usb_xhci_unimplemented("oper write", reg);
> -@@ -3425,6 +3845,15 @@ static void usb_xhci_realize(DeviceState *dev, Error *
> +@@ -3454,6 +3874,15 @@ static void usb_xhci_realize(DeviceState *dev, Error *
> if (xhci->numslots < 1) {
> xhci->numslots = 1;
> }
> @@ -628,7 +628,7 @@ Index: hw/usb/hcd-xhci.c
> if (xhci_get_flag(xhci, XHCI_FLAG_ENABLE_STREAMS)) {
> xhci->max_pstreams_mask = 7; /* == 256 primary streams */
> } else {
> -@@ -3470,6 +3899,14 @@ static void usb_xhci_unrealize(DeviceState *dev)
> +@@ -3499,6 +3928,14 @@ static void usb_xhci_unrealize(DeviceState *dev)
> xhci_disable_slot(xhci, i + 1);
> }
>
> @@ -643,7 +643,7 @@ Index: hw/usb/hcd-xhci.c
> if (xhci->mfwrap_timer) {
> timer_free(xhci->mfwrap_timer);
> xhci->mfwrap_timer = NULL;
> -@@ -3488,17 +3925,70 @@ static void usb_xhci_unrealize(DeviceState *dev)
> +@@ -3517,17 +3954,70 @@ static void usb_xhci_unrealize(DeviceState *dev)
> usb_bus_release(&xhci->bus);
> }
>
> @@ -715,7 +715,7 @@ Index: hw/usb/hcd-xhci.c
> dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
>
> for (slotid = 1; slotid <= xhci->numslots; slotid++) {
> -@@ -3531,11 +4021,19 @@ static int usb_xhci_post_load(void *opaque, int
> versio
> +@@ -3560,11 +4050,19 @@ static int usb_xhci_post_load(void *opaque, int
> versio
> xhci_init_epctx(epctx, pctx, ep_ctx);
> epctx->state = state;
> if (state == EP_RUNNING) {
> @@ -737,7 +737,7 @@ Index: hw/usb/hcd-xhci.c
> return 0;
> }
>
> -@@ -3583,6 +4081,38 @@ static const VMStateDescription vmstate_xhci_event = {
> +@@ -3612,6 +4110,38 @@ static const VMStateDescription vmstate_xhci_event = {
> }
> };
>
> @@ -776,7 +776,7 @@ Index: hw/usb/hcd-xhci.c
> static bool xhci_er_full(void *opaque, int version_id)
> {
> return false;
> -@@ -3617,12 +4147,37 @@ static const VMStateDescription vmstate_xhci_intr = {
> +@@ -3646,12 +4176,37 @@ static const VMStateDescription vmstate_xhci_intr = {
> vmstate_xhci_event, XHCIEvent),
>
> VMSTATE_END_OF_LIST()
> @@ -814,7 +814,7 @@ Index: hw/usb/hcd-xhci.c
> .post_load = usb_xhci_post_load,
> .fields = (const VMStateField[]) {
> VMSTATE_STRUCT_VARRAY_UINT32(ports, XHCIState, numports, 1,
> -@@ -3648,6 +4203,10 @@ const VMStateDescription vmstate_xhci = {
> +@@ -3677,6 +4232,10 @@ const VMStateDescription vmstate_xhci = {
> VMSTATE_STRUCT(cmd_ring, XHCIState, 1, vmstate_xhci_ring, XHCIRing),
>
> VMSTATE_END_OF_LIST()
> Index: patches/patch-meson_build
> ===================================================================
> RCS file: /cvs/ports/emulators/qemu/patches/patch-meson_build,v
> retrieving revision 1.24
> diff -u -p -u -p -r1.24 patch-meson_build
> --- patches/patch-meson_build 21 Sep 2026 09:48:01 -0000 1.24
> +++ patches/patch-meson_build 1 Nov 2026 14:37:09 -0000
> @@ -1,4 +1,7 @@
> - util/cutils: Use getexecpath() on OpenBSD for qemu_init_exec_dir()
> +- qga: implement 'guest-network-get-route' for FreeBSD
> + 0ae3840f612ba00330940f26758ae03754f6c6b6
> +- qga: implement 'guest-get-users' for OpenBSD
>
> - localstatedir does not belong under prefix
> - remove hardcoding of optimization
> @@ -15,7 +18,28 @@ Index: meson.build
> config_host_data.set_quoted('CONFIG_QEMU_MODDIR', get_option('prefix') /
> qemu_moddir)
> config_host_data.set_quoted('CONFIG_SYSCONFDIR', get_option('prefix') /
> get_option('sysconfdir'))
>
> -@@ -3030,6 +3030,14 @@ config_host_data.set('CONFIG_ELF_AUX_INFO', cc.links(o
> +@@ -2433,6 +2433,7 @@ config_host_data.set('CONFIG_BDRV_WHITELIST_TOOLS', ge
> + config_host_data.set('CONFIG_BRLAPI', brlapi.found())
> + config_host_data.set('CONFIG_BSD', host_os in bsd_oses)
> + config_host_data.set('CONFIG_FREEBSD', host_os == 'freebsd')
> ++config_host_data.set('CONFIG_OPENBSD', host_os == 'openbsd')
> + config_host_data.set('CONFIG_CAPSTONE', capstone.found())
> + config_host_data.set('CONFIG_COCOA', cocoa.found())
> + config_host_data.set('CONFIG_DARWIN', host_os == 'darwin')
> +@@ -2755,6 +2756,12 @@ config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM',
> + config_host_data.set('HAVE_BLK_ZONE_REP_CAPACITY',
> + cc.has_member('struct blk_zone', 'capacity',
> + prefix: '#include <linux/blkzoned.h>'))
> ++config_host_data.set('HAVE_STRUCT_RT_METRICS_RMX_METRIC',
> ++ cc.has_member('struct rt_metrics', 'rmx_metric',
> ++ prefix: '''
> ++ #include <sys/types.h>
> ++ #include <sys/socket.h>
> ++ #include <net/route.h>'''))
> +
> + # has_type
> + config_host_data.set('CONFIG_IOVEC',
> +@@ -3030,6 +3037,14 @@ config_host_data.set('CONFIG_ELF_AUX_INFO', cc.links(o
> return hwcap;
> }'''))
>
> @@ -30,7 +54,7 @@ Index: meson.build
> config_host_data.set('CONFIG_USBFS', have_linux_user and cc.compiles('''
> #include <linux/usbdevice_fs.h>
>
> -@@ -4753,9 +4761,6 @@ if have_rust
> +@@ -4753,9 +4768,6 @@ if have_rust
> summary_info += {'bindgen version': bindgen.version()}
> endif
> option_cflags = (get_option('debug') ? ['-g'] : [])
> Index: patches/patch-qga_commands-bsd_c
> ===================================================================
> RCS file: /cvs/ports/emulators/qemu/patches/patch-qga_commands-bsd_c,v
> retrieving revision 1.5
> diff -u -p -u -p -r1.5 patch-qga_commands-bsd_c
> --- patches/patch-qga_commands-bsd_c 21 Sep 2026 09:48:01 -0000 1.5
> +++ patches/patch-qga_commands-bsd_c 1 Nov 2026 14:37:09 -0000
> @@ -1,16 +1,22 @@
> - qga: implement 'guest-get-fsinfo' for FreeBSD
> 2a454b5391ad4241c8d59d8325d8bacac9af7a8c
> - qga: implement 'guest-get-fsinfo' for NetBSD and OpenBSD
> + 6a24fc259da4b1efa8e53dc9a655d89474d270cc
> +- qga: implement 'guest-network-get-route' for FreeBSD
> + 0ae3840f612ba00330940f26758ae03754f6c6b6
> +- qga: implement 'guest-network-get-route' for NetBSD and OpenBSD
> +- qga: implement 'guest-get-diskstats' for OpenBSD
> - qga: implement 'guest-get-vcpus' for the BSDs
> +- qga: implement 'guest-get-users' for OpenBSD
>
> Index: qga/commands-bsd.c
> --- qga/commands-bsd.c.orig
> +++ qga/commands-bsd.c
> -@@ -13,13 +13,13 @@
> - #include "qemu/osdep.h"
> +@@ -14,12 +14,17 @@
> #include "qga-qapi-commands.h"
> #include "qapi/error.h"
> --#include "qemu/queue.h"
> + #include "qemu/queue.h"
> ++#include "block/block-common.h"
> #include "commands-common.h"
> #include <sys/ioctl.h>
> #include <sys/param.h>
> @@ -18,16 +24,25 @@ Index: qga/commands-bsd.c
> #include <sys/mount.h>
> #include <net/if_dl.h>
> +#include <sys/statvfs.h>
> ++#include <sys/sysctl.h>
> ++#include <net/route.h>
> ++#include <net/if.h>
> #if defined(__NetBSD__) || defined(__OpenBSD__)
> #include <net/if_arp.h>
> #include <netinet/if_ether.h>
> -@@ -27,12 +27,20 @@
> +@@ -27,12 +32,40 @@
> #include <net/ethernet.h>
> #endif
> #include <paths.h>
> +#ifdef __FreeBSD__
> +#include <ufs/ffs/fs.h>
> +#endif
> ++#ifdef __OpenBSD__
> ++#include <sys/sysctl.h>
> ++#include <sys/disk.h>
> ++#include <util.h>
> ++#include <utmp.h>
> ++#endif
>
> -#if defined(CONFIG_FSFREEZE) || defined(CONFIG_FSTRIM)
> +#ifdef __NetBSD__
> @@ -36,6 +51,20 @@ Index: qga/commands-bsd.c
> +typedef struct statfs bsd_fsinfo_t;
> +#endif
> +
> ++#if defined(__OpenBSD__)
> ++#define RT_FIRST_SA(rtm) \
> ++ ((struct sockaddr *)((char *)(rtm) + (rtm)->rtm_hdrlen))
> ++#define RT_SA_SIZE(sa) \
> ++ ((sa)->sa_len > 0 ? 1 + (((sa)->sa_len - 1) | (sizeof(long) - 1)) \
> ++ : sizeof(long))
> ++#elif defined(__NetBSD__)
> ++#define RT_FIRST_SA(rtm) ((struct sockaddr *)((rtm) + 1))
> ++#define RT_SA_SIZE(sa) RT_ROUNDUP((sa)->sa_len)
> ++#else /* FreeBSD, DragonFly */
> ++#define RT_FIRST_SA(rtm) ((struct sockaddr *)((rtm) + 1))
> ++#define RT_SA_SIZE(sa) SA_SIZE(sa)
> ++#endif
> ++
> bool build_fs_mount_list(FsMountList *mounts, Error **errp)
> {
> FsMount *mount;
> @@ -44,7 +73,7 @@ Index: qga/commands-bsd.c
> struct stat statbuf;
> int i, count, ret;
>
> -@@ -55,16 +63,18 @@ bool build_fs_mount_list(FsMountList *mounts, Error **
> +@@ -55,16 +88,18 @@ bool build_fs_mount_list(FsMountList *mounts, Error **
>
> mount->dirname = g_strdup(mntp->f_mntonname);
> mount->devtype = g_strdup(mntp->f_fstypename);
> @@ -65,7 +94,7 @@ Index: qga/commands-bsd.c
>
> #if defined(CONFIG_FSFREEZE)
> static int ufssuspend_fd = -1;
> -@@ -178,3 +188,79 @@ bool guest_get_hw_addr(struct ifaddrs *ifa, unsigned c
> +@@ -178,3 +213,461 @@ bool guest_get_hw_addr(struct ifaddrs *ifa, unsigned c
> return true;
> }
> #endif /* HAVE_GETIFADDRS */
> @@ -144,4 +173,386 @@ Index: qga/commands-bsd.c
> +
> + free_fs_mount_list(&mounts);
> + return ret;
> ++}
> ++
> ++#ifdef __OpenBSD__
> ++static uint64_t timeval_to_msec(const struct timeval *tv)
> ++{
> ++ return (uint64_t)tv->tv_sec * 1000ULL + tv->tv_usec / 1000;
> ++}
> ++
> ++static GuestDiskStatsInfo *
> ++guest_diskstats_info_new(const struct diskstats *ds, int rawpart)
> ++{
> ++ GuestDiskStatsInfo *diskstatinfo;
> ++ GuestDiskStats *diskstat;
> ++ struct stat st;
> ++
> ++ diskstatinfo = g_new0(GuestDiskStatsInfo, 1);
> ++ diskstatinfo->name = g_strndup(ds->ds_name, sizeof(ds->ds_name));
> ++
> ++ /*
> ++ * The kernel disk statistics carry no device numbers; take them
> ++ * from the raw partition device node, which covers the whole disk.
> ++ * If that node is missing (e.g. a minimal /dev), report 0.
> ++ */
> ++ if (rawpart >= 0) {
> ++ g_autofree char *devpath = g_strdup_printf(_PATH_DEV "%s%c",
> ++ diskstatinfo->name,
> ++ 'a' + rawpart);
> ++
> ++ if (stat(devpath, &st) == 0 && S_ISBLK(st.st_mode)) {
> ++ diskstatinfo->major = major(st.st_rdev);
> ++ diskstatinfo->minor = minor(st.st_rdev);
> ++ }
> ++ }
> ++
> ++ /*
> ++ * OpenBSD tracks transfer counts and bytes per direction, but busy
> ++ * time only in aggregate, and has no discard, flush or merge
> ++ * counters.
> ++ */
> ++ diskstat = g_new0(GuestDiskStats, 1);
> ++ diskstat->has_read_ios = true;
> ++ diskstat->read_ios = ds->ds_rxfer;
> ++ diskstat->has_read_sectors = true;
> ++ diskstat->read_sectors = ds->ds_rbytes / BDRV_SECTOR_SIZE;
> ++
> ++ diskstat->has_write_ios = true;
> ++ diskstat->write_ios = ds->ds_wxfer;
> ++ diskstat->has_write_sectors = true;
> ++ diskstat->write_sectors = ds->ds_wbytes / BDRV_SECTOR_SIZE;
> ++
> ++ if (ds->ds_busy >= 0) {
> ++ diskstat->has_ios_pgr = true;
> ++ diskstat->ios_pgr = ds->ds_busy;
> ++ }
> ++
> ++ diskstat->has_total_ticks = true;
> ++ diskstat->total_ticks = timeval_to_msec(&ds->ds_time);
> ++
> ++ diskstatinfo->stats = diskstat;
> ++ return diskstatinfo;
> ++}
> ++
> ++#define DISKSTATS_MAX_TRIES 5
> ++
> ++GuestDiskStatsInfoList *qmp_guest_get_diskstats(Error **errp)
> ++{
> ++ GuestDiskStatsInfoList *head = NULL, **tail = &head;
> ++ int mib[] = { CTL_HW, HW_DISKSTATS };
> ++ g_autofree struct diskstats *stats = NULL;
> ++ size_t len, i;
> ++ int rawpart = getrawpartition();
> ++ int tries;
> ++
> ++ /* Disks may attach or detach between the two sysctl calls; retry. */
> ++ for (tries = 0; tries < DISKSTATS_MAX_TRIES; tries++) {
> ++ if (sysctl(mib, ARRAY_SIZE(mib), NULL, &len, NULL, 0) == -1) {
> ++ error_setg_errno(errp, errno, "cannot get size of
> hw.diskstats");
> ++ return NULL;
> ++ }
> ++ if (len == 0) {
> ++ return NULL;
> ++ }
> ++ len += 4 * sizeof(struct diskstats);
> ++ g_free(stats);
> ++ stats = g_malloc(len);
> ++ if (sysctl(mib, ARRAY_SIZE(mib), stats, &len, NULL, 0) == 0) {
> ++ break;
> ++ }
> ++ if (errno != ENOMEM) {
> ++ error_setg_errno(errp, errno, "cannot read hw.diskstats");
> ++ return NULL;
> ++ }
> ++ }
> ++ if (tries == DISKSTATS_MAX_TRIES) {
> ++ error_setg(errp, "hw.diskstats keeps changing size");
> ++ return NULL;
> ++ }
> ++
> ++ for (i = 0; i < len / sizeof(struct diskstats); i++) {
> ++ QAPI_LIST_APPEND(tail, guest_diskstats_info_new(&stats[i],
> rawpart));
> ++ }
> ++
> ++ return head;
> ++}
> ++
> ++GuestUserList *qmp_guest_get_users(Error **errp)
> ++{
> ++ GHashTable *cache;
> ++ GuestUserList *head = NULL, **tail = &head;
> ++ struct utmp ut;
> ++ FILE *fp = NULL;
> ++
> ++ fp = fopen(_PATH_UTMP, "r");
> ++ if (!fp) {
> ++ error_setg_errno(errp, errno, "failed to open %s", _PATH_UTMP);
> ++ return NULL;
> ++ }
> ++
> ++ cache = g_hash_table_new(g_str_hash, g_str_equal);
> ++
> ++ while (fread(&ut, sizeof(ut), 1, fp) == 1) {
> ++ g_autofree char *name = NULL;
> ++ GuestUser *user;
> ++ double login_time;
> ++
> ++ /* logout(3) clears ut_name; skip empty slots like who(1) does */
> ++ if (ut.ut_name[0] == '\0' || ut.ut_line[0] == '\0') {
> ++ continue;
> ++ }
> ++
> ++ /* ut_name is not NUL-terminated if it fills UT_NAMESIZE */
> ++ name = g_strndup(ut.ut_name, sizeof(ut.ut_name));
> ++ login_time = (double)ut.ut_time;
> ++
> ++ user = g_hash_table_lookup(cache, name);
> ++ if (user) {
> ++ /* We're ensuring the earliest login time to be sent */
> ++ if (login_time < user->login_time) {
> ++ user->login_time = login_time;
> ++ }
> ++ continue;
> ++ }
> ++
> ++ user = g_new0(GuestUser, 1);
> ++ user->user = g_steal_pointer(&name);
> ++ user->login_time = login_time;
> ++
> ++ g_hash_table_insert(cache, user->user, user);
> ++ QAPI_LIST_APPEND(tail, user);
> ++ }
> ++
> ++ fclose(fp);
> ++ g_hash_table_destroy(cache);
> ++ return head;
> ++}
> ++#endif /* __OpenBSD__ */
> ++
> ++static void sockaddr_in6_normalize(const struct sockaddr *sa,
> ++ struct sockaddr_in6 *sin6)
> ++{
> ++ size_t len = MIN(sa->sa_len, sizeof(*sin6));
> ++
> ++ memset(sin6, 0, sizeof(*sin6));
> ++ memcpy(sin6, sa, len);
> ++
> ++ sin6->sin6_len = sizeof(*sin6);
> ++
> ++ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
> ++ (sin6->sin6_addr.s6_addr[0] == 0xff &&
> ++ ((sin6->sin6_addr.s6_addr[1] & 0x0f) == 1 ||
> ++ (sin6->sin6_addr.s6_addr[1] & 0x0f) == 2))) {
> ++ if (sin6->sin6_scope_id == 0) {
> ++ sin6->sin6_scope_id =
> ++ (sin6->sin6_addr.s6_addr[2] << 8) |
> ++ sin6->sin6_addr.s6_addr[3];
> ++ sin6->sin6_addr.s6_addr[2] = 0;
> ++ sin6->sin6_addr.s6_addr[3] = 0;
> ++ }
> ++ }
> ++}
> ++
> ++GuestNetworkRouteList *qmp_guest_network_get_route(Error **errp)
> ++{
> ++ GuestNetworkRouteList *head = NULL, **tail = &head;
> ++#ifdef __NetBSD__
> ++ int mib[] = { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_DUMP, 0 };
> ++#else
> ++ int mib[] = { CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_DUMP, 0, 0 };
> ++#endif
> ++ g_autofree char *buf = NULL;
> ++ size_t len;
> ++
> ++ if (sysctl(mib, ARRAY_SIZE(mib), NULL, &len, NULL, 0) == -1) {
> ++ error_setg_errno(errp, errno, "sysctl size");
> ++ return NULL;
> ++ }
> ++
> ++ buf = g_malloc0(len);
> ++
> ++ if (sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) == -1) {
> ++ error_setg_errno(errp, errno, "sysctl routes");
> ++ return NULL;
> ++ }
> ++
> ++ for (char *p = buf, *end = buf + len; p < end; ) {
> ++ struct rt_msghdr *rtm = (struct rt_msghdr *)p;
> ++ struct sockaddr *addresses[RTAX_MAX] = { NULL };
> ++ struct sockaddr *sa;
> ++ struct sockaddr_in6 sin6;
> ++ char destination[NI_MAXHOST];
> ++ char gateway[NI_MAXHOST];
> ++ char ifname[IFNAMSIZ];
> ++ const struct sockaddr *dst = NULL;
> ++ const struct sockaddr *gw = NULL;
> ++ const struct sockaddr *netmask = NULL;
> ++ const struct sockaddr *fmt_sa;
> ++ struct sockaddr_in normalized_mask = { 0 };
> ++ char netmask_buf[INET_ADDRSTRLEN];
> ++ socklen_t salen;
> ++
> ++ g_autoptr(GuestNetworkRoute) route = g_new0(GuestNetworkRoute, 1);
> ++
> ++ if ((size_t)(end - p) < sizeof(*rtm) ||
> ++ rtm->rtm_msglen < sizeof(*rtm) ||
> ++ rtm->rtm_msglen > (size_t)(end - p)) {
> ++ break;
> ++ }
> ++
> ++ p += rtm->rtm_msglen;
> ++
> ++ if (rtm->rtm_version != RTM_VERSION) {
> ++ continue;
> ++ }
> ++
> ++#if defined(RTF_LLINFO)
> ++ /* OpenBSD: skip ARP/NDP entries */
> ++ if (rtm->rtm_flags & RTF_LLINFO) {
> ++ continue;
> ++ }
> ++#elif defined(RTF_LLDATA)
> ++ /* NetBSD: skip ARP/NDP entries */
> ++ if (rtm->rtm_flags & RTF_LLDATA) {
> ++ continue;
> ++ }
> ++#endif
> ++
> ++ sa = RT_FIRST_SA(rtm);
> ++ for (int i = 0; i < RTAX_MAX; i++) {
> ++ if (rtm->rtm_addrs & (1U << i)) {
> ++ addresses[i] = sa;
> ++ sa = (struct sockaddr *)((char *)sa + RT_SA_SIZE(sa));
> ++ }
> ++ }
> ++
> ++ if (if_indextoname(rtm->rtm_index, ifname)) {
> ++ route->iface = g_strdup(ifname);
> ++ } else {
> ++ route->iface = g_strdup_printf("if%u", rtm->rtm_index);
> ++ }
> ++
> ++#if defined(HAVE_STRUCT_RT_METRICS_RMX_METRIC)
> ++ route->metric = rtm->rtm_rmx.rmx_metric;
> ++#endif
> ++
> ++ dst = addresses[RTAX_DST];
> ++ if (!dst) {
> ++ continue;
> ++ }
> ++
> ++ if (dst->sa_family == AF_INET) {
> ++ route->version = 4;
> ++ } else if (dst->sa_family == AF_INET6) {
> ++ route->version = 6;
> ++ } else {
> ++ continue;
> ++ }
> ++
> ++ fmt_sa = dst;
> ++ salen = dst->sa_len;
> ++ if (dst->sa_family == AF_INET6) {
> ++ sockaddr_in6_normalize(dst, &sin6);
> ++ fmt_sa = (struct sockaddr *)&sin6;
> ++ salen = sizeof(sin6);
> ++ }
> ++ if (getnameinfo(fmt_sa, salen,
> ++ destination, NI_MAXHOST,
> ++ NULL, 0, NI_NUMERICHOST) != 0) {
> ++ continue;
> ++ }
> ++ route->destination = g_strdup(destination);
> ++
> ++ gw = addresses[RTAX_GATEWAY];
> ++ if (gw && (gw->sa_family == AF_INET || gw->sa_family == AF_INET6)) {
> ++ fmt_sa = gw;
> ++ salen = gw->sa_len;
> ++ if (gw->sa_family == AF_INET6) {
> ++ sockaddr_in6_normalize(gw, &sin6);
> ++ fmt_sa = (struct sockaddr *)&sin6;
> ++ salen = sizeof(sin6);
> ++ }
> ++ if (getnameinfo(fmt_sa, salen, gateway,
> ++ NI_MAXHOST, NULL, 0,
> ++ NI_NUMERICHOST) != 0) {
> ++ continue;
> ++ }
> ++ if (gw->sa_family == AF_INET) {
> ++ route->gateway = g_strdup(gateway);
> ++ } else if (gw->sa_family == AF_INET6) {
> ++ route->nexthop = g_strdup(gateway);
> ++ }
> ++ }
> ++
> ++ netmask = addresses[RTAX_NETMASK];
> ++ if (dst->sa_family == AF_INET) {
> ++ if (netmask && netmask->sa_len != 0) {
> ++ memcpy(&normalized_mask, netmask,
> ++ MIN(netmask->sa_len, sizeof(normalized_mask)));
> ++ } else if (rtm->rtm_flags & RTF_HOST) {
> ++ normalized_mask.sin_addr.s_addr = 0xFFFFFFFF;
> ++ }
> ++
> ++ if (inet_ntop(AF_INET, &normalized_mask.sin_addr,
> ++ netmask_buf, sizeof(netmask_buf)) != NULL) {
> ++ route->mask = g_strdup(netmask_buf);
> ++ } else {
> ++ route->mask = NULL;
> ++ }
> ++ } else if (dst->sa_family == AF_INET6) {
> ++ struct sockaddr_in6 normalized_mask6;
> ++ memset(&normalized_mask6, 0, sizeof(normalized_mask6));
> ++
> ++ if (netmask && netmask->sa_len != 0) {
> ++ int prefix_len = 0;
> ++ bool valid_mask = true;
> ++ bool zero_found = false;
> ++
> ++ memcpy(&normalized_mask6, netmask,
> ++ MIN(netmask->sa_len, sizeof(normalized_mask6)));
> ++
> ++ for (int i = 0; i < sizeof(normalized_mask6.sin6_addr);
> i++) {
> ++ uint8_t byte = normalized_mask6.sin6_addr.s6_addr[i];
> ++ for (int bit = 7; bit >= 0; bit--) {
> ++ if ((byte >> bit) & 1) {
> ++ if (zero_found) {
> ++ valid_mask = false;
> ++ break;
> ++ }
> ++ prefix_len++;
> ++ } else {
> ++ zero_found = true;
> ++ }
> ++ }
> ++ if (!valid_mask) {
> ++ break;
> ++ }
> ++ }
> ++
> ++ if (valid_mask) {
> ++ route->desprefixlen = g_strdup_printf("%d", prefix_len);
> ++ } else {
> ++ route->desprefixlen = NULL;
> ++ }
> ++ } else if (rtm->rtm_flags & RTF_HOST) {
> ++ route->desprefixlen = g_strdup("128");
> ++ } else {
> ++ route->desprefixlen = g_strdup("0");
> ++ }
> ++ }
> ++
> ++ if (rtm->rtm_rmx.rmx_mtu) {
> ++ route->mtu = rtm->rtm_rmx.rmx_mtu;
> ++ route->has_mtu = true;
> ++ }
> ++
> ++ route->flags = (uint32_t)rtm->rtm_flags;
> ++ route->has_flags = true;
> ++
> ++ QAPI_LIST_APPEND(tail, route);
> ++ route = NULL;
> ++ }
> ++
> ++ return head;
> +}
> Index: patches/patch-qga_commands-common_h
> ===================================================================
> RCS file: /cvs/ports/emulators/qemu/patches/patch-qga_commands-common_h,v
> retrieving revision 1.1
> diff -u -p -u -p -r1.1 patch-qga_commands-common_h
> --- patches/patch-qga_commands-common_h 21 Sep 2026 09:48:01 -0000
> 1.1
> +++ patches/patch-qga_commands-common_h 1 Nov 2026 14:37:09 -0000
> @@ -1,6 +1,7 @@
> - qga: implement 'guest-get-fsinfo' for FreeBSD
> 2a454b5391ad4241c8d59d8325d8bacac9af7a8c
> - qga: implement 'guest-get-fsinfo' for NetBSD and OpenBSD
> + 6a24fc259da4b1efa8e53dc9a655d89474d270cc
>
> Index: qga/commands-common.h
> --- qga/commands-common.h.orig
> Index: patches/patch-qga_commands-posix_c
> ===================================================================
> RCS file: /cvs/ports/emulators/qemu/patches/patch-qga_commands-posix_c,v
> retrieving revision 1.13
> diff -u -p -u -p -r1.13 patch-qga_commands-posix_c
> --- patches/patch-qga_commands-posix_c 21 Sep 2026 09:48:01 -0000
> 1.13
> +++ patches/patch-qga_commands-posix_c 1 Nov 2026 14:37:09 -0000
> @@ -1,11 +1,35 @@
> - qga: implement 'guest-get-fsinfo' for FreeBSD
> 2a454b5391ad4241c8d59d8325d8bacac9af7a8c
> - qga: implement 'guest-get-fsinfo' for NetBSD and OpenBSD
> + 6a24fc259da4b1efa8e53dc9a655d89474d270cc
> +- qga: do not run hwclock(8) on non-Linux POSIX OSes
> + e1d00ea443da6f15dc10aea8c3ab4ad7ffeb68cc
>
> Index: qga/commands-posix.c
> --- qga/commands-posix.c.orig
> +++ qga/commands-posix.c
> -@@ -718,7 +718,7 @@ void qmp_guest_file_flush(int64_t handle, Error **errp
> +@@ -322,6 +322,20 @@ void qmp_guest_set_time(bool has_time, int64_t time_ns
> + }
> + }
> +
> ++#if !defined(CONFIG_LINUX)
> ++ /*
> ++ * BSDs (FreeBSD, OpenBSD, NetBSD) and illumos do not have the
> ++ * hwclock(8) tool. These systems update hardware clock when
> ++ * settimeofday() sets system time, so no additional actions
> ++ * are needed. Setting system time from RTC is not supported.
> ++ */
> ++ if (!has_time) {
> ++ error_setg(errp, "Setting system time from RTC is not supported");
> ++ }
> ++
> ++ return;
> ++#endif
> ++
> + /* Now, if user has passed a time to set and the system time is set, we
> + * just need to synchronize the hardware clock. However, if no time was
> + * passed, user is requesting the opposite: set the system time from the
> +@@ -718,7 +732,7 @@ void qmp_guest_file_flush(int64_t handle, Error **errp
> }
> }
>
> @@ -14,7 +38,7 @@ Index: qga/commands-posix.c
> void free_fs_mount_list(FsMountList *mounts)
> {
> FsMount *mount, *temp;
> -@@ -731,6 +731,9 @@ void free_fs_mount_list(FsMountList *mounts)
> +@@ -731,6 +745,9 @@ void free_fs_mount_list(FsMountList *mounts)
> QTAILQ_REMOVE(mounts, mount, next);
> g_free(mount->dirname);
> g_free(mount->devtype);
> Index: patches/patch-qga_meson_build
> ===================================================================
> RCS file: patches/patch-qga_meson_build
> diff -N patches/patch-qga_meson_build
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ patches/patch-qga_meson_build 1 Nov 2026 14:37:09 -0000
> @@ -0,0 +1,15 @@
> +- qga: implement 'guest-get-diskstats' for OpenBSD
> +
> +Index: qga/meson.build
> +--- qga/meson.build.orig
> ++++ qga/meson.build
> +@@ -93,6 +93,9 @@ qga_ss = qga_ss.apply({})
> +
> + gen_tlb = []
> + qga_libs = []
> ++if host_os == 'openbsd'
> ++ qga_libs += ['-lutil']
> ++endif
> + if host_os == 'windows'
> + qga_libs += ['-lws2_32', '-lwinmm', '-lpowrprof', '-lwtsapi32',
> '-lwininet', '-liphlpapi', '-lnetapi32',
> + '-lsetupapi', '-lcfgmgr32', '-luserenv', '-lpdh' ]
> Index: patches/patch-qga_qapi-schema_json
> ===================================================================
> RCS file: /cvs/ports/emulators/qemu/patches/patch-qga_qapi-schema_json,v
> retrieving revision 1.5
> diff -u -p -u -p -r1.5 patch-qga_qapi-schema_json
> --- patches/patch-qga_qapi-schema_json 21 Sep 2026 09:48:01 -0000
> 1.5
> +++ patches/patch-qga_qapi-schema_json 1 Nov 2026 14:37:09 -0000
> @@ -1,6 +1,11 @@
> - qga: implement 'guest-get-fsinfo' for FreeBSD
> 2a454b5391ad4241c8d59d8325d8bacac9af7a8c
> - qga: implement 'guest-get-fsinfo' for NetBSD and OpenBSD
> + 6a24fc259da4b1efa8e53dc9a655d89474d270cc
> +- qga: implement 'guest-network-get-route' for FreeBSD
> + 0ae3840f612ba00330940f26758ae03754f6c6b6
> +- qga: implement 'guest-network-get-route' for NetBSD and OpenBSD
> +- qga: implement 'guest-get-diskstats' for OpenBSD
> - qga: implement 'guest-get-vcpus' for the BSDs
>
> Index: qga/qapi-schema.json
> @@ -78,3 +83,122 @@ Index: qga/qapi-schema.json
>
> ##
> # @guest-set-user-password:
> +@@ -1407,7 +1407,7 @@
> + ##
> + { 'struct': 'GuestUser',
> + 'data': { 'user': 'str', 'login-time': 'number', '*domain': 'str' },
> +- 'if': { 'any': ['CONFIG_WIN32', 'HAVE_UTMPX' ] } }
> ++ 'if': { 'any': ['CONFIG_WIN32', 'HAVE_UTMPX', 'CONFIG_OPENBSD' ] } }
> +
> + ##
> + # @guest-get-users:
> +@@ -1420,7 +1420,7 @@
> + ##
> + { 'command': 'guest-get-users',
> + 'returns': ['GuestUser'],
> +- 'if': { 'any': ['CONFIG_WIN32', 'HAVE_UTMPX' ] } }
> ++ 'if': { 'any': ['CONFIG_WIN32', 'HAVE_UTMPX', 'CONFIG_OPENBSD' ] } }
> +
> + ##
> + # @GuestTimezone:
> +@@ -1714,7 +1714,7 @@
> + '*total-ticks': 'uint64',
> + '*weight-ticks': 'uint64'
> + },
> +- 'if': 'CONFIG_LINUX' }
> ++ 'if': { 'any': ['CONFIG_LINUX', 'CONFIG_BSD'] } }
> +
> + ##
> + # @GuestDiskStatsInfo:
> +@@ -1732,7 +1732,7 @@
> + 'major': 'uint64',
> + 'minor': 'uint64',
> + 'stats': 'GuestDiskStats' },
> +- 'if': 'CONFIG_LINUX' }
> ++ 'if': { 'any': ['CONFIG_LINUX', 'CONFIG_BSD'] } }
> +
> + ##
> + # @guest-get-diskstats:
> +@@ -1745,7 +1745,7 @@
> + ##
> + { 'command': 'guest-get-diskstats',
> + 'returns': ['GuestDiskStatsInfo'],
> +- 'if': 'CONFIG_LINUX'
> ++ 'if': { 'any': ['CONFIG_LINUX', 'CONFIG_BSD'] }
> + }
> +
> + ##
> +@@ -1879,8 +1879,8 @@
> + ##
> + # @GuestNetworkRoute:
> + #
> +-# Route information. Supported on Linux (since 9.1) and Windows
> +-# (since 11.0).
> ++# Route information. Supported on Linux (since 9.1), Windows
> ++# (since 11.0), and BSD (since 11.2).
> + #
> + # @iface: The destination network or host's egress network interface
> + # in the routing table
> +@@ -1894,30 +1894,31 @@
> + #
> + # @mask: Subnet Mask (IPv4 only)
> + #
> +-# @irtt: Initial round-trip delay (not for windows, IPv4 only)
> ++# @irtt: Initial round-trip delay (not for Windows and BSD,
> ++# IPv4 only)
> + #
> +-# @flags: Route flags (not for windows)
> ++# @flags: Route flags (not for Windows)
> + #
> +-# @refcnt: The route's reference count (not for windows)
> ++# @refcnt: The route's reference count (not for Windows and BSD)
> + #
> +-# @use: Route usage count (not for windows)
> ++# @use: Route usage count (not for Windows and BSD)
> + #
> +-# @window: TCP window size, used for flow control (not for windows,
> +-# IPv4 only)
> ++# @window: TCP window size, used for flow control (not for Windows
> ++# and BSD, IPv4 only)
> + #
> +-# @mtu: Data link layer maximum packet size (not for windows)
> ++# @mtu: Data link layer maximum packet size (not for Windows)
> + #
> + # @desprefixlen: Destination prefix length (for IPv6)
> + #
> +-# @source: Source IP address (for IPv6)
> ++# @source: Source IP address (not for BSD, IPv6 only)
> + #
> +-# @srcprefixlen: Source prefix length (for IPv6)
> ++# @srcprefixlen: Source prefix length (not for BSD, IPv6 only)
> + #
> + # @nexthop: Next hop IP address (for IPv6)
> + #
> + # @version: IP version (4 or 6)
> + #
> +-# Since: 9.1 (Linux only); 11.0 (Windows)
> ++# Since: 9.1 (Linux only); 11.0 (Windows); 11.2 (BSD)
> + ##
> + { 'struct': 'GuestNetworkRoute',
> + 'data': {'iface': 'str',
> +@@ -1937,7 +1938,7 @@
> + '*nexthop': 'str',
> + 'version': 'int'
> + },
> +- 'if': { 'any': ['CONFIG_LINUX', 'CONFIG_WIN32'] } }
> ++ 'if': { 'any': ['CONFIG_LINUX', 'CONFIG_WIN32', 'CONFIG_BSD'] } }
> +
> + ##
> + # @guest-network-get-route:
> +@@ -1946,9 +1947,9 @@
> + #
> + # Returns: List of route info of guest.
> + #
> +-# Since: 9.1 (Linux only); 11.0 (Windows)
> ++# Since: 9.1 (Linux only); 11.0 (Windows); 11.2 (BSD)
> + ##
> + { 'command': 'guest-network-get-route',
> + 'returns': ['GuestNetworkRoute'],
> +- 'if': { 'any': ['CONFIG_LINUX', 'CONFIG_WIN32'] }
> ++ 'if': { 'any': ['CONFIG_LINUX', 'CONFIG_WIN32', 'CONFIG_BSD'] }
> + }
>
--
wbr, Kirill