From nobody Mon Nov 02 20:44:48 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4jJNxL2Fk3z6yW01 for ; Mon, 02 Nov 2026 20:44:54 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 4jJNxK73bTz4mkB for ; Mon, 02 Nov 2026 20:44:53 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793652294; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=iVo4elRN9rlf6YscCvoOaxPnAOBW5PTuyzBP6H5chdA=; b=TCtkdTFsrwXXBIUqm/fmPSEf15o8n4OdO4zsbsWPctMQi9CcpBtY1i85DvcSaHzA8g8E/5 aDaEXC8Sj5wYro7tkyCRr9t02tIWqn2/lQVxy7UgE6ohSC0q75s/XtXIGEMkPQ+1btIaE5 XcATpnRQOMR0v34Fj1zDI1GAA22zpYzS4j7a+s1eZBH3kOQtCBvmkkM1j+a7dqBo0tSmks 7ZeFX2q7CpKJHKokED6+ifvcjh6cTNWs7UPqadcOmuf9z/M0dN/e/v8uJnahILAbhR9dWq Qv7wMOmL7c5wrenmo/uf6l+MHNYzk76imheMRehnKvQLr7mLLhSBmauvNhgJ3A== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1793652294; b=LW74CavXWjEDUDT8PlIErZgVOYW3EyttsfM1S3eSouNZB1yp3+WR0UshX88rwn8BjleOhr nHhWzkY2benufPZaGioBzTU1u73z69YJS8qmpBrZ0ZLPkZvevi9JUJTELvvIwfcdMcknMX mnQIX8Am4KrHmYuIFOkTLV34x6wF5QymZZYv9S3ei8aRfKTphWmlDkjptsWrOE1OySSCjo 1LuarZ+rTiODIp60epjTPAEESj40J38i0iftif5UvgZaACMc65a45lnfJAsPz06xI9vz/G IS0sTtHHHO1L/ERYJhIAek6RaZiVO1gJ5dZwGsRh3QEKhuxz52en7tWcQ/VZlw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1793652294; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=iVo4elRN9rlf6YscCvoOaxPnAOBW5PTuyzBP6H5chdA=; b=qPzi0BuySevld22omHFK87YO+hEN/69JZxRshWJh0qUlBfNf1cErWTLtRgLlaI0rJ+QrkE TCqmEOp0KKNWt3ueZDzOEnm2am8bh3f3Ho7/cqOj41/6OuXCXWPtmrTYrg0RGrO50b1KvI 1k6+SO49U+zRPKvNNjWvVp2Ngj9O0F4wvE3rmHpi9yGzRFSToIgjaSSQ4EVzi2CmK8vUoO viPjN+WSEkRTvAvDBH+SKGVmQMI0F5ahttBPxda73bsvu2GXmfsSVePOO3kDv4so0Hzuew QJLvFvad2MTJ2HsSI1M6WjHkzS1z3UY6JVFpgQ77l4a5k3BaeB138xlk/LFbcQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4jJNxK6jwBz11yL for ; Mon, 02 Nov 2026 20:44:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3d912 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 02 Nov 2026 20:44:48 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Cc: Faraz Vahedi From: Faraz Vahedi Subject: git: 94e19d4178e6 - stable/15 - vtnet: Implement VIRTIO_NET_F_GUEST_ANNOUNCE List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: Commit messages for all branches of the src repository List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kfv X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 94e19d4178e6aa758c0526345578ba56331813d7 Auto-Submitted: auto-generated Date: Mon, 02 Nov 2026 20:44:48 +0000 Message-Id: <6ae8f640.3d912.3ba49ed0@gitrepo.freebsd.org> The branch stable/15 has been updated by kfv: URL: https://cgit.FreeBSD.org/src/commit/?id=94e19d4178e6aa758c0526345578ba56331813d7 commit 94e19d4178e6aa758c0526345578ba56331813d7 Author: Faraz Vahedi AuthorDate: 2026-07-12 20:46:20 +0000 Commit: Faraz Vahedi CommitDate: 2026-11-02 20:41:21 +0000 vtnet: Implement VIRTIO_NET_F_GUEST_ANNOUNCE When the device sets VIRTIO_NET_S_ANNOUNCE in the config status field, for example after a VM migrates to a new host, announce the interface's presence on the network so peers and switches learn the new attachment point, then acknowledge the request with the VIRTIO_NET_CTRL_ANNOUNCE_ACK control command, as per VirtIO v1.3, 5.1.6.5.4. The announcement raises iflladdr_event: the stack sends gratuitous ARPs and unsolicited neighbor advertisements for the interface's addresses, and stacked interfaces such as vlan(4) propagate the event and announce theirs as well. The event handlers may sleep, so the work is deferred from the config change interrupt to a task on taskqueue_thread; that context also allows the acknowledgement to be skipped safely if the interface was stopped in the meantime, in which case the device keeps the bit set and the request is re-delivered with the next config change interrupt. Signed-off-by: Faraz Vahedi Reviewed by: adrian Pull Request: https://github.com/freebsd/freebsd-src/pull/2322 (cherry picked from commit c5caf856453325728155a18d3bb02a9cd651a0a0) --- sys/dev/virtio/network/if_vtnet.c | 88 ++++++++++++++++++++++++++++++++++++ sys/dev/virtio/network/if_vtnetvar.h | 2 + 2 files changed, 90 insertions(+) diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c index 112edde34b03..cc49c743ee97 100644 --- a/sys/dev/virtio/network/if_vtnet.c +++ b/sys/dev/virtio/network/if_vtnet.c @@ -213,6 +213,9 @@ static void vtnet_exec_ctrl_cmd(struct vtnet_softc *, void *, static int vtnet_ctrl_mac_cmd(struct vtnet_softc *, uint8_t *); static int vtnet_ctrl_guest_offloads(struct vtnet_softc *, uint64_t); static int vtnet_ctrl_mq_cmd(struct vtnet_softc *, uint16_t); +static int vtnet_ctrl_announce_ack_cmd(struct vtnet_softc *); +static bool vtnet_announce_pending(struct vtnet_softc *); +static void vtnet_announce(void *, int); static int vtnet_ctrl_rx_cmd(struct vtnet_softc *, uint8_t, bool); static int vtnet_set_promisc(struct vtnet_softc *, bool); static int vtnet_set_allmulti(struct vtnet_softc *, bool); @@ -451,6 +454,7 @@ vtnet_attach(device_t dev) VTNET_CORE_LOCK_INIT(sc); callout_init_mtx(&sc->vtnet_tick_ch, VTNET_CORE_MTX(sc), 0); + TASK_INIT(&sc->vtnet_announce_task, 0, vtnet_announce, sc); vtnet_load_tunables(sc); vtnet_alloc_interface(sc); @@ -525,6 +529,8 @@ vtnet_detach(device_t dev) ether_ifdetach(ifp); } + taskqueue_drain(taskqueue_thread, &sc->vtnet_announce_task); + #ifdef DEV_NETMAP netmap_detach(ifp); #endif @@ -629,6 +635,8 @@ vtnet_config_change(device_t dev) VTNET_CORE_LOCK(sc); vtnet_update_link_status(sc); + if (vtnet_announce_pending(sc)) + taskqueue_enqueue(taskqueue_thread, &sc->vtnet_announce_task); if (sc->vtnet_link_active != 0) vtnet_tx_start_all(sc); VTNET_CORE_UNLOCK(sc); @@ -3698,6 +3706,86 @@ vtnet_ctrl_mq_cmd(struct vtnet_softc *sc, uint16_t npairs) return (s.ack == VIRTIO_NET_OK ? 0 : EIO); } +static int +vtnet_ctrl_announce_ack_cmd(struct vtnet_softc *sc) +{ + struct sglist_seg segs[2]; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; + struct sglist sg; + struct virtio_net_ctrl_hdr hdr __aligned(2); + uint8_t ack; + int error; + + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error != 0) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &hdr, + sizeof(hdr), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error != 0) + goto error_destroy_hdr; + + hdr.class = VIRTIO_NET_CTRL_ANNOUNCE; + hdr.cmd = VIRTIO_NET_CTRL_ANNOUNCE_ACK; + ack = VIRTIO_NET_ERR; + bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE); + + sglist_init(&sg, nitems(segs), segs); + error = sglist_append_phys(&sg, hdr_paddr, sizeof(hdr)); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); + + if (error == 0) + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); + + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +error_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +error_out: + return (error); +} + +static bool +vtnet_announce_pending(struct vtnet_softc *sc) +{ + uint16_t status; + + if ((sc->vtnet_features & VIRTIO_NET_F_GUEST_ANNOUNCE) == 0 || + (sc->vtnet_features & VIRTIO_NET_F_CTRL_VQ) == 0 || + (sc->vtnet_features & VIRTIO_NET_F_STATUS) == 0) + return (false); + + status = virtio_read_dev_config_2(sc->vtnet_dev, + offsetof(struct virtio_net_config, status)); + + return ((status & VIRTIO_NET_S_ANNOUNCE) != 0); +} + +static void +vtnet_announce(void *xsc, int pending __unused) +{ + struct vtnet_softc *sc; + if_t ifp; + + sc = xsc; + ifp = sc->vtnet_ifp; + + if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) + return; + + CURVNET_SET(if_getvnet(ifp)); + EVENTHANDLER_INVOKE(iflladdr_event, ifp); + CURVNET_RESTORE(); + + VTNET_CORE_LOCK(sc); + if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0 && + vtnet_ctrl_announce_ack_cmd(sc) != 0) + device_printf(sc->vtnet_dev, "cannot ack announcement\n"); + VTNET_CORE_UNLOCK(sc); +} + static int vtnet_ctrl_rx_cmd(struct vtnet_softc *sc, uint8_t cmd, bool on) { diff --git a/sys/dev/virtio/network/if_vtnetvar.h b/sys/dev/virtio/network/if_vtnetvar.h index 237b86fd0244..d1dd8adaed69 100644 --- a/sys/dev/virtio/network/if_vtnetvar.h +++ b/sys/dev/virtio/network/if_vtnetvar.h @@ -183,6 +183,7 @@ struct vtnet_softc { uint64_t vtnet_negotiated_features; struct vtnet_statistics vtnet_stats; struct callout vtnet_tick_ch; + struct task vtnet_announce_task; struct ifmedia vtnet_media; eventhandler_tag vtnet_vlan_attach; eventhandler_tag vtnet_vlan_detach; @@ -322,6 +323,7 @@ CTASSERT(sizeof(struct vtnet_mac_filter) <= PAGE_SIZE); VIRTIO_NET_F_CTRL_RX | \ VIRTIO_NET_F_CTRL_MAC_ADDR | \ VIRTIO_NET_F_CTRL_VLAN | \ + VIRTIO_NET_F_GUEST_ANNOUNCE | \ VIRTIO_NET_F_CSUM | \ VIRTIO_NET_F_HOST_TSO4 | \ VIRTIO_NET_F_HOST_TSO6 | \