Received: by 2002:a05:6a10:c604:0:0:0:0 with SMTP id y4csp3762363pxt; Tue, 10 Aug 2021 10:43:53 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxIfSBPfk/GycZmgE8fflsG0snRHS8HdY94s4/dGxUSRr83tRmWem6EGkTSzfF0AabJECDl X-Received: by 2002:a17:906:7d0:: with SMTP id m16mr12392565ejc.105.1628617432603; Tue, 10 Aug 2021 10:43:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1628617432; cv=none; d=google.com; s=arc-20160816; b=Ezkgr3Zr5K3Z4nM+3umnwnGru29MvKkwXyVpxCU0C6oCpGQOXGsEvrcaGaukST3ONo iyrNtR3trhWmep5KImdsHP8wusm3zy0lVgQodxcZzCzSYPtr/g6/JkUzPynfwhMyDAaq pIe8ewBtgSWDlIhoB0zFAeF/ZVuEY0ZS+pTJttwR8fhgCAvZQ4Hf0M7fggh6mixjXrbt iYJJc57USVcWn9hKb0u+Z/1p6dmnDInpKjEFDfPAYo8uuW5GglW+tZX4MnZSVnP+hoU7 XcWLvOWtdd1rQ4i8/tA2wi5fdtq+eaqf1kKHhUKMsiMfT+wz2ZBK9dhRfKLtT8AUfdzE kj2g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=7iUiiBzsGHCqQGCcrEQF3ScWl7KOXd9wZ08ZfngP9hM=; b=0le+BQ6/YOSW1fYTEDxiEM93f6+O48DuFbMRVEX4oupb2XU7B0EcUk/4TVWzwnHWkJ NXoXXjsaeWvhgBW0BwNZ+p5baqajJRTh6oBCFtcrzz1VrFxnVUWS51D0gsQT/McIGGyM /qvraEGRkBz/ylG7GEf/nTGAIEKyKTQ6313906BvrfqZ8D3ZMlqBW9Rlk8X6Su2abItW 7Ff+sdYkRspXitlfigJCVG6fKHF5i6OCQcClWfkLwSsxlBaeqKXJBoagD6jcNaavmI5A vqjAa8BTQh6v4vklnDb66jgT7XNwqYjGTMhzdUiR7G+RIxLDDssDI77Ps8i0cO96ltF7 hYYg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=hfZlWyrh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id hb17si8255938ejb.208.2021.08.10.10.43.26; Tue, 10 Aug 2021 10:43:52 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=hfZlWyrh; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234967AbhHJRiq (ORCPT + 99 others); Tue, 10 Aug 2021 13:38:46 -0400 Received: from mail.kernel.org ([198.145.29.99]:38896 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233516AbhHJRgS (ORCPT ); Tue, 10 Aug 2021 13:36:18 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id B48DA610FD; Tue, 10 Aug 2021 17:35:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1628616933; bh=ZMDDFpqSjtRvjmnYV8p+2q7qGs8S+7d3lJji4BjqxHU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hfZlWyrhAnEEmydTJl+2O9dNDdC1HUi+eut7Di0TzI2s8iFYSexfLwU77nwSnIr99 v6Et1bXBLtaBG9sCGOObNhZP5ROoBRTaIRwmIkCBcBW7xwvmh9ISf/0hx+Z1rXBqVX C9h5hqvaRG4sCD5sXPiNF7wIcgJLOBINiNJBmpvw= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Vladimir Oltean , "David S. Miller" , Sasha Levin Subject: [PATCH 5.4 22/85] net: dsa: sja1105: invalidate dynamic FDB entries learned concurrently with statically added ones Date: Tue, 10 Aug 2021 19:29:55 +0200 Message-Id: <20210810172948.945259392@linuxfoundation.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210810172948.192298392@linuxfoundation.org> References: <20210810172948.192298392@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Vladimir Oltean [ Upstream commit 6c5fc159e0927531707895709eee1f8bfa04289f ] The procedure to add a static FDB entry in sja1105 is concurrent with dynamic learning performed on all bridge ports and the CPU port. The switch looks up the FDB from left to right, and also learns dynamically from left to right, so it is possible that between the moment when we pick up a free slot to install an FDB entry, another slot to the left of that one becomes free due to an address ageing out, and that other slot is then immediately used by the switch to learn dynamically the same address as we're trying to add statically. The result is that we succeeded to add our static FDB entry, but it is being shadowed by a dynamic FDB entry to its left, and the switch will behave as if our static FDB entry did not exist. We cannot really prevent this from happening unless we make the entire process to add a static FDB entry a huge critical section where address learning is temporarily disabled on _all_ ports, and then re-enabled according to the configuration done by sja1105_port_set_learning. However, that is kind of disruptive for the operation of the network. What we can do alternatively is to simply read back the FDB for dynamic entries located before our newly added static one, and delete them. This will guarantee that our static FDB entry is now operational. It will still not guarantee that there aren't dynamic FDB entries to the _right_ of that static FDB entry, but at least those entries will age out by themselves since they aren't hit, and won't bother anyone. Fixes: 291d1e72b756 ("net: dsa: sja1105: Add support for FDB and MDB management") Fixes: 1da73821343c ("net: dsa: sja1105: Add FDB operations for P/Q/R/S series") Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/dsa/sja1105/sja1105_main.c | 57 +++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 54b77eafdf63..a07d8051ec3e 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -992,10 +992,11 @@ static int sja1105et_is_fdb_entry_in_bin(struct sja1105_private *priv, int bin, int sja1105et_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid) { - struct sja1105_l2_lookup_entry l2_lookup = {0}; + struct sja1105_l2_lookup_entry l2_lookup = {0}, tmp; struct sja1105_private *priv = ds->priv; struct device *dev = ds->dev; int last_unused = -1; + int start, end, i; int bin, way, rc; bin = sja1105et_fdb_hash(priv, addr, vid); @@ -1047,6 +1048,29 @@ int sja1105et_fdb_add(struct dsa_switch *ds, int port, if (rc < 0) return rc; + /* Invalidate a dynamically learned entry if that exists */ + start = sja1105et_fdb_index(bin, 0); + end = sja1105et_fdb_index(bin, way); + + for (i = start; i < end; i++) { + rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP, + i, &tmp); + if (rc == -ENOENT) + continue; + if (rc) + return rc; + + if (tmp.macaddr != ether_addr_to_u64(addr) || tmp.vlanid != vid) + continue; + + rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP, + i, NULL, false); + if (rc) + return rc; + + break; + } + return sja1105_static_fdb_change(priv, port, &l2_lookup, true); } @@ -1088,7 +1112,7 @@ int sja1105et_fdb_del(struct dsa_switch *ds, int port, int sja1105pqrs_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid) { - struct sja1105_l2_lookup_entry l2_lookup = {0}; + struct sja1105_l2_lookup_entry l2_lookup = {0}, tmp; struct sja1105_private *priv = ds->priv; int rc, i; @@ -1146,6 +1170,35 @@ skip_finding_an_index: if (rc < 0) return rc; + /* The switch learns dynamic entries and looks up the FDB left to + * right. It is possible that our addition was concurrent with the + * dynamic learning of the same address, so now that the static entry + * has been installed, we are certain that address learning for this + * particular address has been turned off, so the dynamic entry either + * is in the FDB at an index smaller than the static one, or isn't (it + * can also be at a larger index, but in that case it is inactive + * because the static FDB entry will match first, and the dynamic one + * will eventually age out). Search for a dynamically learned address + * prior to our static one and invalidate it. + */ + tmp = l2_lookup; + + rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP, + SJA1105_SEARCH, &tmp); + if (rc < 0) { + dev_err(ds->dev, + "port %d failed to read back entry for %pM vid %d: %pe\n", + port, addr, vid, ERR_PTR(rc)); + return rc; + } + + if (tmp.index < l2_lookup.index) { + rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP, + tmp.index, NULL, false); + if (rc < 0) + return rc; + } + return sja1105_static_fdb_change(priv, port, &l2_lookup, true); } -- 2.30.2