git: 6b3b1d6d4f43 - main - hn: Serialize VF link events with datapath handoff
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 15 Sep 2026 02:01:54 UTC
The branch main has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=6b3b1d6d4f43d1521e5e10b759e3542deaf23667
commit 6b3b1d6d4f43d1521e5e10b759e3542deaf23667
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-09-15 00:22:13 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-09-15 02:01:35 +0000
hn: Serialize VF link events with datapath handoff
Hold hn_vf_lock across the VF identity/state check and link publication.
Otherwise an event can observe an enabled VF, pause during fallback, then
overwrite the freshly reported synthetic carrier with stale VF state.
Ignore events while switching or after the association generation changes.
The link notification only queues further work, so the callback does not
need the sleepable hn lock.
Document that association serial numbers are currently diagnostic:
hn_ismyvf() matches the VF by MAC, while notifications gate availability.
MFC after: 2 weeks
Sponsored by: BBOX.io
---
sys/dev/hyperv/netvsc/if_hn.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/sys/dev/hyperv/netvsc/if_hn.c b/sys/dev/hyperv/netvsc/if_hn.c
index a36656b89b76..e4774b285a15 100644
--- a/sys/dev/hyperv/netvsc/if_hn.c
+++ b/sys/dev/hyperv/netvsc/if_hn.c
@@ -2132,10 +2132,16 @@ static void
hn_ifnet_lnkevent(void *xsc, if_t ifp, int link_state)
{
struct hn_softc *sc = xsc;
+ struct rm_priotracker pt;
+ /* Publish before a concurrent handoff can restore synthetic carrier. */
+ rm_rlock(&sc->hn_vf_lock, &pt);
if (sc->hn_vf_ifp == ifp &&
- (sc->hn_xvf_flags & HN_XVFFLAG_ENABLED))
+ (sc->hn_xvf_flags & (HN_XVFFLAG_ENABLED | HN_XVFFLAG_SWITCHING)) ==
+ HN_XVFFLAG_ENABLED && sc->hn_vf_active_assoc ==
+ atomic_load_acq_int(&sc->hn_vf_assoc))
if_link_state_change(sc->hn_ifp, link_state);
+ rm_runlock(&sc->hn_vf_lock, &pt);
}
static int
@@ -7527,6 +7533,7 @@ hn_nvs_handle_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt)
if_printf(sc->hn_ifp, "invalid VF association notification\n");
return;
}
+ /* The serial is diagnostic; hn_ismyvf() matches the VF by MAC. */
/* Preserve withdrawals even when the worker coalesces notices. */
state = (atomic_load_int(&sc->hn_vf_assoc) + HN_VF_ASSOC_GENINC) &
~HN_VF_ASSOC_ALLOCATED;