From nobody Thu Sep 17 08:36:28 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 4hlpyB2tBYz6shVr for ; Thu, 17 Sep 2026 08:36:34 +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 4hlpyB25g2z57C5 for ; Thu, 17 Sep 2026 08:36:34 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789634194; 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=nVey1N43roizu1F8I+1k9d7hYt286mpRlzDiAXfo/MSSL3va29M2tgY77vyBNrLFa602wS AtK3nt3+WbnPVvP7a7N44SBNc1lcpOoMwwJdE55IlwCeluO82YuxrOIiSO5z+I9Z7mMPKA anRzhC44kPAfNR8qHyW72d0g4/57eGsiHcVx7G62qkcbEAU51qgoJX+QdargOWRFHgJ1Em I1ZjO/0zcu9bwFIjRJL1zaNvhmCCuI6d4hTC+5FQ+vc/GzlpLze1j3FqrpWQhavhYD7dDz o0DdnA2w6DN93opBrQnQsSaBCL65IaGSF79KM60liyAl2T+eCCCE4EEgCPY2/g== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1789634194; b=rQV6Ein0ExZ3lbIZEeLmmr1hM5L+rtkZepUnn3DKoSkDg/6A1PY+eCdriuBZlCXjOKMKhT PqG6mBiQu4tBkPNtbsXLJYghCXgm2SwaUvXtvN8U0FkPggpdkq1K3ohB8C5dSSeaJR/FOU P7vsULEbVZ+yYHHdhKP5NcxCEIV0zJ0aXtC6dSIKIxluk3xq2QHNTilzIgNQW/WR5ym1ph oWzqipE0eFTLBa0zRAKqXbVx5WEuMvhVOn9CEyY9zOv2Cb6WW6D/+A6uKo/G9omQ2wfYY6 2keWA/5wHjQ494wunvtDV8zP5T3jjRanODyYyYgQN0SjCoZZAm4XNdfVa8FHNw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789634194; 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=QSl5k+NScTqqXjR1n26usxNXIigfCEE4zg6Gmddw2GPsLNXTimzafezaQMRa1NCVmAcjpc h8SmhCmjeb156Nfysy7nPuYyND6d04InLnbijvJj2KgfPqC+xpMCMtfGCRpEJ+wMvTZ7iQ dfYp5XU7oZm95ijs5AGtnmI8N5kty+iXkcZo8DSG2/o7oLJvNvphc6G/+TiiOBry0onF26 g7aFxgbzA74NHm2TEinSbccnRPMqUGANa+oKKcR6NDZ8XcwO6r4pbClPpc3Ia9a1BtiVJu mnPfmB+/mEGlvNKo9bc9DTKA2T4fImh6OuO5jDTYvxqFGpSVqaecNI4vzm1aJw== 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 4hlpyB0rY6zPB1 for ; Thu, 17 Sep 2026 08:36:34 +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 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: 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");