From nobody Thu Jul 30 05:04:56 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 4h9cZd04Znz6mfjG for ; Thu, 30 Jul 2026 05:04:57 +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 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4h9cZc3rPdz3Wjh for ; Thu, 30 Jul 2026 05:04:56 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785387896; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=692V5k6obRjo/q0wvOGtUNNLOqLNmbHSkpAnxHyJiHs=; b=FCTFx1ih/Jg0wIuUSwCMOjCwBnoRKEh+DaBuKEBDMgLho4vr4vrJW9G2SeXlrT18M3TIhw ekTdUTcNaMRv/G/v6QjhNIeLL9M38/rGff9de2soZNZysDC/sP2uygGRrveR4HcmL8XG8f ghqQUYQZ0CLXIdzZHiyp0gnS6p1S2fat3uXpUV5hbKWTXkhjPAX2dnyQmkYwdxxxK/XLO3 VQzaCYFu8n5D8FUAcwSYRASOqQJiyS5MFAHKUnUqjKHCo3INBH997FZAuOAmybf34d4q4C O56AnLItoiqyYFX0ydLl5Na16Q8phwTYgosi0QjDfyuV1bhux2in2tldBjP1qw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1785387896; a=rsa-sha256; cv=none; b=jyI0CAPe/XD2i8EgFNbPXcIBFVDXNAR/VkV/TOYZcLNspdWgnpEgzMYgq40P1rN+p2K+7n 16f9isrtQBJUews0vAjHV/fszAHUIWCr3qXfw8B94ObqoRCkamoRuCsdCi2qEPPGW75N3a zJfVKAUS7Zmo6bUdRYvieRAv4drwM0y/dUiAm4M0G8Rjm5wKeOVO3WCn20hf6H5gGvxsFu ckUJ0VWNTaU5jxQ26KF+ocNOtcKgmC/qPN6fPmeS2AuyEfrvSTjZzRj1rWP25/gUUVbTKt 17ce8ATtitw37+Rg4cCfAnwDPrzAk1NnzvmFze+JVIDrusZBnaAmw1QME0FsMg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785387896; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=692V5k6obRjo/q0wvOGtUNNLOqLNmbHSkpAnxHyJiHs=; b=dTnFubPP7MLBlxf3t6szTZrxLU4bDIQQW3z+ZiZ1aGwubIo8E2NylutcbQDnTAHzEF7Bro Vxd+5Ww9hvTpiZJgaa+vh2Vlh+gzAnU5hUtiYFZPHkb8XsFd6D58E5eUt6I7dDe8mQwXQr sMWKjUiw9/rciS/+If8EkPxrZW17B2QGwQQpWOjol7Rm/g+RIAnBnLeP+eMviQZxsNv/KL J2vHRB5TQAPvVspCvkHiUuogaNuW4oIyDembFQ3Xgq7hwqP0s2sTobwiVABvFzQdCMA3G1 lKKOk/1z0r9Tsalxo3jRmNtTLFG2fdkWrt5wqtM9rYFnFy+8VSDu7ieDCoZohA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4h9cZc1shVzyMF for ; Thu, 30 Jul 2026 05:04:56 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 32021 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 30 Jul 2026 05:04:56 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 9332fd555588 - main - igbv: Support secondary unicast filters List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: 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: kbowling X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 9332fd555588ef4f7913664f8bdb57febc828e76 Auto-Submitted: auto-generated Date: Thu, 30 Jul 2026 05:04:56 +0000 Message-Id: <6a6adb78.32021.3f4bb023@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=9332fd555588ef4f7913664f8bdb57febc828e76 commit 9332fd555588ef4f7913664f8bdb57febc828e76 Author: Kevin Bowling AuthorDate: 2026-07-29 04:22:32 +0000 Commit: Kevin Bowling CommitDate: 2026-07-30 05:01:32 +0000 igbv: Support secondary unicast filters Support the Linux igbvf secondary-MAC mailbox subprotocol, used by Linux guests running MacVTap. Replay up to three non-primary unicast addresses after reset and whenever the address list changes, subject to PF allow-set-mac policy. Sponsored by: BBOX.io --- sys/dev/e1000/e1000_82575.h | 1 + sys/dev/e1000/e1000_vf.c | 35 ++++++++++++++++++++++++ sys/dev/e1000/e1000_vf.h | 1 + sys/dev/e1000/if_em.c | 1 + sys/dev/e1000/if_em.h | 3 +++ sys/dev/e1000/if_igbv.c | 66 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+) diff --git a/sys/dev/e1000/e1000_82575.h b/sys/dev/e1000/e1000_82575.h index 720ecf8fc817..c919a8064476 100644 --- a/sys/dev/e1000/e1000_82575.h +++ b/sys/dev/e1000/e1000_82575.h @@ -405,6 +405,7 @@ enum e1000_promisc_type { s32 e1000_vfta_set_vf(struct e1000_hw *, u16, bool); void e1000_rlpml_set_vf(struct e1000_hw *, u16); s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type type); +s32 e1000_set_uc_addr_vf(struct e1000_hw *, u32, u8 *); void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value); u16 e1000_rxpbs_adjust_82580(u32 data); s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data); diff --git a/sys/dev/e1000/e1000_vf.c b/sys/dev/e1000/e1000_vf.c index d25dc7a23056..d48a4153c1b3 100644 --- a/sys/dev/e1000/e1000_vf.c +++ b/sys/dev/e1000/e1000_vf.c @@ -388,6 +388,41 @@ static void e1000_write_msg_read_ack(struct e1000_hw *hw, mbx->ops.read_posted(hw, retmsg, E1000_VFMAILBOX_SIZE, 0); } +/** + * e1000_set_uc_addr_vf - Add or clear secondary unicast addresses + * @hw: pointer to the HW structure + * @sub_cmd: E1000_VF_MAC_FILTER_ADD or E1000_VF_MAC_FILTER_CLR + * @addr: address to add, or a valid compatibility address when clearing + * + * Uses the secondary-MAC mailbox subprotocol implemented by Linux igbvf. + * Linux igb PFs validate this field before dispatching the clear subcommand, + * even though they do not otherwise use it for a clear request. + **/ +s32 +e1000_set_uc_addr_vf(struct e1000_hw *hw, u32 sub_cmd, u8 *addr) +{ + struct e1000_mbx_info *mbx = &hw->mbx; + u32 msgbuf[3] = {}; + u32 request; + s32 ret_val; + + msgbuf[0] = E1000_VF_SET_MAC_ADDR | sub_cmd; + request = msgbuf[0]; + if (addr != NULL) + memcpy(&msgbuf[1], addr, ETHER_ADDR_LEN); + + ret_val = mbx->ops.write_posted(hw, msgbuf, 3, 0); + if (ret_val == E1000_SUCCESS) + ret_val = mbx->ops.read_posted(hw, msgbuf, 3, 0); + + msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS; + if (ret_val == E1000_SUCCESS && + msgbuf[0] == (request | E1000_VT_MSGTYPE_NACK)) + ret_val = -E1000_ERR_NO_SPACE; + + return (ret_val); +} + /** * e1000_update_mc_addr_list_vf - Update Multicast addresses * @hw: pointer to the HW structure diff --git a/sys/dev/e1000/e1000_vf.h b/sys/dev/e1000/e1000_vf.h index b509ba48eb0b..17116a86b084 100644 --- a/sys/dev/e1000/e1000_vf.h +++ b/sys/dev/e1000/e1000_vf.h @@ -294,4 +294,5 @@ s32 e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value); s32 e1000_vfta_set_vf(struct e1000_hw *, u16, bool); void e1000_rlpml_set_vf(struct e1000_hw *, u16); s32 e1000_promisc_set_vf(struct e1000_hw *, enum e1000_promisc_type); +s32 e1000_set_uc_addr_vf(struct e1000_hw *, u32, u8 *); #endif /* _E1000_VF_H_ */ diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 9f9d3dc3024e..4f4eeee5da50 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -2550,6 +2550,7 @@ em_if_multi_set(if_ctx_t ctx) if (sc->vf_ifp) { e1000_update_mc_addr_list(&sc->hw, mta, mcnt); + igbv_update_uc_addr_list(sc, ifp); return; } diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h index dbc3e945f78b..93ddf0bfc25a 100644 --- a/sys/dev/e1000/if_em.h +++ b/sys/dev/e1000/if_em.h @@ -643,6 +643,8 @@ struct e1000_softc { u16 vf_ifp; bool vf_reset_pending; + /* A PF can retain auxiliary filters across a VF reset. */ + bool vf_uc_filters_set; }; /* @@ -669,6 +671,7 @@ void igbv_initialize_receive_unit(if_ctx_t); void igbv_initialize_transmit_unit(if_ctx_t); void igbv_reconcile_mac(struct e1000_softc *, if_t); bool igbv_reset(if_ctx_t); +void igbv_update_uc_addr_list(struct e1000_softc *, if_t); /******************************************************************************** * vendor_info_array diff --git a/sys/dev/e1000/if_igbv.c b/sys/dev/e1000/if_igbv.c index 78b07d204aef..4f869388ce81 100644 --- a/sys/dev/e1000/if_igbv.c +++ b/sys/dev/e1000/if_igbv.c @@ -30,6 +30,13 @@ #include +#define IGBV_MAX_MAC_FILTERS 3 + +struct igb_vf_uc_addr_list { + struct e1000_softc *sc; + u8 addrs[IGBV_MAX_MAC_FILTERS][ETHER_ADDR_LEN]; +}; + static bool igbv_tx_pending(struct e1000_softc *); int @@ -293,6 +300,65 @@ igbv_get_regs(SYSCTL_HANDLER_ARGS) return (error); } +static u_int +igbv_copy_uc_addr(void *arg, struct sockaddr_dl *sdl, u_int idx) +{ + struct igb_vf_uc_addr_list *list; + const u8 *addr; + + list = arg; + addr = (const u8 *)LLADDR(sdl); + if (memcmp(addr, list->sc->hw.mac.addr, ETHER_ADDR_LEN) == 0) + return (0); + if (idx < IGBV_MAX_MAC_FILTERS) + memcpy(list->addrs[idx], addr, ETHER_ADDR_LEN); + return (1); +} + +void +igbv_update_uc_addr_list(struct e1000_softc *sc, if_t ifp) +{ + struct igb_vf_uc_addr_list list = { + .sc = sc, + }; + u_int count; + + count = if_foreach_lladdr(ifp, igbv_copy_uc_addr, &list); + if (count > IGBV_MAX_MAC_FILTERS) { + device_printf(sc->dev, + "too many secondary unicast addresses; maximum is %u\n", + IGBV_MAX_MAC_FILTERS); + } + if (count == 0 && !sc->vf_uc_filters_set) + return; + /* + * Linux igb PFs validate the address field before dispatching the CLR + * subcommand. Supply the primary address rather than the zero payload + * used by igbvf so those PFs actually remove the old filters. FreeBSD + * PFs dispatch CLR before inspecting the otherwise-ignored address. + */ + if (e1000_set_uc_addr_vf(&sc->hw, E1000_VF_MAC_FILTER_CLR, + sc->hw.mac.addr) != E1000_SUCCESS) { + device_printf(sc->dev, + "VF secondary unicast filter clear request failed\n"); + return; + } + sc->vf_uc_filters_set = false; + if (count > IGBV_MAX_MAC_FILTERS) + return; + + for (u_int i = 0; i < count; i++) { + if (e1000_set_uc_addr_vf(&sc->hw, E1000_VF_MAC_FILTER_ADD, + list.addrs[i]) != E1000_SUCCESS) { + device_printf(sc->dev, + "VF secondary unicast filter add request failed " + "for %6D\n", list.addrs[i], ":"); + } else + sc->vf_uc_filters_set = true; + usec_delay(200); + } +} + void igbv_reconcile_mac(struct e1000_softc *sc, if_t ifp) {