From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.9 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C86C9C43219 for ; Sun, 28 Apr 2019 18:48:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 99AFA20652 for ; Sun, 28 Apr 2019 18:48:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PmfiG2N0" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727180AbfD1SsC (ORCPT ); Sun, 28 Apr 2019 14:48:02 -0400 Received: from mail-wm1-f68.google.com ([209.85.128.68]:50897 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727130AbfD1SsA (ORCPT ); Sun, 28 Apr 2019 14:48:00 -0400 Received: by mail-wm1-f68.google.com with SMTP id p21so9096168wmc.0 for ; Sun, 28 Apr 2019 11:47:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=6iYGSXPGdZMtGj2jzWd5/XwQgHbc2g5MC8wNGgNrAAI=; b=PmfiG2N0mdvvRAwebvPSDPI5RAfiN3nebu8MDJh/IttjjbXP6Nu4UCt3Q3M6GJSnIn NZ8F/J0vTktI7SpowMFbXNaJmu9ds4nmLlHRRyUyCseaClBYxlSMxwwyQQYuQEsgzhnc TYBjkMGM/xrBshqNpVTC2X5OKRUza2hdvhI8iYKDn73o7axj4fJrAgSmUm96Zt+O463u BG0Fr0a4EaR9Bj9VWMdI693XZtjBw6nLh6N+oHV6KhmyrhkhkwOdDjG0vMDmEq4MICaq jxj9MIKGIOM8/b44DxRwdfW5kq4CG9L72BCRe8NlP71pphpwoxzxCs9lYKDlhIbgCOju s68g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=6iYGSXPGdZMtGj2jzWd5/XwQgHbc2g5MC8wNGgNrAAI=; b=UEtU2Tp4KmGmJCp+5OOYiyXRLpreZNLYDQlK/7n1S5/jE6gSZrLX3NnBuhDqCrBaMD eUITQvFuFkCuHRfFPsmuX9uGLPKaqG9vNS2HH9smTxydbWcbvWO9J0pXLaEzRxP/xocI Xj3FQIkXSx6ytXdauxIQzcgL5/HZEXZ2LtguasCOjC3aSA4OoUZJEXXgvEDA55p7kSAP QBcqCRfmzJcWStBxwpxptF/qtMZsY1ljnDwAD/s0K7XnL5SYKrCa5xiDZcB/SO8QT8Zg 0YKovSrQttLWldVcXVwLzMFOcuPJrxqXpFCdls2DVVrrZR8v/wT0BSZTH13NzKc+bZSU Qegg== X-Gm-Message-State: APjAAAWoAI+LJeNajl7BMuDd4Ck0TXHF50cBdBip43jzsY6BlnT0cimf gmeC8MY8665wMgrKuHD4gwE= X-Google-Smtp-Source: APXvYqxHrneFUHzpUmz1HzblR4YqmVusRuWFiCGTJRcfyl0aGo07uR3+/kOlZsMJdNrXlM8NqGHkcw== X-Received: by 2002:a1c:b48a:: with SMTP id d132mr2801739wmf.92.1556477278538; Sun, 28 Apr 2019 11:47:58 -0700 (PDT) Received: from localhost.localdomain (5-12-225-227.residential.rdsnet.ro. [5.12.225.227]) by smtp.gmail.com with ESMTPSA id h5sm12254910wmf.38.2019.04.28.11.47.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 28 Apr 2019 11:47:58 -0700 (PDT) From: Vladimir Oltean To: f.fainelli@gmail.com, vivien.didelot@gmail.com, andrew@lunn.ch, davem@davemloft.net Cc: netdev@vger.kernel.org, Vladimir Oltean Subject: [PATCH net-next 03/13] net: dsa: Be aware of switches where VLAN filtering is a global setting Date: Sun, 28 Apr 2019 21:45:44 +0300 Message-Id: <20190428184554.9968-4-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190428184554.9968-1-olteanv@gmail.com> References: <20190428184554.9968-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org On some switches, the action of whether to parse VLAN frame headers and use that information for ingress admission is configurable, but not per port. Such is the case for the Broadcom BCM53xx and the NXP SJA1105 families, for example. In that case, DSA can prevent the bridge core from trying to apply different VLAN filtering settings on net devices that belong to the same switch. Signed-off-by: Vladimir Oltean Suggested-by: Florian Fainelli Reviewed-by: Florian Fainelli --- include/net/dsa.h | 5 +++++ net/dsa/port.c | 52 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 79a87913126c..aab3c2029edd 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -228,6 +228,11 @@ struct dsa_switch { /* Number of switch port queues */ unsigned int num_tx_queues; + /* Disallow bridge core from requesting different VLAN awareness + * settings on ports if not hardware-supported + */ + bool vlan_filtering_is_global; + unsigned long *bitmap; unsigned long _bitmap; diff --git a/net/dsa/port.c b/net/dsa/port.c index 0caf7f9bfb57..67bfad30cd40 100644 --- a/net/dsa/port.c +++ b/net/dsa/port.c @@ -154,6 +154,39 @@ void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br) dsa_port_set_state_now(dp, BR_STATE_FORWARDING); } +static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp, + bool vlan_filtering) +{ + struct dsa_switch *ds = dp->ds; + int i; + + if (!ds->vlan_filtering_is_global) + return true; + + /* For cases where enabling/disabling VLAN awareness is global to the + * switch, we need to handle the case where multiple bridges span + * different ports of the same switch device and one of them has a + * different setting than what is being requested. + */ + for (i = 0; i < ds->num_ports; i++) { + struct net_device *other_bridge; + + other_bridge = dsa_to_port(ds, i)->bridge_dev; + if (!other_bridge) + continue; + /* If it's the same bridge, it also has same + * vlan_filtering setting => no need to check + */ + if (other_bridge == dp->bridge_dev) + continue; + if (br_vlan_enabled(other_bridge) != vlan_filtering) { + dev_err(ds->dev, "VLAN filtering is a global setting\n"); + return false; + } + } + return true; +} + int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, struct switchdev_trans *trans) { @@ -164,13 +197,18 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, if (switchdev_trans_ph_prepare(trans)) return 0; - if (ds->ops->port_vlan_filtering) { - err = ds->ops->port_vlan_filtering(ds, dp->index, - vlan_filtering); - if (err) - return err; - dp->vlan_filtering = vlan_filtering; - } + if (!ds->ops->port_vlan_filtering) + return 0; + + if (!dsa_port_can_apply_vlan_filtering(dp, vlan_filtering)) + return -EINVAL; + + err = ds->ops->port_vlan_filtering(ds, dp->index, + vlan_filtering); + if (err) + return err; + + dp->vlan_filtering = vlan_filtering; return 0; } -- 2.17.1