From nobody Thu Jul 30 05:11:12 2026 X-Original-To: dev-commits-src-main@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 4h9cjs0MbXz6mgPN for ; Thu, 30 Jul 2026 05:11:13 +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 4h9cjr6Wjgz3YZH for ; Thu, 30 Jul 2026 05:11:12 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785388272; 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=dcyDAm+f542adKtchqipDVk8J8qC1/RAyw6pL7NOQHA=; b=gI8UI19EXRjsRs1ebqpPrNA6hvwH0IstvZ93X/eZ6JROsZ8MwYCx7z9bRHfb8Cyx/kF4ls ZT9ZtXNkRRyZR2Lrt6aZvZd3XCGAe7n/qAOv0mGndHHWApWQGNXG8+Ezol6l3Dxq+TxlXo y9MzsNwbvgbTfeXc5XuzthlLSDSusdanv34NRCg4N7xP0YgHj7WXZS/EhLM9nn6Hr5m1zq I7JDJpXm6/hKG/qXm3W5irna1zsMsubLAlb0avuLwsql8rtTmCmHWlrJj54JKIBfTe5KOH JuwAM029CG4ZvoM21+H1CiLBGyM9LHwelr3cZpqJqrZqVYjHLGAf12lBzK3/gw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1785388272; a=rsa-sha256; cv=none; b=IENUmRnE/p9vDQsfK5AoWW/2NZr5TDRKWMjGDWU7MBWBo4fTYDVuVjgMn+MoSIW7aUM+ou y4u1OT37VT4PIUGr/ZSHpzHiW6QTL9FsUcxDzSTM6JvyhntcneaKHjnMFul98MeCBUqK6j R2iibecE+1cdo4hZenY0H8zkXSF+eJprd9eudVhMELPlO2QJT8z3wUQAudS/DeDt42uqRM ywRcM8OkZdA/wFAUmefAXv4Ry3Q1I3vy9rt7f9YvP++9koC3fUAV91OfYSz/Ey5t1QTs6t YFUF/4BfuvdWbD8chK4HMQwvCec1GqC8o4snS5b4dEe7C6IJyWD+8FL5Cqup/g== 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=1785388272; 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=dcyDAm+f542adKtchqipDVk8J8qC1/RAyw6pL7NOQHA=; b=MLC8+UafoIKLc7ue8qbZHCaHnHUY4CvNjHv3ufyrLdRay09nVhvfC2xgP1wQUn/KTZWYnb a0HMEWr37FIW9D2xNstbl0U0a4OmP2kgCdi3cSKn8AJ6F89h+YWCXRJ/6wG6mXhLjZ5pxv mSoe3PJvJm05RUdG7TbaBmUYxvc776vVWJijtBYp7HybEO/HysBPD6UFPBZhHMN4QgzyYg 9V5NYONn67zqhEhaZOosIxHLZfopxOtpyGZoDrBu2WY4NbEPTROH62UNjGuO2LNFun+ITY XMgf2ZS+rBCzb9/nvYJaCdSH+K6TzDy8mLqtnDWPEiYH1g5l6J+oou0i6cjKuA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4h9cjr4mXCzyPg for ; Thu, 30 Jul 2026 05:11:12 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3337e by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 30 Jul 2026 05:11:12 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: e8f3b96ba794 - main - igb: Rate-limit VF VLAN rebuild requests List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@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: e8f3b96ba794521af9904a451da33cf119381da8 Auto-Submitted: auto-generated Date: Thu, 30 Jul 2026 05:11:12 +0000 Message-Id: <6a6adcf0.3337e.7f35a7b2@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=e8f3b96ba794521af9904a451da33cf119381da8 commit e8f3b96ba794521af9904a451da33cf119381da8 Author: Kevin Bowling AuthorDate: 2026-07-29 08:04:40 +0000 Commit: Kevin Bowling CommitDate: 2026-07-30 05:10:00 +0000 igb: Rate-limit VF VLAN rebuild requests Give each VF a burst of 64 VLAN additions and refill it at eight additions per second. Removals remain unrestricted, idempotent requests consume nothing, and trusted PF-wide initialization replenishes the burst while guest resets do not. Checks VLVF capacity before charging a token. Do not apply this policy to multicast requests because Linux igbvf and DPDK ignore their reply status; aggregate MTA write elision bounds those updates instead. Sponsored by: BBOX.io --- sys/dev/e1000/if_igb_iov.c | 62 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/sys/dev/e1000/if_igb_iov.c b/sys/dev/e1000/if_igb_iov.c index 9b2c77a92eb7..f43e994c0440 100644 --- a/sys/dev/e1000/if_igb_iov.c +++ b/sys/dev/e1000/if_igb_iov.c @@ -19,6 +19,9 @@ #define IGB_IOV_MAX_MAC_FILTERS 3 #define IGB_IOV_MAX_MC_HASHES 30 #define IGB_IOV_MBX_RETRY_COUNT 6 +/* Allow two complete 31-VID replays, then sustain eight additions/second. */ +#define IGB_IOV_VLAN_CHANGE_BURST 64 +#define IGB_IOV_VLAN_CHANGE_INTERVAL (SBT_1S / 8) /* 82576 Datasheet rev. 2.0, Section 8.14.16: VMOLR[31] must be one. */ #define IGB_82576_VMOLR_RSV (1U << 31) #define IGB_82576_LVMMC_BLOCK_MASK 0x1c @@ -58,11 +61,13 @@ struct igb_vf { struct timeval last_mdd_log; sbintime_t mbx_retry_at; sbintime_t mdd_notify_at; + sbintime_t vlan_token_time; u16 pool; u16 rar_index; u16 max_frame_size; u16 mc_count; u16 vlan_count; + u16 vlan_tokens; u16 default_vlan; u8 mbx_retry_count; u8 mac[ETHER_ADDR_LEN]; @@ -167,6 +172,34 @@ igb_iov_nack_allowed(struct igb_vf *vf) return (ratecheck(&vf->last_nack, &igb_iov_nack_interval) != 0); } +static void +igb_iov_reset_vlan_rate(struct igb_vf *vf) +{ + + vf->vlan_token_time = getsbinuptime(); + vf->vlan_tokens = IGB_IOV_VLAN_CHANGE_BURST; +} + +static bool +igb_iov_vlan_add_allowed(struct igb_vf *vf) +{ + sbintime_t elapsed, now; + uint64_t refill; + + now = getsbinuptime(); + elapsed = now - vf->vlan_token_time; + if (elapsed >= IGB_IOV_VLAN_CHANGE_INTERVAL) { + refill = elapsed / IGB_IOV_VLAN_CHANGE_INTERVAL; + vf->vlan_tokens = min((uint64_t)IGB_IOV_VLAN_CHANGE_BURST, + vf->vlan_tokens + refill); + vf->vlan_token_time = now; + } + if (vf->vlan_tokens == 0) + return (false); + vf->vlan_tokens--; + return (true); +} + static u32 igb_iov_reply_header(u32 request, bool cts, bool ack) { @@ -642,7 +675,6 @@ igb_iov_rebuild_mta(struct e1000_softc *sc) mta[(hash >> 5) & (hw->mac.mta_reg_count - 1)] |= 1U << (hash & 0x1f); } - igb_iov_configure_vmolr(sc, vf); } changed = false; @@ -881,12 +913,17 @@ igb_iov_vlan_present(struct e1000_softc *sc, u16 vid, bool include_pf) static int igb_iov_vlan_unique_count(struct e1000_softc *sc, bool include_pf) { - int count, vid; + u32 vlans; + int count, i, word; count = 0; - for (vid = 0; vid < 4096; vid++) - if (igb_iov_vlan_present(sc, vid, include_pf)) - count++; + for (word = 0; word < EM_VFTA_SIZE; word++) { + vlans = include_pf ? sc->shadow_vfta[word] : 0; + for (i = 0; i < sc->num_vfs; i++) + if ((sc->vfs[i].flags & IGB_VF_ACTIVE) != 0) + vlans |= sc->vfs[i].vlans[word]; + count += bitcount32(vlans); + } return (count); } @@ -909,10 +946,17 @@ igb_iov_set_vlan(struct e1000_softc *sc, struct igb_vf *vf, u16 vid, if (add == present) return (0); + /* + * Removals always reduce privilege and remain available. Charge only + * additions, which a hostile VF must alternate with removals to force + * repeated global VLAN rebuilds. + */ if (add && !igb_iov_vlan_present(sc, vid, false) && igb_iov_vlan_unique_count(sc, false) >= E1000_VLVF_ARRAY_SIZE) return (ENOSPC); + if (add && !igb_iov_vlan_add_allowed(vf)) + return (EBUSY); if (add) { vf->vlans[vid >> 5] |= bit; @@ -1170,6 +1214,7 @@ igb_iov_set_multicast(struct e1000_softc *sc, struct igb_vf *vf, u32 *msg) "VF %u multicast list exceeds 30 entries; " "enabling all-multicast reception\n", vf->pool); } + igb_iov_configure_vmolr(sc, vf); igb_iov_rebuild_mta(sc); return (0); } @@ -1660,6 +1705,12 @@ igb_iov_initialize(struct e1000_softc *sc) vf = &sc->vfs[i]; if (!(vf->flags & IGB_VF_ACTIVE)) continue; + /* + * A PF-wide reset is trusted and can require a complete guest + * replay. Guest-controlled RESET and VFLR do not refill this + * allowance. + */ + igb_iov_reset_vlan_rate(vf); igb_iov_clear_mac_filters(sc, vf); igb_iov_reset_vf_state(sc, vf); igb_iov_clear_rar(sc, vf->rar_index); @@ -1875,6 +1926,7 @@ igb_if_iov_vf_add(if_ctx_t ctx, u16 vfnum, const nvlist_t *config) vf->rar_index = sc->hw.mac.rar_entry_count - (vfnum + 1); vf->max_frame_size = ETHER_MAX_LEN; vf->default_vlan = vlan; + igb_iov_reset_vlan_rate(vf); if (nvlist_exists_binary(config, "mac-addr")) { mac = nvlist_get_binary(config, "mac-addr", &mac_size); if (mac_size != ETHER_ADDR_LEN || !igb_iov_mac_valid(mac))