From owner-dev-commits-src-all@freebsd.org Mon Apr 19 19:51:30 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id F31765FD8E1; Mon, 19 Apr 2021 19:51:30 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4FPHWQ6ctZz4nQn; Mon, 19 Apr 2021 19:51:30 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id D61CD254BC; Mon, 19 Apr 2021 19:51:30 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 13JJpUa9052302; Mon, 19 Apr 2021 19:51:30 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 13JJpUud052301; Mon, 19 Apr 2021 19:51:30 GMT (envelope-from git) Date: Mon, 19 Apr 2021 19:51:30 GMT Message-Id: <202104191951.13JJpUud052301@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 4b38eed76da9 - main - e1000: Correct promisc multicast filter handling 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: 4b38eed76da9c36f09bff33b5cf15687cd99016f Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 19 Apr 2021 19:51:31 -0000 The branch main has been updated by kbowling (ports committer): URL: https://cgit.FreeBSD.org/src/commit/?id=4b38eed76da9c36f09bff33b5cf15687cd99016f commit 4b38eed76da9c36f09bff33b5cf15687cd99016f Author: Kevin Bowling AuthorDate: 2021-04-16 23:15:50 +0000 Commit: Kevin Bowling CommitDate: 2021-04-19 19:49:55 +0000 e1000: Correct promisc multicast filter handling There are a number of issues in the e1000 multicast filter handling that have been present for a long time. Take the updated approach from ixgbe(4) which does not have the issues. The issues are outlined in the PR, in particular this solves crossing over and under the hardware's filter limit, not programming the hardware filter when we are above its limit, disabling SBP (show bad packets) when the tunable is enabled and exiting promiscuous mode, and an off-by-one error in the em_copy_maddr function. PR: 140647 Reported by: jtl Reviewed by: markj MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D29789 --- sys/dev/e1000/if_em.c | 62 +++++++++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 79a617b3342f..2c0c8541d7f2 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -303,7 +303,6 @@ static int em_enable_phy_wakeup(struct adapter *); static void em_disable_aspm(struct adapter *); int em_intr(void *arg); -static void em_disable_promisc(if_ctx_t ctx); /* MSI-X handlers */ static int em_if_msix_intr_assign(if_ctx_t, int); @@ -1641,11 +1640,20 @@ static int em_if_set_promisc(if_ctx_t ctx, int flags) { struct adapter *adapter = iflib_get_softc(ctx); + struct ifnet *ifp = iflib_get_ifp(ctx); u32 reg_rctl; - - em_disable_promisc(ctx); + int mcnt = 0; reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); + reg_rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_UPE); + if (flags & IFF_ALLMULTI) + mcnt = MAX_NUM_MULTICAST_ADDRESSES; + else + mcnt = min(if_llmaddr_count(ifp), MAX_NUM_MULTICAST_ADDRESSES); + + if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) + reg_rctl &= (~E1000_RCTL_MPE); + E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); if (flags & IFF_PROMISC) { reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); @@ -1661,37 +1669,15 @@ em_if_set_promisc(if_ctx_t ctx, int flags) return (0); } -static void -em_disable_promisc(if_ctx_t ctx) -{ - struct adapter *adapter = iflib_get_softc(ctx); - struct ifnet *ifp = iflib_get_ifp(ctx); - u32 reg_rctl; - int mcnt = 0; - - reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); - reg_rctl &= (~E1000_RCTL_UPE); - if (if_getflags(ifp) & IFF_ALLMULTI) - mcnt = MAX_NUM_MULTICAST_ADDRESSES; - else - mcnt = if_llmaddr_count(ifp); - /* Don't disable if in MAX groups */ - if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) - reg_rctl &= (~E1000_RCTL_MPE); - reg_rctl &= (~E1000_RCTL_SBP); - E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); -} - - static u_int -em_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) +em_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int idx) { u8 *mta = arg; - if (cnt == MAX_NUM_MULTICAST_ADDRESSES) - return (1); + if (idx == MAX_NUM_MULTICAST_ADDRESSES) + return (0); - bcopy(LLADDR(sdl), &mta[cnt * ETHER_ADDR_LEN], ETHER_ADDR_LEN); + bcopy(LLADDR(sdl), &mta[idx * ETHER_ADDR_LEN], ETHER_ADDR_LEN); return (1); } @@ -1702,14 +1688,13 @@ em_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) * This routine is called whenever multicast address list is updated. * **********************************************************************/ - static void em_if_multi_set(if_ctx_t ctx) { struct adapter *adapter = iflib_get_softc(ctx); struct ifnet *ifp = iflib_get_ifp(ctx); - u32 reg_rctl = 0; u8 *mta; /* Multicast array memory */ + u32 reg_rctl = 0; int mcnt = 0; IOCTL_DEBUGOUT("em_set_multi: begin"); @@ -1729,11 +1714,20 @@ em_if_multi_set(if_ctx_t ctx) mcnt = if_foreach_llmaddr(ifp, em_copy_maddr, mta); - if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES) { - reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); + reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL); + + if (if_getflags(ifp) & IFF_PROMISC) + reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); + else if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES || + if_getflags(ifp) & IFF_ALLMULTI) { reg_rctl |= E1000_RCTL_MPE; - E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); + reg_rctl &= ~E1000_RCTL_UPE; } else + reg_rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); + + E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); + + if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) e1000_update_mc_addr_list(&adapter->hw, mta, mcnt); if (adapter->hw.mac.type == e1000_82542 &&