From nobody Thu Sep 17 08:36:28 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 4hlpy50G8cz6sh7L for ; Thu, 17 Sep 2026 08:36:29 +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 "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hlpy46trhz574H for ; Thu, 17 Sep 2026 08:36:28 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789634189; 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=xvu8rKDHJ00fjs+WWqBuaOJZx1/NFm2eamYdLkm8Gsc=; b=WOdVyKRQGnsbvn3B2XB9aTHvGwyNACst4qxqnoTeZ2hPKligpsalxlQuegTf45Z4SYVh4h ipjgQliLdwTLc+FhO2+ofMDYKNh/Zly3/MJ4QPVDF9gPeBlctwLiDMlWU8UZ/cLgo0YJSE smqgkGEQQGloipJ+Ce0gguFgMreSyQ2PwpNESo7RfV4p0BagEl8+Tp83IfKUGW5f8u124x /tprWoqWQzyzd8HHPQ6ArQ1Wx2fsBjzI3FVXGXcivNl6g3LmTx5t7SFbdpjKnq+dlzNOit JjsQsKs5hDassPoo5/IrfTNxe0/wE/A8kDV4o8YDhpbObLushh+9jsZtq7qrDQ== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1789634189; b=GUAAvJi9kHyxApzOFyayCpbFoilayEPO1PEPIwCmMZb/Q8VrTM28DmSZFe5xcSlnHPxdV9 Sa3mNXKmR9n5GCUeQ+Ly66gKE5c/NRtpnNpj1pHPPUIok7JHR72GdkS78Ila8UVxAS0ccA I/SDC7RXwsQeX7EZ9nL9hma4VJbsgEp8vgnCB/Th5AiDNAaqiwlof0o5fDyPUcRzsNr/H7 QfuoVR98B1EbI5cFY8RKJirFCO2v+b3G7iL8TG3isz+d2PKERQoq9VQBoMlDiM9W7khUWr q4onKnnX+G6GROTTS3XW74N2dvtdB8vnF/Kw4g/ASVEgaLajdxzVr8RzOEpyRA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789634189; 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=xvu8rKDHJ00fjs+WWqBuaOJZx1/NFm2eamYdLkm8Gsc=; b=iyI0Gm8M/MV1dIzyhmeZJvsgjoKpJ+BP08Wq7/FA3CyPS2sMdsNh6WtJwfFyxwmxZdaZp5 oJVLhGlXKzf2H0kFKg7QlIrYzXYQao2QsHl7pg1d4ewxZeLXi3TUancWcnsMOSnS4yBC+R TQty1X6OCVxITLevwN65EUAoPIZpQmgapkiLIcV7qHBd3hW8zti6gOlBqiVej01fspr4ZD is10rewEyRdYPwI70kHDA7WKELltdpyVw3twi61zOEe+u9509d+dvLvQhpfHoK79EI1niD a3hiTnXblG2QlMmnsSGVXx9acBxxcIXtJiY+5F/+9FCE8HYz82jfmKttmTI33A== 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 4hlpy45zKNzPmf for ; Thu, 17 Sep 2026 08:36:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3ce16 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 17 Sep 2026 08:36:28 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 2231e505d1d4 - main - ice: Make VF VLAN requests idempotent 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: 2231e505d1d40441b80cfacb5a92111d1408a935 Auto-Submitted: auto-generated Date: Thu, 17 Sep 2026 08:36:28 +0000 Message-Id: <6aaba68c.3ce16.58ef8906@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=2231e505d1d40441b80cfacb5a92111d1408a935 commit 2231e505d1d40441b80cfacb5a92111d1408a935 Author: Kevin Bowling AuthorDate: 2026-08-18 10:44:24 +0000 Commit: Kevin Bowling CommitDate: 2026-09-17 08:34:55 +0000 ice: Make VF VLAN requests idempotent VF drivers replay their VLAN filters after a reset and may retry a request whose reply was lost. The PF tracked only a count and sent every requested ID back to the switch. After PF reset replay had already restored the filters, duplicate VID 0 failed with ICE_ERR_ALREADY_EXISTS and NACKed the entire VF batch. Track exact VLAN membership for each VF. Compact requests to unique IDs whose membership changes, enforce the configured limit against those IDs, and update membership after each hardware operation so partial failures cannot undercount filters. Treat already-present adds and already-absent deletes as successful reconciliation and suppress their misleading low-level error dump. Validated on an E810-XXV with a host-attached iavf VF. A three-filter limit was filled with VIDs 0, 1, and 4094. PF and CORE resets replayed all three without a duplicate warning or ADD_VLAN NACK, and DTrace confirmed a three-VID replay reached the PF. A fourth unique VID was rejected without changing the count; deleting an absent VID was a no-op; deleting and replacing a present VID updated the count exactly. A 128 four-queue VF create/destroy cycle also completed cleanly, and a newly recreated VF started with an empty membership map. MFC after: 2 weeks Sponsored by: BBOX.io Differential Revision: https://reviews.freebsd.org/D58909 --- sys/dev/ice/ice_iov.c | 107 +++++++++++++++++++++++++++++++++++++++----------- sys/dev/ice/ice_iov.h | 3 ++ sys/dev/ice/ice_lib.c | 4 +- 3 files changed, 89 insertions(+), 25 deletions(-) diff --git a/sys/dev/ice/ice_iov.c b/sys/dev/ice/ice_iov.c index 869fe43a9411..61f53aad89b9 100644 --- a/sys/dev/ice/ice_iov.c +++ b/sys/dev/ice/ice_iov.c @@ -79,6 +79,8 @@ static void ice_vc_add_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf); static void ice_vc_del_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf); +static int ice_vc_select_vlans(struct ice_vf *vf, u16 *vids, u16 count, + bool add, u16 *selected_count); static enum virtchnl_status_code ice_iov_err_to_virt_err(int ice_err); static int ice_vf_validate_mac(struct ice_vf *vf, const uint8_t *addr); @@ -959,6 +961,43 @@ ice_vc_del_eth_addr_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) v_status, NULL, 0, NULL); } +/** + * ice_vc_select_vlans - Compact a VF VLAN request in place + * @vf: VF tracking structure + * @vids: VLAN IDs supplied by the VF + * @count: number of VLAN IDs in the request + * @add: select absent VLANs for add, or present VLANs for delete + * @selected_count: returned number of VLAN IDs requiring a hardware change + * + * A VF may replay its entire VLAN configuration after a reset or retry a + * request whose reply was lost. Select only unique IDs whose membership + * actually changes so those requests remain idempotent and filter accounting + * continues to enforce the configured limit. + */ +static int +ice_vc_select_vlans(struct ice_vf *vf, u16 *vids, u16 count, bool add, + u16 *selected_count) +{ + bitstr_t bit_decl(seen, ICE_VF_VLAN_MAP_LEN); + u16 selected, vid; + + bzero(seen, sizeof(seen)); + selected = 0; + for (u16 i = 0; i < count; i++) { + vid = vids[i]; + if (vid > EVL_VLID_MASK) + return (EINVAL); + if (bit_test(seen, vid)) + continue; + bit_set(seen, vid); + if (bit_test(vf->vlans_map, vid) == add) + continue; + vids[selected++] = vid; + } + *selected_count = selected; + return (0); +} + /** * ice_vc_add_vlan_msg - Handle VIRTCHNL_OP_ADD_VLAN msg from VF * @sc: PF's softc structure @@ -972,6 +1011,7 @@ ice_vc_add_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) { struct ice_hw *hw = &sc->hw; struct virtchnl_vlan_filter_list *vlan_list; + u16 selected; int status = 0; enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; struct ice_vsi *vsi = vf->vsi; @@ -986,23 +1026,34 @@ ice_vc_add_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) goto done; } - if (vlan_list->num_elements > (vf->vlan_limit - vf->vlan_cnt)) { - v_status = VIRTCHNL_STATUS_ERR_NO_MEMORY; + status = ice_vc_select_vlans(vf, vlan_list->vlan_id, + vlan_list->num_elements, true, &selected); + if (status != 0) { + v_status = VIRTCHNL_STATUS_ERR_PARAM; goto done; } - status = ice_add_vlan_hw_filters(vsi, vlan_list->vlan_id, - vlan_list->num_elements); - if (status) { - device_printf(sc->dev, - "VF-%d: Failure adding VLANs to VSI %d, err %s aq_err %s\n", - vf->vf_num, vsi->idx, ice_status_str(status), - ice_aq_str(sc->hw.adminq.sq_last_status)); - v_status = ice_iov_err_to_virt_err(status); + if ((u32)vf->vlan_cnt + selected > vf->vlan_limit) { + v_status = VIRTCHNL_STATUS_ERR_NO_MEMORY; goto done; } + if (selected == 0) + goto done; - vf->vlan_cnt += vlan_list->num_elements; + for (u16 i = 0; i < selected; i++) { + status = ice_add_vlan_hw_filter(vsi, vlan_list->vlan_id[i]); + if (status != 0 && status != ICE_ERR_ALREADY_EXISTS) { + device_printf(sc->dev, + "VF-%d: Failure adding VLAN %d to VSI %d, err %s aq_err %s\n", + vf->vf_num, vlan_list->vlan_id[i], vsi->idx, + ice_status_str(status), + ice_aq_str(sc->hw.adminq.sq_last_status)); + v_status = ice_iov_err_to_virt_err(status); + goto done; + } + bit_set(vf->vlans_map, vlan_list->vlan_id[i]); + vf->vlan_cnt++; + } done: ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_ADD_VLAN, @@ -1022,6 +1073,7 @@ ice_vc_del_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) { struct ice_hw *hw = &sc->hw; struct virtchnl_vlan_filter_list *vlan_list; + u16 selected; int status = 0; enum virtchnl_status_code v_status = VIRTCHNL_STATUS_SUCCESS; struct ice_vsi *vsi = vf->vsi; @@ -1036,21 +1088,30 @@ ice_vc_del_vlan_msg(struct ice_softc *sc, struct ice_vf *vf, u8 *msg_buf) goto done; } - status = ice_remove_vlan_hw_filters(vsi, vlan_list->vlan_id, - vlan_list->num_elements); - if (status) { - device_printf(sc->dev, - "VF-%d: Failure deleting VLANs from VSI %d, err %s aq_err %s\n", - vf->vf_num, vsi->idx, ice_status_str(status), - ice_aq_str(sc->hw.adminq.sq_last_status)); - v_status = ice_iov_err_to_virt_err(status); + status = ice_vc_select_vlans(vf, vlan_list->vlan_id, + vlan_list->num_elements, false, &selected); + if (status != 0) { + v_status = VIRTCHNL_STATUS_ERR_PARAM; goto done; } + if (selected == 0) + goto done; - if (vlan_list->num_elements >= vf->vlan_cnt) - vf->vlan_cnt = 0; - else - vf->vlan_cnt -= vlan_list->num_elements; + for (u16 i = 0; i < selected; i++) { + status = ice_remove_vlan_hw_filter(vsi, vlan_list->vlan_id[i]); + if (status != 0 && status != ICE_ERR_DOES_NOT_EXIST) { + device_printf(sc->dev, + "VF-%d: Failure deleting VLAN %d from VSI %d, err %s aq_err %s\n", + vf->vf_num, vlan_list->vlan_id[i], vsi->idx, + ice_status_str(status), + ice_aq_str(sc->hw.adminq.sq_last_status)); + v_status = ice_iov_err_to_virt_err(status); + goto done; + } + bit_clear(vf->vlans_map, vlan_list->vlan_id[i]); + MPASS(vf->vlan_cnt > 0); + vf->vlan_cnt--; + } done: ice_aq_send_msg_to_vf(hw, vf->vf_num, VIRTCHNL_OP_DEL_VLAN, diff --git a/sys/dev/ice/ice_iov.h b/sys/dev/ice/ice_iov.h index 7d6d7fdb1211..0ebd1b1c0555 100644 --- a/sys/dev/ice/ice_iov.h +++ b/sys/dev/ice/ice_iov.h @@ -41,6 +41,7 @@ #define _ICE_IOV_H_ #include +#include #include #include #include @@ -91,6 +92,8 @@ struct ice_vf { u16 mac_filter_cnt; u16 vlan_limit; u16 vlan_cnt; +#define ICE_VF_VLAN_MAP_LEN (EVL_VLID_MASK + 1) + bitstr_t bit_decl(vlans_map, ICE_VF_VLAN_MAP_LEN); u16 num_irq_vectors; u16 *vf_imap; diff --git a/sys/dev/ice/ice_lib.c b/sys/dev/ice/ice_lib.c index b92b55208b78..e7dce30222d5 100644 --- a/sys/dev/ice/ice_lib.c +++ b/sys/dev/ice/ice_lib.c @@ -5592,7 +5592,7 @@ ice_add_vlan_hw_filters(struct ice_vsi *vsi, u16 *vid, u16 length) } status = ice_add_vlan(hw, &vlan_list); - if (!status) + if (!status || status == ICE_ERR_ALREADY_EXISTS) goto done; device_printf(vsi->sc->dev, "Failed to add VLAN filters:\n"); @@ -5657,7 +5657,7 @@ ice_remove_vlan_hw_filters(struct ice_vsi *vsi, u16 *vid, u16 length) } status = ice_remove_vlan(hw, &vlan_list); - if (!status) + if (!status || status == ICE_ERR_DOES_NOT_EXIST) goto done; device_printf(vsi->sc->dev, "Failed to remove VLAN filters:\n");