From patchwork Sun May 10 16:42:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287249 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=BKveuE6d; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49Kqg06l3Dz9sRf for ; Mon, 11 May 2020 02:45:00 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728990AbgEJQnb (ORCPT ); Sun, 10 May 2020 12:43:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34826 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1726744AbgEJQnb (ORCPT ); Sun, 10 May 2020 12:43:31 -0400 Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DE61BC05BD09; Sun, 10 May 2020 09:43:30 -0700 (PDT) Received: by mail-wr1-x443.google.com with SMTP id g13so7907074wrb.8; Sun, 10 May 2020 09:43:30 -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=8HLKUBcP0NCqjxNIy/DVSzX+QRhK/w5m5uqDn4NFARI=; b=BKveuE6dYDcmvMaG8MCuoloyFU8yj+8glwVkXKt1EzYOTCcAwpW+PiulvbCMAf6PpD SxVfnFRvrv4zYzBdiq3mWZb5/gEkZ/uboGvKx97skPkEdpwRTlXpsNyghpcRuybnSFsT W3mBXQo3UGQTgSgFkuGqAIfCfYmh28IHVXYwSj1O/FzesZQZrod6RasM/mmKW8dhxyyL nE5424AVNLtmuTmgNcAx6kb+FcMKOM+CGdFCkPUP0R4+9nqhyEFqydGWU+qBNdIShzJ9 7zIxt6u4lLHAAnOCruFrR1YGgU9D2os/R8ztn4HKIi7Rsb5nEwkYw2Ulr4ByF7xh2CC3 8USg== 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=8HLKUBcP0NCqjxNIy/DVSzX+QRhK/w5m5uqDn4NFARI=; b=nY3Pf9P6l4bJ31dittWhrT+e4w4R85ve+feGPdosNwMrvFBE+89uTEaWqWUVOX1buX UMCSscWT9Nz+PErJqoDF8GtvN1lapxPQk8XSWq1G+ginwgfsc6Jx2Kn4sPrgmZ1+4dc0 tQeUK99BiZPrM61vuhNMycvf+9n9udvKF4HHFk2nhk7xsGW3baYzOH8XowLuCUlZG6GK RNdp5FcKf8lXtBs6i0dAfwxMttNO1OQukmI3MwhZkPYXUK6g0cB4Yfq6z23zxZhNwb60 ffGXzjOyBtxFQUR1nhKeUSEXRresbfS6bsgGSXy+ayY8RPIhXY0EFEkaxUvF/dMnVbmr XaHA== X-Gm-Message-State: AGi0PuZuH90w/sr3HY00mnkcGru6lb4wGMPoshf12gEvJ2x6x5Va4Zd5 0KXD5hQk+Tq0lFf8m/RriSk= X-Google-Smtp-Source: APiQypLgm8tXTf7mvlxHdNb3P+qljM+sqcbZQU4a0N8/C1+4iBAD4af7aWXhdOPFMNu2Mlx+GhV1bA== X-Received: by 2002:a5d:4dc9:: with SMTP id f9mr4718771wru.407.1589129009598; Sun, 10 May 2020 09:43:29 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:29 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 01/15] net: dsa: provide an option for drivers to always receive bridge VLANs Date: Sun, 10 May 2020 19:42:41 +0300 Message-Id: <20200510164255.19322-2-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Russell King DSA assumes that a bridge which has vlan filtering disabled is not vlan aware, and ignores all vlan configuration. However, the kernel software bridge code allows configuration in this state. This causes the kernel's idea of the bridge vlan state and the hardware state to disagree, so "bridge vlan show" indicates a correct configuration but the hardware lacks all configuration. Even worse, enabling vlan filtering on a DSA bridge immediately blocks all traffic which, given the output of "bridge vlan show", is very confusing. Provide an option that drivers can set to indicate they want to receive vlan configuration even when vlan filtering is disabled. At the very least, this is safe for Marvell DSA bridges, which do not look up ingress traffic in the VTU if the port is in 8021Q disabled state. It is also safe for the Ocelot switch family. Whether this change is suitable for all DSA bridges is not known. Signed-off-by: Russell King Signed-off-by: Vladimir Oltean --- include/net/dsa.h | 1 + net/dsa/slave.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/net/dsa.h b/include/net/dsa.h index 312c2f067e65..c69cee85923e 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -281,6 +281,7 @@ struct dsa_switch { * settings on ports if not hardware-supported */ bool vlan_filtering_is_global; + bool vlan_bridge_vtu; /* In case vlan_filtering_is_global is set, the VLAN awareness state * should be retrieved from here and not from the per-port settings. diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 61b0de52040a..e72ebff86a1f 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -314,7 +314,8 @@ static int dsa_slave_vlan_add(struct net_device *dev, if (obj->orig_dev != dev) return -EOPNOTSUPP; - if (dp->bridge_dev && !br_vlan_enabled(dp->bridge_dev)) + if (dp->bridge_dev && !dp->ds->vlan_bridge_vtu && + !br_vlan_enabled(dp->bridge_dev)) return 0; vlan = *SWITCHDEV_OBJ_PORT_VLAN(obj); @@ -381,7 +382,8 @@ static int dsa_slave_vlan_del(struct net_device *dev, if (obj->orig_dev != dev) return -EOPNOTSUPP; - if (dp->bridge_dev && !br_vlan_enabled(dp->bridge_dev)) + if (dp->bridge_dev && !dp->ds->vlan_bridge_vtu && + !br_vlan_enabled(dp->bridge_dev)) return 0; /* Do not deprogram the CPU port as it may be shared with other user @@ -1240,7 +1242,8 @@ static int dsa_slave_vlan_rx_add_vid(struct net_device *dev, __be16 proto, * need to emulate the switchdev prepare + commit phase. */ if (dp->bridge_dev) { - if (!br_vlan_enabled(dp->bridge_dev)) + if (!dp->ds->vlan_bridge_vtu && + !br_vlan_enabled(dp->bridge_dev)) return 0; /* br_vlan_get_info() returns -EINVAL or -ENOENT if the @@ -1274,7 +1277,8 @@ static int dsa_slave_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, * need to emulate the switchdev prepare + commit phase. */ if (dp->bridge_dev) { - if (!br_vlan_enabled(dp->bridge_dev)) + if (!dp->ds->vlan_bridge_vtu && + !br_vlan_enabled(dp->bridge_dev)) return 0; /* br_vlan_get_info() returns -EINVAL or -ENOENT if the From patchwork Sun May 10 16:42:42 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287248 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=WDOd1kaF; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49Kqfw6vL9z9sNH for ; Mon, 11 May 2020 02:44:56 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729385AbgEJQox (ORCPT ); Sun, 10 May 2020 12:44:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34828 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729057AbgEJQnc (ORCPT ); Sun, 10 May 2020 12:43:32 -0400 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D3B2CC061A0E; Sun, 10 May 2020 09:43:31 -0700 (PDT) Received: by mail-wm1-x344.google.com with SMTP id h4so15411882wmb.4; Sun, 10 May 2020 09:43:31 -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=i3xdQfNNhGs9x7KATPUsqJauaICpGQwRxOGD+fuAb3E=; b=WDOd1kaFFfF1lWYkOl5N2PcGLxEpbfz7Esm+tYr4fNIZKYYKI0JOhhjTECCi7QjL4L 08Su9U7PR5HLZ4qojIQymZE7k/0yRKQCl7FVJhb9P79x/yueTtR1I808yr8YquSmP1tX wSsZgdns1vTP1pWWEOTyXRIIrUoN5qELGV2t/5enTI+MNU/qznCX4ZLwFfoTbcccnQNu ZcNb+xNnOjW4x3bjMfa9/ksBfxXAoHisxsdADVYZ35nVbTaXT96OVkgdtl6KwjYZPckw NdsOc1u+kqyfgcZab3saHgIXv+5vTA5VLzB1jSsyp4s+YRaRMsnozEMxtjm6Zt7y3N5q tkmQ== 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=i3xdQfNNhGs9x7KATPUsqJauaICpGQwRxOGD+fuAb3E=; b=rSTGcxm0+mJHt+4SUwIkDurgcsMCmK9gq0eovf10134etlzapMKX+OaUYS4sbqK5Zr ss9gfmfv/bLuF1k0VTYSgnJXIiZRlvSSEqntTCD6mjYhsRZpqzqqUzIDmSCb9dcebfnd uNd5la3yaDx7RNY854zElQcN8gRyaGOqi687J6w7Y7Wmwk4CY1ZwzCmTgwOaOKjVfggD c+dtIzHXXZqRIES0LrAgRrGrtVwtNonDxbvsb5tdCDRHAVUecKM+b0UkGqJEbY1b48+2 JCS4TSP3FJ8z9koly8aclXLUP7bbW/p91DE7J3jKF5u7JbyyEjyhR6dTtVws+OYc6+ed CJpQ== X-Gm-Message-State: AGi0PubSK/nHHNPcEGGTbB1wd1N4Bx1iOwPUWdFRkLOzSm3o8zLLIU6N HN0RnRfneFJ8mjY+KQmQo5XjZoUk X-Google-Smtp-Source: APiQypIEeFJc0XI3zCN/4DAndO81GyyjKAPeqV2gSbg+qYMYSWvIL/M3C690waMQ+nrRhSZBZl6iLw== X-Received: by 2002:a7b:cc83:: with SMTP id p3mr9078882wma.156.1589129010592; Sun, 10 May 2020 09:43:30 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:30 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 02/15] net: dsa: tag_8021q: introduce a vid_is_dsa_8021q helper Date: Sun, 10 May 2020 19:42:42 +0300 Message-Id: <20200510164255.19322-3-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean This function returns a boolean denoting whether the VLAN passed as argument is part of the 1024-3071 range that the dsa_8021q tagging scheme uses. Signed-off-by: Vladimir Oltean --- include/linux/dsa/8021q.h | 7 +++++++ net/dsa/tag_8021q.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/include/linux/dsa/8021q.h b/include/linux/dsa/8021q.h index b8daaec0896e..ebc245ff838a 100644 --- a/include/linux/dsa/8021q.h +++ b/include/linux/dsa/8021q.h @@ -50,6 +50,8 @@ int dsa_8021q_rx_switch_id(u16 vid); int dsa_8021q_rx_source_port(u16 vid); +bool vid_is_dsa_8021q(u16 vid); + #else int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int index, @@ -107,6 +109,11 @@ int dsa_8021q_rx_source_port(u16 vid) return 0; } +bool vid_is_dsa_8021q(u16 vid) +{ + return false; +} + #endif /* IS_ENABLED(CONFIG_NET_DSA_TAG_8021Q) */ #endif /* _NET_DSA_8021Q_H */ diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c index ff9c5bf64bda..4774ecd1f8fc 100644 --- a/net/dsa/tag_8021q.c +++ b/net/dsa/tag_8021q.c @@ -93,6 +93,13 @@ int dsa_8021q_rx_source_port(u16 vid) } EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port); +bool vid_is_dsa_8021q(u16 vid) +{ + return ((vid & DSA_8021Q_DIR_MASK) == DSA_8021Q_DIR_RX || + (vid & DSA_8021Q_DIR_MASK) == DSA_8021Q_DIR_TX); +} +EXPORT_SYMBOL_GPL(vid_is_dsa_8021q); + static int dsa_8021q_restore_pvid(struct dsa_switch *ds, int port) { struct bridge_vlan_info vinfo; From patchwork Sun May 10 16:42:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287234 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=qmuC8DrO; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49KqdP6mwtz9sRY for ; Mon, 11 May 2020 02:43:37 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729144AbgEJQng (ORCPT ); Sun, 10 May 2020 12:43:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34834 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729124AbgEJQnd (ORCPT ); Sun, 10 May 2020 12:43:33 -0400 Received: from mail-wm1-x343.google.com (mail-wm1-x343.google.com [IPv6:2a00:1450:4864:20::343]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E643FC061A0C; Sun, 10 May 2020 09:43:32 -0700 (PDT) Received: by mail-wm1-x343.google.com with SMTP id g12so16295799wmh.3; Sun, 10 May 2020 09:43:32 -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=S/ucj9FqaJZxqwK6ttNEH98kMzRsUXKRYHBKd01NMJ0=; b=qmuC8DrOSHDAALVQnKjGk39SZNRqnza6L0ea8eY8dl/g/XT06McJ2wGJxUkW2lvqRv zX7YdpS6aDg3Mx4FpRdvaSiYiYKY5SJ8r0lLHbqS2ZMNsER398QdyaxiY0qKrlegxCUm vqsVnYvgJGuxf0nlQVdA/IFGytgT+0hJ516TpfI7LZPhDfRa/qqf3tr2f3qhDqDQufSy ZvXUsajVF4xvji3QONCWgfyKwUkvrLR8tzUWpzGK7joCXp963sXPrceBe9BjFuTHbqYE C/Ip1tSsWdRJSYIx99XdA1dUXajyWwVo2jyYouwj8WmQVenSzjNnz3wawhGtxhsDIUIP Vl9A== 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=S/ucj9FqaJZxqwK6ttNEH98kMzRsUXKRYHBKd01NMJ0=; b=H7MwZ5hFj4L8Fec34zNNiuyoFL3v9r0sCnT1ejUeiU3a3V9NvF2MVLzoKiGDJYYj21 ln+CW4oCyWOosfgjIyFv4t6cy/eK6Eaao01y8Yfjdjcpc25w4ODb772pKqBjiF4FHPSG Ca+l8zb+507+3OxTL1gaLTaFV5pMXFFVU45KYt1M4ZQVAUcu6GycoJKnDhsqycVKiY71 Eiw5fzTMui0T0aG2HuV5BQ5FWK3dSFwlamFUbGNv6/kuscezyLZwqKoOg68eoch8XkDw W547MJqBtVnPQ/zn5Qn/btVAJTSmrEKkG3eXu3gX3SCjgXwdbRJ3COgkvg1CEhKQ6jUl GMjw== X-Gm-Message-State: AGi0PuY7jSbzYOIs6bcviJuzAbAkpv0c6xPviSYM16pow1xSL/UB3yU1 //vPnHqdi2gML9EXJlg6FZQ= X-Google-Smtp-Source: APiQypLPuwUkRPgewra1ItZFSUUfJFbg+CHbvtR1qKra1pq50WTsDjHWt58lOp7rO4KbpLqZO8mSfw== X-Received: by 2002:a1c:7e4e:: with SMTP id z75mr22092030wmc.41.1589129011681; Sun, 10 May 2020 09:43:31 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:31 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 03/15] net: dsa: sja1105: keep the VLAN awareness state in a driver variable Date: Sun, 10 May 2020 19:42:43 +0300 Message-Id: <20200510164255.19322-4-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean Soon we'll add a third operating mode to the driver. Introduce a vlan_state to make things more easy to manage, and use it where applicable. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105.h | 6 ++++++ drivers/net/dsa/sja1105/sja1105_main.c | 16 ++++++++++++++++ include/linux/dsa/sja1105.h | 2 ++ net/dsa/tag_sja1105.c | 2 +- 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index a64ace07b89f..5b2b275d01a7 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -178,6 +178,11 @@ struct sja1105_flow_block { int num_virtual_links; }; +enum sja1105_vlan_state { + SJA1105_VLAN_UNAWARE, + SJA1105_VLAN_FILTERING_FULL, +}; + struct sja1105_private { struct sja1105_static_config static_config; bool rgmii_rx_delay[SJA1105_NUM_PORTS]; @@ -193,6 +198,7 @@ struct sja1105_private { * the switch doesn't confuse them with one another. */ struct mutex mgmt_lock; + enum sja1105_vlan_state vlan_state; struct sja1105_tagger_data tagger_data; struct sja1105_ptp_data ptp_data; struct sja1105_tas_data tas_data; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index d5de9305df25..7dee9b282a1b 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1917,6 +1917,7 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) struct sja1105_l2_lookup_params_entry *l2_lookup_params; struct sja1105_general_params_entry *general_params; struct sja1105_private *priv = ds->priv; + enum sja1105_vlan_state state; struct sja1105_table *table; struct sja1105_rule *rule; u16 tpid, tpid2; @@ -1940,6 +1941,13 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) tpid2 = ETH_P_SJA1105; } + if (!enabled) + state = SJA1105_VLAN_UNAWARE; + else + state = SJA1105_VLAN_FILTERING_FULL; + + priv->vlan_state = state; + table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS]; general_params = table->entries; /* EtherType used to identify inner tagged (C-tag) VLAN traffic */ @@ -1985,6 +1993,14 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) return sja1105_setup_8021q_tagging(ds, !enabled); } +bool sja1105_can_use_vlan_as_tags(struct dsa_switch *ds) +{ + struct sja1105_private *priv = ds->priv; + + return priv->vlan_state != SJA1105_VLAN_FILTERING_FULL; +} +EXPORT_SYMBOL_GPL(sja1105_can_use_vlan_as_tags); + static void sja1105_vlan_add(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan) { diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h index fa5735c353cd..136481ce3c6f 100644 --- a/include/linux/dsa/sja1105.h +++ b/include/linux/dsa/sja1105.h @@ -61,4 +61,6 @@ struct sja1105_port { bool hwts_tx_en; }; +bool sja1105_can_use_vlan_as_tags(struct dsa_switch *ds); + #endif /* _NET_DSA_SJA1105_H */ diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index d553bf36bd41..5368cd34bcf4 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c @@ -74,7 +74,7 @@ static inline bool sja1105_is_meta_frame(const struct sk_buff *skb) */ static bool sja1105_filter(const struct sk_buff *skb, struct net_device *dev) { - if (!dsa_port_is_vlan_filtering(dev->dsa_ptr)) + if (sja1105_can_use_vlan_as_tags(dev->dsa_ptr->ds)) return true; if (sja1105_is_link_local(skb)) return true; From patchwork Sun May 10 16:42:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287246 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=mVQTYMOF; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49Kqfj3s1Fz9sRf for ; Mon, 11 May 2020 02:44:45 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729370AbgEJQoo (ORCPT ); Sun, 10 May 2020 12:44:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34836 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1728600AbgEJQne (ORCPT ); Sun, 10 May 2020 12:43:34 -0400 Received: from mail-wm1-x343.google.com (mail-wm1-x343.google.com [IPv6:2a00:1450:4864:20::343]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 261F9C061A0E; Sun, 10 May 2020 09:43:34 -0700 (PDT) Received: by mail-wm1-x343.google.com with SMTP id y24so16339347wma.4; Sun, 10 May 2020 09:43:34 -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=E8h43DVwyQEgSe9HIpdWtHOas81wEn11zRRa4f/9ZqY=; b=mVQTYMOFooSM6RmZW+EMQJ9xmnGfScaL/MYmCMDzbroi11rHUC42IgfGQhzx0XNuEV jitnnpg5Y2S8DHErQvSv1XUQnrOKDQW+uD9SZy3ToF4bkS+cDZkqNT4g19QuKj9ekdhe gI+ZkGobmo/pameejq0LhGmoIQ9N0t25CjgyX2i95Dyp5vbD4HZvTbu7dG7L3WD8uetq LtVM7BrI/mSzDF6oRgQay+XTdkwgRtq5dhyr6sMgfn8VykPEx4xocL70CIUEPRlNAujY bFUTN/xQQW8ftmmwThBhBJnk+NQRk5TPVg2/FxYWtdrcYo7ch9D8u5j/+Z6GAXLKnR8c 3AIA== 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=E8h43DVwyQEgSe9HIpdWtHOas81wEn11zRRa4f/9ZqY=; b=GgSnkQw00T0v8t07Twk+/uSJw3AYLwQUhjX4odqdWR37tTG3sijRxgcJgj3ZifCjDZ g7uCVhyLLycUrGaplotPN5Puwf9y1uBUJAw0vAEiEuhdE1GOuXWZGHoK4sJ2fHnX8X5S UnpNFzjYjjfAYa1VWBPZNRGNgV/o0JxRuuTvnLBdHIlzDG9Uvcr/42gFU4BZCMlseQIN /OPvRfv4UcvzLCauO+pV128nfs/Jb8pAREV+5wTN59s9UQiB8UCwOIoc4MTTjKb9mqK/ KzLjmfCPO1HgwAc0wyjaiWKF+EG5nEnbfScEc2RHJ7QOPzcaERC0qNnY6K743EiaG48e lGmQ== X-Gm-Message-State: AGi0PuaDMWL/ldXtA2DSyyQ2HZIzy5SpJ8fEFJVV2wg1taF3IsbwUAbt M5HSCSBTRJ9MabtShk1FSro= X-Google-Smtp-Source: APiQypKgVHOV8okpTdmr5fM/KeOlvti8GIAiuavgVTfCo94SN/jcs0VE92Tg0gYmnnvv+lJ5WwSlmg== X-Received: by 2002:a7b:c5d3:: with SMTP id n19mr19754955wmk.21.1589129012851; Sun, 10 May 2020 09:43:32 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:32 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 04/15] net: dsa: sja1105: deny alterations of dsa_8021q VLANs from the bridge Date: Sun, 10 May 2020 19:42:44 +0300 Message-Id: <20200510164255.19322-5-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean At the moment, this can never happen. The 2 modes that we operate in do not permit that: - SJA1105_VLAN_UNAWARE: we are guarded from bridge VLANs added by the user by the DSA core. We will later lift this restriction by setting ds->vlan_bridge_vtu = true, and that is where we'll need it. - SJA1105_VLAN_FILTERING_FULL: in this mode, dsa_8021q configuration is disabled. So the user is free to add these VLANs in the 1024-3071 range. The reason for the patch is that we'll introduce a third VLAN awareness state, where both dsa_8021q as well as the bridge are going to call our .port_vlan_add and .port_vlan_del methods. For that, we need a good way to discriminate between the 2. The easiest (and less intrusive way for upper layers) is to recognize the fact that dsa_8021q configurations are always driven by our driver - we _know_ when a .port_vlan_add method will be called from dsa_8021q because _we_ initiated it. So introduce an expect_dsa_8021q boolean which is only used, at the moment, for blacklisting VLANs in range 1024-3071 in the modes when dsa_8021q is active. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105.h | 1 + drivers/net/dsa/sja1105/sja1105_main.c | 31 +++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index 5b2b275d01a7..667056d0c819 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -198,6 +198,7 @@ struct sja1105_private { * the switch doesn't confuse them with one another. */ struct mutex mgmt_lock; + bool expect_dsa_8021q; enum sja1105_vlan_state vlan_state; struct sja1105_tagger_data tagger_data; struct sja1105_ptp_data ptp_data; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 7dee9b282a1b..78ec97850f96 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1811,15 +1811,19 @@ static int sja1105_crosschip_bridge_join(struct dsa_switch *ds, if (dsa_to_port(ds, port)->bridge_dev != br) continue; + other_priv->expect_dsa_8021q = true; rc = dsa_8021q_crosschip_bridge_join(ds, port, other_ds, other_port, br, &priv->crosschip_links); + other_priv->expect_dsa_8021q = false; if (rc) return rc; + priv->expect_dsa_8021q = true; rc = dsa_8021q_crosschip_bridge_join(other_ds, other_port, ds, port, br, &other_priv->crosschip_links); + priv->expect_dsa_8021q = false; if (rc) return rc; } @@ -1846,12 +1850,16 @@ static void sja1105_crosschip_bridge_leave(struct dsa_switch *ds, if (dsa_to_port(ds, port)->bridge_dev != br) continue; + other_priv->expect_dsa_8021q = true; dsa_8021q_crosschip_bridge_leave(ds, port, other_ds, other_port, br, &priv->crosschip_links); + other_priv->expect_dsa_8021q = false; + priv->expect_dsa_8021q = true; dsa_8021q_crosschip_bridge_leave(other_ds, other_port, ds, port, br, &other_priv->crosschip_links); + priv->expect_dsa_8021q = false; } } @@ -1862,8 +1870,10 @@ static int sja1105_replay_crosschip_vlans(struct dsa_switch *ds, bool enabled) int rc; list_for_each_entry(c, &priv->crosschip_links, list) { + priv->expect_dsa_8021q = true; rc = dsa_8021q_crosschip_link_apply(ds, c->port, c->other_ds, c->other_port, enabled); + priv->expect_dsa_8021q = false; if (rc) break; } @@ -1873,10 +1883,13 @@ static int sja1105_replay_crosschip_vlans(struct dsa_switch *ds, bool enabled) static int sja1105_setup_8021q_tagging(struct dsa_switch *ds, bool enabled) { + struct sja1105_private *priv = ds->priv; int rc, i; for (i = 0; i < SJA1105_NUM_PORTS; i++) { + priv->expect_dsa_8021q = true; rc = dsa_port_setup_8021q_tagging(ds, i, enabled); + priv->expect_dsa_8021q = false; if (rc < 0) { dev_err(ds->dev, "Failed to setup VLAN tagging for port %d: %d\n", i, rc); @@ -1901,10 +1914,26 @@ sja1105_get_tag_protocol(struct dsa_switch *ds, int port, return DSA_TAG_PROTO_SJA1105; } -/* This callback needs to be present */ static int sja1105_vlan_prepare(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan) { + struct sja1105_private *priv = ds->priv; + u16 vid; + + if (priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) + return 0; + + /* If the user wants best-effort VLAN filtering (aka vlan_filtering + * bridge plus tagging), be sure to at least deny alterations to the + * configuration done by dsa_8021q. + */ + for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { + if (!priv->expect_dsa_8021q && vid_is_dsa_8021q(vid)) { + dev_err(ds->dev, "Range 1024-3071 reserved for dsa_8021q operation\n"); + return -EBUSY; + } + } + return 0; } From patchwork Sun May 10 16:42:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287245 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=B7/XkouH; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49Kqff6PTLz9sRK for ; Mon, 11 May 2020 02:44:42 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729357AbgEJQoh (ORCPT ); Sun, 10 May 2020 12:44:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34844 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729135AbgEJQnf (ORCPT ); Sun, 10 May 2020 12:43:35 -0400 Received: from mail-wm1-x342.google.com (mail-wm1-x342.google.com [IPv6:2a00:1450:4864:20::342]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 65010C061A0C; Sun, 10 May 2020 09:43:35 -0700 (PDT) Received: by mail-wm1-x342.google.com with SMTP id g14so5031030wme.1; Sun, 10 May 2020 09:43:35 -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=lXWEF0lFPnL1sJpICuLXl9aEJQHRS6Q0fzltLMvwdoY=; b=B7/XkouHbjfzgAvLK9KSWHtt7VRkZX+xn8ksA2GsVNtHRFOxER/hKji4FRALeNtmUk S+ANfiuFu39D5VlV9M/LYGYZonu6oSzTfquObLUak/uAzYTbbwFh5AxCA0/02KEZBGBX eK3tEfexmivKKu2RZ56qfNNqh0uJZ7Opnvd0FaSWBeR43uDv6C704haBMd2wp0YfckUW hohfDMm79oZ3SpAlRZ8tr7BtEKd/+kz5/bcg+dLzHDS40BaFARcqr2rB3XdWAZ4XAiMF O+jDLCuzBtaPpB48nQiEQsJMpUNsBNFjPq8VGtGZyKduaWx7s2gfh1duoxktXgJA7zDB veoQ== 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=lXWEF0lFPnL1sJpICuLXl9aEJQHRS6Q0fzltLMvwdoY=; b=qWhulhW+T/fIWFET3C+W+jITK6CHN37T6EwOIuDIV6lRDdeajYYu8aSba7BHS/N73o hn+ldzFoMnxGVQ1QuXur1MSBn5lY3tSMPWN05W7slpm3ZnfxYA2iTqJKJb+R9o2gXCDo 1JqqXIeVAS+2d8VKf1DjLeU0a/VnI1x1UOMCCy0ROqJQeSh+JDW7Xl/iMk+lvLUS75wk Y07ukg3OzszQ6L8o4MjTbV/xw3u/kbbjGJwoueIHqYtW+NiIoSMrALNwWRCqyBQ1JSH0 vn8CAjz2N6QrgbYUvtRDMQuIgPQscOj3EeqINwWsfWug+4e6IuKkqmW3h8bG8vbGMzQp VtYg== X-Gm-Message-State: AGi0Pub3fYvqE7F8/e20N+NrEx0AlQSpB1THwPcCsAcbvw7mPIOGE4cE fjUMe2t1jk8P+h+OsDG0AgIbwrim X-Google-Smtp-Source: APiQypL5koCU406/XPdaoQ1BgnuNSFMVAxEmuw1g3nKcs07AFys4cN3ppCIlO1Xh08f10wptXwSwcA== X-Received: by 2002:a7b:ca54:: with SMTP id m20mr27694560wml.45.1589129013946; Sun, 10 May 2020 09:43:33 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:33 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 05/15] net: dsa: sja1105: save/restore VLANs using a delta commit method Date: Sun, 10 May 2020 19:42:45 +0300 Message-Id: <20200510164255.19322-6-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean Managing the VLAN table that is present in hardware will become very difficult once we add a third operating state (best_effort_vlan_filtering). That is because correct cleanup (not too little, not too much) becomes virtually impossible, when VLANs can be added from the bridge layer, from dsa_8021q for basic tagging, for cross-chip bridging, as well as retagging rules for sub-VLANs and cross-chip sub-VLANs. So we need to rethink VLAN interaction with the switch in a more scalable way. In preparation for that, use the priv->expect_dsa_8021q boolean to classify any VLAN request received through .port_vlan_add or .port_vlan_del towards either one of 2 internal lists: bridge VLANs and dsa_8021q VLANs. Then, implement a central sja1105_build_vlan_table method that creates a VLAN configuration from scratch based on the 2 lists of VLANs kept by the driver, and based on the VLAN awareness state. Currently, if we are VLAN-unaware, install the dsa_8021q VLANs, otherwise the bridge VLANs. Then, implement a delta commit procedure that identifies which VLANs from this new configuration are actually different from the config previously committed to hardware. We apply the delta through the dynamic configuration interface (we don't reset the switch). The result is that the hardware should see the exact sequence of operations as before this patch. This also helps remove the "br" argument passed to dsa_8021q_crosschip_bridge_join, which it was only using to figure out whether it should commit the configuration back to us or not, based on the VLAN awareness state of the bridge. We can simplify that, by always allowing those VLANs inside of our dsa_8021q_vlans list, and committing those to hardware when necessary. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105.h | 10 + drivers/net/dsa/sja1105/sja1105_main.c | 453 ++++++++++++++++++------- include/linux/dsa/8021q.h | 19 +- net/dsa/tag_8021q.c | 45 +-- 4 files changed, 359 insertions(+), 168 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index 667056d0c819..c80f1999c694 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -178,6 +178,14 @@ struct sja1105_flow_block { int num_virtual_links; }; +struct sja1105_bridge_vlan { + struct list_head list; + int port; + u16 vid; + bool pvid; + bool untagged; +}; + enum sja1105_vlan_state { SJA1105_VLAN_UNAWARE, SJA1105_VLAN_FILTERING_FULL, @@ -191,6 +199,8 @@ struct sja1105_private { struct gpio_desc *reset_gpio; struct spi_device *spidev; struct dsa_switch *ds; + struct list_head dsa_8021q_vlans; + struct list_head bridge_vlans; struct list_head crosschip_links; struct sja1105_flow_block flow_block; struct sja1105_port ports[SJA1105_NUM_PORTS]; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 78ec97850f96..8aa8bbcce6e3 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1717,82 +1717,6 @@ static int sja1105_pvid_apply(struct sja1105_private *priv, int port, u16 pvid) &mac[port], true); } -static int sja1105_is_vlan_configured(struct sja1105_private *priv, u16 vid) -{ - struct sja1105_vlan_lookup_entry *vlan; - int count, i; - - vlan = priv->static_config.tables[BLK_IDX_VLAN_LOOKUP].entries; - count = priv->static_config.tables[BLK_IDX_VLAN_LOOKUP].entry_count; - - for (i = 0; i < count; i++) - if (vlan[i].vlanid == vid) - return i; - - /* Return an invalid entry index if not found */ - return -1; -} - -static int sja1105_vlan_apply(struct sja1105_private *priv, int port, u16 vid, - bool enabled, bool untagged) -{ - struct sja1105_vlan_lookup_entry *vlan; - struct sja1105_table *table; - bool keep = true; - int match, rc; - - table = &priv->static_config.tables[BLK_IDX_VLAN_LOOKUP]; - - match = sja1105_is_vlan_configured(priv, vid); - if (match < 0) { - /* Can't delete a missing entry. */ - if (!enabled) - return 0; - rc = sja1105_table_resize(table, table->entry_count + 1); - if (rc) - return rc; - match = table->entry_count - 1; - } - /* Assign pointer after the resize (it's new memory) */ - vlan = table->entries; - vlan[match].vlanid = vid; - if (enabled) { - vlan[match].vlan_bc |= BIT(port); - vlan[match].vmemb_port |= BIT(port); - } else { - vlan[match].vlan_bc &= ~BIT(port); - vlan[match].vmemb_port &= ~BIT(port); - } - /* Also unset tag_port if removing this VLAN was requested, - * just so we don't have a confusing bitmap (no practical purpose). - */ - if (untagged || !enabled) - vlan[match].tag_port &= ~BIT(port); - else - vlan[match].tag_port |= BIT(port); - /* If there's no port left as member of this VLAN, - * it's time for it to go. - */ - if (!vlan[match].vmemb_port) - keep = false; - - dev_dbg(priv->ds->dev, - "%s: port %d, vid %llu, broadcast domain 0x%llx, " - "port members 0x%llx, tagged ports 0x%llx, keep %d\n", - __func__, port, vlan[match].vlanid, vlan[match].vlan_bc, - vlan[match].vmemb_port, vlan[match].tag_port, keep); - - rc = sja1105_dynamic_config_write(priv, BLK_IDX_VLAN_LOOKUP, vid, - &vlan[match], keep); - if (rc < 0) - return rc; - - if (!keep) - return sja1105_table_delete_entry(table, match); - - return 0; -} - static int sja1105_crosschip_bridge_join(struct dsa_switch *ds, int tree_index, int sw_index, int other_port, struct net_device *br) @@ -1813,7 +1737,7 @@ static int sja1105_crosschip_bridge_join(struct dsa_switch *ds, other_priv->expect_dsa_8021q = true; rc = dsa_8021q_crosschip_bridge_join(ds, port, other_ds, - other_port, br, + other_port, &priv->crosschip_links); other_priv->expect_dsa_8021q = false; if (rc) @@ -1821,7 +1745,7 @@ static int sja1105_crosschip_bridge_join(struct dsa_switch *ds, priv->expect_dsa_8021q = true; rc = dsa_8021q_crosschip_bridge_join(other_ds, other_port, ds, - port, br, + port, &other_priv->crosschip_links); priv->expect_dsa_8021q = false; if (rc) @@ -1852,35 +1776,16 @@ static void sja1105_crosschip_bridge_leave(struct dsa_switch *ds, other_priv->expect_dsa_8021q = true; dsa_8021q_crosschip_bridge_leave(ds, port, other_ds, other_port, - br, &priv->crosschip_links); + &priv->crosschip_links); other_priv->expect_dsa_8021q = false; priv->expect_dsa_8021q = true; - dsa_8021q_crosschip_bridge_leave(other_ds, other_port, ds, - port, br, + dsa_8021q_crosschip_bridge_leave(other_ds, other_port, ds, port, &other_priv->crosschip_links); priv->expect_dsa_8021q = false; } } -static int sja1105_replay_crosschip_vlans(struct dsa_switch *ds, bool enabled) -{ - struct sja1105_private *priv = ds->priv; - struct dsa_8021q_crosschip_link *c; - int rc; - - list_for_each_entry(c, &priv->crosschip_links, list) { - priv->expect_dsa_8021q = true; - rc = dsa_8021q_crosschip_link_apply(ds, c->port, c->other_ds, - c->other_port, enabled); - priv->expect_dsa_8021q = false; - if (rc) - break; - } - - return rc; -} - static int sja1105_setup_8021q_tagging(struct dsa_switch *ds, bool enabled) { struct sja1105_private *priv = ds->priv; @@ -1896,11 +1801,6 @@ static int sja1105_setup_8021q_tagging(struct dsa_switch *ds, bool enabled) return rc; } } - rc = sja1105_replay_crosschip_vlans(ds, enabled); - if (rc) { - dev_err(ds->dev, "Failed to replay crosschip VLANs: %d\n", rc); - return rc; - } dev_info(ds->dev, "%s switch tagging\n", enabled ? "Enabled" : "Disabled"); @@ -1914,6 +1814,272 @@ sja1105_get_tag_protocol(struct dsa_switch *ds, int port, return DSA_TAG_PROTO_SJA1105; } +static int sja1105_is_vlan_configured(struct sja1105_private *priv, u16 vid) +{ + struct sja1105_vlan_lookup_entry *vlan; + int count, i; + + vlan = priv->static_config.tables[BLK_IDX_VLAN_LOOKUP].entries; + count = priv->static_config.tables[BLK_IDX_VLAN_LOOKUP].entry_count; + + for (i = 0; i < count; i++) + if (vlan[i].vlanid == vid) + return i; + + /* Return an invalid entry index if not found */ + return -1; +} + +static int sja1105_commit_vlans(struct sja1105_private *priv, + struct sja1105_vlan_lookup_entry *new_vlan) +{ + struct sja1105_vlan_lookup_entry *vlan; + struct sja1105_table *table; + int num_vlans = 0; + int rc, i, k = 0; + + /* VLAN table */ + table = &priv->static_config.tables[BLK_IDX_VLAN_LOOKUP]; + vlan = table->entries; + + for (i = 0; i < VLAN_N_VID; i++) { + int match = sja1105_is_vlan_configured(priv, i); + + if (new_vlan[i].vlanid != VLAN_N_VID) + num_vlans++; + + if (new_vlan[i].vlanid == VLAN_N_VID && match >= 0) { + /* Was there before, no longer is. Delete */ + dev_dbg(priv->ds->dev, "Deleting VLAN %d\n", i); + rc = sja1105_dynamic_config_write(priv, + BLK_IDX_VLAN_LOOKUP, + i, &vlan[match], false); + if (rc < 0) + return rc; + } else if (new_vlan[i].vlanid != VLAN_N_VID) { + /* Nothing changed, don't do anything */ + if (match >= 0 && + vlan[match].vlanid == new_vlan[i].vlanid && + vlan[match].tag_port == new_vlan[i].tag_port && + vlan[match].vlan_bc == new_vlan[i].vlan_bc && + vlan[match].vmemb_port == new_vlan[i].vmemb_port) + continue; + /* Update entry */ + dev_dbg(priv->ds->dev, "Updating VLAN %d\n", i); + rc = sja1105_dynamic_config_write(priv, + BLK_IDX_VLAN_LOOKUP, + i, &new_vlan[i], + true); + if (rc < 0) + return rc; + } + } + + if (table->entry_count) + kfree(table->entries); + + table->entries = kcalloc(num_vlans, table->ops->unpacked_entry_size, + GFP_KERNEL); + if (!table->entries) + return -ENOMEM; + + table->entry_count = num_vlans; + vlan = table->entries; + + for (i = 0; i < VLAN_N_VID; i++) { + if (new_vlan[i].vlanid == VLAN_N_VID) + continue; + vlan[k++] = new_vlan[i]; + } + + return 0; +} + +struct sja1105_crosschip_switch { + struct list_head list; + struct dsa_switch *other_ds; +}; + +static int sja1105_commit_pvid(struct sja1105_private *priv) +{ + struct sja1105_bridge_vlan *v; + struct list_head *vlan_list; + int rc = 0; + + if (priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) + vlan_list = &priv->bridge_vlans; + else + vlan_list = &priv->dsa_8021q_vlans; + + list_for_each_entry(v, vlan_list, list) { + if (v->pvid) { + rc = sja1105_pvid_apply(priv, v->port, v->vid); + if (rc) + break; + } + } + + return rc; +} + +static int +sja1105_build_bridge_vlans(struct sja1105_private *priv, + struct sja1105_vlan_lookup_entry *new_vlan) +{ + struct sja1105_bridge_vlan *v; + + if (priv->vlan_state == SJA1105_VLAN_UNAWARE) + return 0; + + list_for_each_entry(v, &priv->bridge_vlans, list) { + int match = v->vid; + + new_vlan[match].vlanid = v->vid; + new_vlan[match].vmemb_port |= BIT(v->port); + new_vlan[match].vlan_bc |= BIT(v->port); + if (!v->untagged) + new_vlan[match].tag_port |= BIT(v->port); + } + + return 0; +} + +static int +sja1105_build_dsa_8021q_vlans(struct sja1105_private *priv, + struct sja1105_vlan_lookup_entry *new_vlan) +{ + struct sja1105_bridge_vlan *v; + + if (priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) + return 0; + + list_for_each_entry(v, &priv->dsa_8021q_vlans, list) { + int match = v->vid; + + new_vlan[match].vlanid = v->vid; + new_vlan[match].vmemb_port |= BIT(v->port); + new_vlan[match].vlan_bc |= BIT(v->port); + if (!v->untagged) + new_vlan[match].tag_port |= BIT(v->port); + } + + return 0; +} + +static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify); + +static int sja1105_notify_crosschip_switches(struct sja1105_private *priv) +{ + struct sja1105_crosschip_switch *s, *pos; + struct list_head crosschip_switches; + struct dsa_8021q_crosschip_link *c; + int rc = 0; + + INIT_LIST_HEAD(&crosschip_switches); + + list_for_each_entry(c, &priv->crosschip_links, list) { + bool already_added = false; + + list_for_each_entry(s, &crosschip_switches, list) { + if (s->other_ds == c->other_ds) { + already_added = true; + break; + } + } + + if (already_added) + continue; + + s = kzalloc(sizeof(*s), GFP_KERNEL); + if (!s) { + dev_err(priv->ds->dev, "Failed to allocate memory\n"); + rc = -ENOMEM; + goto out; + } + s->other_ds = c->other_ds; + list_add(&s->list, &crosschip_switches); + } + + list_for_each_entry(s, &crosschip_switches, list) { + struct sja1105_private *other_priv = s->other_ds->priv; + + rc = sja1105_build_vlan_table(other_priv, false); + if (rc) + goto out; + } + +out: + list_for_each_entry_safe(s, pos, &crosschip_switches, list) { + list_del(&s->list); + kfree(s); + } + + return rc; +} + +static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) +{ + struct sja1105_vlan_lookup_entry *new_vlan; + struct sja1105_table *table; + int rc; + int i; + + table = &priv->static_config.tables[BLK_IDX_VLAN_LOOKUP]; + new_vlan = kcalloc(VLAN_N_VID, + table->ops->unpacked_entry_size, GFP_KERNEL); + if (!new_vlan) + return -ENOMEM; + + for (i = 0; i < VLAN_N_VID; i++) + new_vlan[i].vlanid = VLAN_N_VID; + + /* Bridge VLANs */ + rc = sja1105_build_bridge_vlans(priv, new_vlan); + if (rc) + goto out; + + /* VLANs necessary for dsa_8021q operation, given to us by tag_8021q.c: + * - RX VLANs + * - TX VLANs + * - Crosschip links + */ + rc = sja1105_build_dsa_8021q_vlans(priv, new_vlan); + if (rc) + goto out; + + rc = sja1105_commit_vlans(priv, new_vlan); + if (rc) + goto out; + + rc = sja1105_commit_pvid(priv); + if (rc) + goto out; + + if (notify) { + rc = sja1105_notify_crosschip_switches(priv); + if (rc) + goto out; + } + +out: + kfree(new_vlan); + + return rc; +} + +/* Select the list to which we should add this VLAN. */ +static struct list_head *sja1105_classify_vlan(struct sja1105_private *priv, + u16 vid) +{ + if (priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) + return &priv->bridge_vlans; + + if (priv->expect_dsa_8021q) + return &priv->dsa_8021q_vlans; + + return &priv->bridge_vlans; +} + static int sja1105_vlan_prepare(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan) { @@ -2034,45 +2200,80 @@ static void sja1105_vlan_add(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan) { struct sja1105_private *priv = ds->priv; + bool vlan_table_changed = false; u16 vid; int rc; for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { - rc = sja1105_vlan_apply(priv, port, vid, true, vlan->flags & - BRIDGE_VLAN_INFO_UNTAGGED); - if (rc < 0) { - dev_err(ds->dev, "Failed to add VLAN %d to port %d: %d\n", - vid, port, rc); - return; - } - if (vlan->flags & BRIDGE_VLAN_INFO_PVID) { - rc = sja1105_pvid_apply(ds->priv, port, vid); - if (rc < 0) { - dev_err(ds->dev, "Failed to set pvid %d on port %d: %d\n", - vid, port, rc); - return; + bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; + bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; + struct sja1105_bridge_vlan *v; + struct list_head *vlan_list; + bool already_added = false; + + vlan_list = sja1105_classify_vlan(priv, vid); + + list_for_each_entry(v, vlan_list, list) { + if (v->port == port && v->vid == vid && + v->untagged == untagged && v->pvid == pvid) { + already_added = true; + break; } } + + if (already_added) + continue; + + v = kzalloc(sizeof(*v), GFP_KERNEL); + if (!v) { + dev_err(ds->dev, "Out of memory while storing VLAN\n"); + return; + } + + v->port = port; + v->vid = vid; + v->untagged = untagged; + v->pvid = pvid; + list_add(&v->list, vlan_list); + + vlan_table_changed = true; } + + if (!vlan_table_changed) + return; + + rc = sja1105_build_vlan_table(priv, true); + if (rc) + dev_err(ds->dev, "Failed to build VLAN table: %d\n", rc); } static int sja1105_vlan_del(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan) { struct sja1105_private *priv = ds->priv; + bool vlan_table_changed = false; u16 vid; - int rc; for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) { - rc = sja1105_vlan_apply(priv, port, vid, false, vlan->flags & - BRIDGE_VLAN_INFO_UNTAGGED); - if (rc < 0) { - dev_err(ds->dev, "Failed to remove VLAN %d from port %d: %d\n", - vid, port, rc); - return rc; + struct sja1105_bridge_vlan *v, *n; + struct list_head *vlan_list; + + vlan_list = sja1105_classify_vlan(priv, vid); + + list_for_each_entry_safe(v, n, vlan_list, list) { + if (v->port == port && v->vid == vid) { + list_del(&v->list); + kfree(v); + vlan_table_changed = true; + break; + } } } - return 0; + + if (!vlan_table_changed) + return 0; + + return sja1105_build_vlan_table(priv, true); } /* The programming model for the SJA1105 switch is "all-at-once" via static @@ -2606,6 +2807,8 @@ static int sja1105_probe(struct spi_device *spi) mutex_init(&priv->mgmt_lock); INIT_LIST_HEAD(&priv->crosschip_links); + INIT_LIST_HEAD(&priv->bridge_vlans); + INIT_LIST_HEAD(&priv->dsa_8021q_vlans); sja1105_tas_setup(ds); sja1105_flower_setup(ds); diff --git a/include/linux/dsa/8021q.h b/include/linux/dsa/8021q.h index ebc245ff838a..404bd2cce642 100644 --- a/include/linux/dsa/8021q.h +++ b/include/linux/dsa/8021q.h @@ -25,18 +25,14 @@ struct dsa_8021q_crosschip_link { int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int index, bool enabled); -int dsa_8021q_crosschip_link_apply(struct dsa_switch *ds, int port, - struct dsa_switch *other_ds, - int other_port, bool enabled); - int dsa_8021q_crosschip_bridge_join(struct dsa_switch *ds, int port, struct dsa_switch *other_ds, - int other_port, struct net_device *br, + int other_port, struct list_head *crosschip_links); int dsa_8021q_crosschip_bridge_leave(struct dsa_switch *ds, int port, struct dsa_switch *other_ds, - int other_port, struct net_device *br, + int other_port, struct list_head *crosschip_links); struct sk_buff *dsa_8021q_xmit(struct sk_buff *skb, struct net_device *netdev, @@ -60,16 +56,9 @@ int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int index, return 0; } -int dsa_8021q_crosschip_link_apply(struct dsa_switch *ds, int port, - struct dsa_switch *other_ds, - int other_port, bool enabled) -{ - return 0; -} - int dsa_8021q_crosschip_bridge_join(struct dsa_switch *ds, int port, struct dsa_switch *other_ds, - int other_port, struct net_device *br, + int other_port, struct list_head *crosschip_links) { return 0; @@ -77,7 +66,7 @@ int dsa_8021q_crosschip_bridge_join(struct dsa_switch *ds, int port, int dsa_8021q_crosschip_bridge_leave(struct dsa_switch *ds, int port, struct dsa_switch *other_ds, - int other_port, struct net_device *br, + int other_port, struct list_head *crosschip_links) { return 0; diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c index 4774ecd1f8fc..3236fbbf85b9 100644 --- a/net/dsa/tag_8021q.c +++ b/net/dsa/tag_8021q.c @@ -296,9 +296,9 @@ int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int port, bool enabled) } EXPORT_SYMBOL_GPL(dsa_port_setup_8021q_tagging); -int dsa_8021q_crosschip_link_apply(struct dsa_switch *ds, int port, - struct dsa_switch *other_ds, - int other_port, bool enabled) +static int dsa_8021q_crosschip_link_apply(struct dsa_switch *ds, int port, + struct dsa_switch *other_ds, + int other_port, bool enabled) { u16 rx_vid = dsa_8021q_rx_vid(ds, port); @@ -308,7 +308,6 @@ int dsa_8021q_crosschip_link_apply(struct dsa_switch *ds, int port, return dsa_8021q_vid_apply(other_ds, other_port, rx_vid, BRIDGE_VLAN_INFO_UNTAGGED, enabled); } -EXPORT_SYMBOL_GPL(dsa_8021q_crosschip_link_apply); static int dsa_8021q_crosschip_link_add(struct dsa_switch *ds, int port, struct dsa_switch *other_ds, @@ -369,7 +368,7 @@ static void dsa_8021q_crosschip_link_del(struct dsa_switch *ds, */ int dsa_8021q_crosschip_bridge_join(struct dsa_switch *ds, int port, struct dsa_switch *other_ds, - int other_port, struct net_device *br, + int other_port, struct list_head *crosschip_links) { /* @other_upstream is how @other_ds reaches us. If we are part @@ -385,12 +384,10 @@ int dsa_8021q_crosschip_bridge_join(struct dsa_switch *ds, int port, if (rc) return rc; - if (!br_vlan_enabled(br)) { - rc = dsa_8021q_crosschip_link_apply(ds, port, other_ds, - other_port, true); - if (rc) - return rc; - } + rc = dsa_8021q_crosschip_link_apply(ds, port, other_ds, + other_port, true); + if (rc) + return rc; rc = dsa_8021q_crosschip_link_add(ds, port, other_ds, other_upstream, @@ -398,20 +395,14 @@ int dsa_8021q_crosschip_bridge_join(struct dsa_switch *ds, int port, if (rc) return rc; - if (!br_vlan_enabled(br)) { - rc = dsa_8021q_crosschip_link_apply(ds, port, other_ds, - other_upstream, true); - if (rc) - return rc; - } - - return 0; + return dsa_8021q_crosschip_link_apply(ds, port, other_ds, + other_upstream, true); } EXPORT_SYMBOL_GPL(dsa_8021q_crosschip_bridge_join); int dsa_8021q_crosschip_bridge_leave(struct dsa_switch *ds, int port, struct dsa_switch *other_ds, - int other_port, struct net_device *br, + int other_port, struct list_head *crosschip_links) { int other_upstream = dsa_upstream_port(other_ds, other_port); @@ -431,14 +422,12 @@ int dsa_8021q_crosschip_bridge_leave(struct dsa_switch *ds, int port, if (keep) continue; - if (!br_vlan_enabled(br)) { - rc = dsa_8021q_crosschip_link_apply(ds, port, - other_ds, - other_port, - false); - if (rc) - return rc; - } + rc = dsa_8021q_crosschip_link_apply(ds, port, + other_ds, + other_port, + false); + if (rc) + return rc; } } From patchwork Sun May 10 16:42:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287243 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=dM9ZHwFF; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49KqfP1mGbz9sRY for ; Mon, 11 May 2020 02:44:29 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729179AbgEJQnj (ORCPT ); Sun, 10 May 2020 12:43:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34846 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729154AbgEJQng (ORCPT ); Sun, 10 May 2020 12:43:36 -0400 Received: from mail-wm1-x342.google.com (mail-wm1-x342.google.com [IPv6:2a00:1450:4864:20::342]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5CEAAC061A0C; Sun, 10 May 2020 09:43:36 -0700 (PDT) Received: by mail-wm1-x342.google.com with SMTP id n5so1408979wmd.0; Sun, 10 May 2020 09:43:36 -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=t2q/+kLZ8m4kfHoubHx5th7aZ54O84h5KKZCd08nJiA=; b=dM9ZHwFFiD/nMLUKsOG3Q2sWk19Mzy4hM6XJqIPpNwM91zjHE7qRHXNFy+olPdIX6r 9N/1oGYHjmqZO1V79LEop/82rhc7NQoNQZHjDO+92Io4UO6UvT62XWuldN+VxkPPjaBt /+UPpR7iFoa2o5htERSvrT9l5PgJwe0DmUpugR5hZfHcCk3qLXTLUWOgnO0/w2DnVZNH UhsDeCgBMIZ+aGP3iZkrrCaQTjhfeesWn4VtTjNfbqSQbWCnYboI/sD1sWDTthifbs+q 9560VT2C1C0SBzK9+xL7q9Rzk8MG2vlX9xYJoLo04R2flUZFKWM9XHY6ZmpMjPkoA5xY +rHw== 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=t2q/+kLZ8m4kfHoubHx5th7aZ54O84h5KKZCd08nJiA=; b=PFP1yer0Ipw1RxY9E1uOUMkgJszOWcZwX3fC3S42CZWjPwTeFfPNCA2UnE1X12ndAf wMP2Sgr+mOMc8uVTr6RnGEc3xaUAH3H4FLZS75nbduDnBLHLi8aSVs8AV2XbMyXTxEBu LzgzrfODzfBSxuUZ8y2AvAOkuqC3fm4SkumaRcSacxgIcHo9uRQB5J5gKOwjF+OPK8Uh IuS2daJJ79v1wdGYlSxOLP1gFFMgT2w/j+XT/tLEIRhvlnCPbh7LBTFcxkdku9hPeqfs LZXcNj+KroKiNqQssQ8JPQrj3Idy/xO8pGSh4PYJFZ90TUVg3N9Ia+NPmd0fxcEgnIi2 OfHA== X-Gm-Message-State: AGi0PuaRmLpcX4xqM8XNaKbepCAWudLsvkAOCBNXHpt4aiBnXHQP/TP1 PO47IC2e82peVJBLBwQX1es= X-Google-Smtp-Source: APiQypILCo/4dSdM6QHiJb7NYT4z88Ubo7nmyKX7+E28fYgJOtkW+SmuoWHlRhS5sOdyAkkluaBbHA== X-Received: by 2002:a1c:a793:: with SMTP id q141mr5890557wme.135.1589129015099; Sun, 10 May 2020 09:43:35 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:34 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 06/15] net: dsa: sja1105: allow VLAN configuration from the bridge in all states Date: Sun, 10 May 2020 19:42:46 +0300 Message-Id: <20200510164255.19322-7-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean Let the DSA core call our .port_vlan_add methods every time the bridge layer requests so. We will deal internally with saving/restoring VLANs depending on our VLAN awareness state. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 8aa8bbcce6e3..15db37067bf1 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -2340,6 +2340,7 @@ static int sja1105_setup(struct dsa_switch *ds) ds->num_tx_queues = SJA1105_NUM_TC; ds->mtu_enforcement_ingress = true; + ds->vlan_bridge_vtu = true; /* The DSA/switchdev model brings up switch ports in standalone mode by * default, and that means vlan_filtering is 0 since they're not under From patchwork Sun May 10 16:42:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287244 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=vJrLPXUk; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49KqfV2p3tz9sRK for ; Mon, 11 May 2020 02:44:34 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729342AbgEJQob (ORCPT ); Sun, 10 May 2020 12:44:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34852 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729168AbgEJQni (ORCPT ); Sun, 10 May 2020 12:43:38 -0400 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6C7D5C061A0C; Sun, 10 May 2020 09:43:37 -0700 (PDT) Received: by mail-wm1-x344.google.com with SMTP id h4so15412081wmb.4; Sun, 10 May 2020 09:43:37 -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=6xcuiP37UyCaOrsW3hqo0Y2XODppUiFrZnzXTjx4S0k=; b=vJrLPXUk2QKRO15Se7GIMgGmGG/wAP1E3EtpeHrKXADxPBRuFX7iXjHEbTfvURnN1o Cn5eT89zwSVk+1i7z1vblEDVlYLpOL+R62CnkGZPQzvv9MDoeuAPFPK7H+hXUgd5ZWsv 2H28PjknhZWibXyOwm3hEcG+er/hKJ1KWwlx7wOtLyDx1hjQePB3fO3X1+fy0OD+QNpu bQNFObXWfIUAwQFoPrGG8KSzaXbLGF2LSWHpR+Miy/2gnssTzz+pEbdvjjDYvPx1b+9h FQ19piijLcv1A/GReY19t74091MllKLM2UzK9gCZVqdKSxSmE73u5huVYuhYq8sMSQXu TKdA== 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=6xcuiP37UyCaOrsW3hqo0Y2XODppUiFrZnzXTjx4S0k=; b=tEGrx4iJRDS9XcQIgUGywavbd9HFEyybAulOLsYo+TlUaj35Codrh6eVvIICT/gDl+ nkVC4cV76QOw0nDI7p1U1MgoZZsRRIs7XE19dlemKkade9S540qJv0AJRB/LWjUVHx0g sbkc2kZyob6BqUTDYmS4Mi12i+73eUdlpG/14ESnplnOeNveT9clCZBrgxZbHSXWcLl8 BNneeKUi4zO6I36kFBDuJ/JsCu6w2+wQw9soAUcJZ44zTTM9kG1Sgrni+CxxiMZOjPfG urWjyeUxMdzonsB1HH2IAmSO3XLDm7R9YJqfy1/4ihjBOVGTV0nl4qOF3TJSgWmzTLjZ NsHA== X-Gm-Message-State: AGi0PuaNVf3t+0VrQcUrY+Aoys7pszdQBnnApSa+MRVnX3QqUUbKUG8r RG8bBnVYG2OuplxINsf4boM= X-Google-Smtp-Source: APiQypKsoR77XB6Q9xEtQ/cC2yoZ4pewQuFzXr9xnz9Y2UlEIYQUosHc6LBUO4u/Vf+7E0NZbY7rHw== X-Received: by 2002:a7b:c10b:: with SMTP id w11mr14146888wmi.146.1589129016216; Sun, 10 May 2020 09:43:36 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:35 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 07/15] net: dsa: sja1105: exit sja1105_vlan_filtering when called multiple times Date: Sun, 10 May 2020 19:42:47 +0300 Message-Id: <20200510164255.19322-8-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean VLAN filtering is a global property for sja1105, and that means that we rely on the DSA core to not call us more than once. But we need to introduce some per-port state for the tagger, namely the xmit_tpid, and the best place to do that is where the xmit_tpid changes, namely in sja1105_vlan_filtering. So at the moment, exit early from the function to avoid unnecessarily resetting the switch for each port call. Then we'll change the xmit_tpid prior to the early exit in the next patch. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 15db37067bf1..8cf17238bc6a 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -2141,6 +2141,9 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) else state = SJA1105_VLAN_FILTERING_FULL; + if (priv->vlan_state == state) + return 0; + priv->vlan_state = state; table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS]; From patchwork Sun May 10 16:42:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287240 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=naL1fUrk; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49Kqf110b2z9sNH for ; Mon, 11 May 2020 02:44:09 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729233AbgEJQnr (ORCPT ); Sun, 10 May 2020 12:43:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34860 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729184AbgEJQnj (ORCPT ); Sun, 10 May 2020 12:43:39 -0400 Received: from mail-wm1-x344.google.com (mail-wm1-x344.google.com [IPv6:2a00:1450:4864:20::344]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 82C98C061A0E; Sun, 10 May 2020 09:43:38 -0700 (PDT) Received: by mail-wm1-x344.google.com with SMTP id k12so15373249wmj.3; Sun, 10 May 2020 09:43:38 -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=wuNa9dUTzo5dhNeShT+Z0EUvQDKyte55bwDEiseFjgE=; b=naL1fUrkes4Xk2tRknh7wo+NnUipoSbirgCAzpRaj+3S39UKrOxEoR9cOTIcTjH+0L N+dpYjN8nERaL14WE10JwSHpiUD8600A46S6pLBE7MTF0VTwFkiwNJ/ecj1Acnc/jvRZ y1qEz8sWKcQ33mjm//4kD+ARAwv4KbSmAxgj0NyBy6VoA0FuzWTbMWIHhpcDXIvULpVd oydXaRBzWYMHTLm35qaiXe6XXXYk8l8w6g+TGpmYgI2aAxalhiPI6PNwigxRKgD/dyLr ywUma8C27v6IXrRKmaNHVAJdDcfobn9HYP+IaWojTaM3D/o5z9pjiLUs2HMyM0UOjwf9 cO/w== 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=wuNa9dUTzo5dhNeShT+Z0EUvQDKyte55bwDEiseFjgE=; b=I6X9yEf1uqUC7Q4fuzRrX0Z0bwixvTSJvERO4H7za6DcisFKxbWjAyOaF2tJLMVkZV QeH5RDrJIURkr0L0B96pTNUYsM6/MPGVT0LG4+eqzvbOuEVfIMx4ypzDmSmcDJlcoq03 MW5K4T0ULsM2IvszoiBL+iBHEmyDqy+Zm8tcuMPowoopEG7DCyq4Sj/AfIAexuHW/237 UL9RdpZnuY7jv4niRxhyF7QzbMkUHt6dTm8Os8J5Q/IA0yawJkOdLozYJFGuMxX+iG9x ORlsjuSIlde1XVNOmm5/1pFv4Z7yTqES16tj5isFa4sbjUiOIKjsijuZjINiDtQfxlEw bxPA== X-Gm-Message-State: AGi0PuarZzkeFvcTrZv6vhUGR4IqSrb4QI5ap8JxPHf0Az39dBIa5fkj ia50zr0SY3IRmTA5WzlsX44= X-Google-Smtp-Source: APiQypK20K1daP+sQfApitxQsnIhmLeFGIKDF1+/V8mIJOiGnoTnaS9h2gaMrA73Ya3pUW7FE/LMrw== X-Received: by 2002:a7b:c8d4:: with SMTP id f20mr5281428wml.72.1589129017242; Sun, 10 May 2020 09:43:37 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:36 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 08/15] net: dsa: sja1105: prepare tagger for handling DSA tags and VLAN simultaneously Date: Sun, 10 May 2020 19:42:48 +0300 Message-Id: <20200510164255.19322-9-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean In VLAN-unaware mode, sja1105 uses VLAN tags with a custom TPID of 0xdadb. While in the yet-to-be introduced best_effort_vlan_filtering mode, it needs to work with normal VLAN TPID values. A complication arises when we must transmit a VLAN-tagged packet to the switch when it's in VLAN-aware mode. We need to construct a packet with 2 VLAN tags, and the switch will use the outer header for routing and pop it on egress. But sadly, here the 2 hardware generations don't behave the same: - E/T switches won't pop an ETH_P_8021AD tag on egress, it seems (packets will remain double-tagged). - P/Q/R/S switches will drop a packet with 2 ETH_P_8021Q tags (it looks like it tries to prevent VLAN hopping). But looks like the reverse is also true: - E/T switches have no problem popping the outer tag from packets with 2 ETH_P_8021Q tags. - P/Q/R/S will have no problem popping a single tag even if that is ETH_P_8021AD. So it is clear that if we want the hardware to work with dsa_8021q tagging in VLAN-aware mode, we need to send different TPIDs depending on revision. Keep that information in priv->info->qinq_tpid. The per-port tagger structure will hold an xmit_tpid value that depends not only upon the qinq_tpid, but also upon the VLAN awareness state itself (in case we must transmit using 0xdadb). Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105.h | 6 ++++++ drivers/net/dsa/sja1105/sja1105_main.c | 10 ++++++++++ drivers/net/dsa/sja1105/sja1105_spi.c | 6 ++++++ include/linux/dsa/sja1105.h | 2 ++ net/dsa/tag_sja1105.c | 17 +++++++---------- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index c80f1999c694..a019ffae38f1 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -87,6 +87,12 @@ struct sja1105_info { const struct sja1105_dynamic_table_ops *dyn_ops; const struct sja1105_table_ops *static_ops; const struct sja1105_regs *regs; + /* Both E/T and P/Q/R/S have quirks when it comes to popping the S-Tag + * from double-tagged frames. E/T will pop it only when it's equal to + * TPID from the General Parameters Table, while P/Q/R/S will only + * pop it when it's equal to TPID2. + */ + u16 qinq_tpid; int (*reset_cmd)(struct dsa_switch *ds); int (*setup_rgmii_delay)(const void *ctx, int port); /* Prototypes from include/net/dsa.h */ diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 8cf17238bc6a..34006b2def32 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -2136,6 +2136,15 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) tpid2 = ETH_P_SJA1105; } + for (port = 0; port < ds->num_ports; port++) { + struct sja1105_port *sp = &priv->ports[port]; + + if (enabled) + sp->xmit_tpid = priv->info->qinq_tpid; + else + sp->xmit_tpid = ETH_P_SJA1105; + } + if (!enabled) state = SJA1105_VLAN_UNAWARE; else @@ -2845,6 +2854,7 @@ static int sja1105_probe(struct spi_device *spi) goto out; } skb_queue_head_init(&sp->xmit_queue); + sp->xmit_tpid = ETH_P_SJA1105; } return 0; diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index 0be75c49e6c3..a0dacae803cc 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -512,6 +512,7 @@ struct sja1105_info sja1105e_info = { .part_no = SJA1105ET_PART_NO, .static_ops = sja1105e_table_ops, .dyn_ops = sja1105et_dyn_ops, + .qinq_tpid = ETH_P_8021Q, .ptp_ts_bits = 24, .ptpegr_ts_bytes = 4, .reset_cmd = sja1105et_reset_cmd, @@ -526,6 +527,7 @@ struct sja1105_info sja1105t_info = { .part_no = SJA1105ET_PART_NO, .static_ops = sja1105t_table_ops, .dyn_ops = sja1105et_dyn_ops, + .qinq_tpid = ETH_P_8021Q, .ptp_ts_bits = 24, .ptpegr_ts_bytes = 4, .reset_cmd = sja1105et_reset_cmd, @@ -540,6 +542,7 @@ struct sja1105_info sja1105p_info = { .part_no = SJA1105P_PART_NO, .static_ops = sja1105p_table_ops, .dyn_ops = sja1105pqrs_dyn_ops, + .qinq_tpid = ETH_P_8021AD, .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, @@ -555,6 +558,7 @@ struct sja1105_info sja1105q_info = { .part_no = SJA1105Q_PART_NO, .static_ops = sja1105q_table_ops, .dyn_ops = sja1105pqrs_dyn_ops, + .qinq_tpid = ETH_P_8021AD, .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, @@ -570,6 +574,7 @@ struct sja1105_info sja1105r_info = { .part_no = SJA1105R_PART_NO, .static_ops = sja1105r_table_ops, .dyn_ops = sja1105pqrs_dyn_ops, + .qinq_tpid = ETH_P_8021AD, .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, @@ -586,6 +591,7 @@ struct sja1105_info sja1105s_info = { .static_ops = sja1105s_table_ops, .dyn_ops = sja1105pqrs_dyn_ops, .regs = &sja1105pqrs_regs, + .qinq_tpid = ETH_P_8021AD, .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h index 136481ce3c6f..e47acf0965c5 100644 --- a/include/linux/dsa/sja1105.h +++ b/include/linux/dsa/sja1105.h @@ -9,6 +9,7 @@ #include #include +#include #include #define ETH_P_SJA1105 ETH_P_DSA_8021Q @@ -59,6 +60,7 @@ struct sja1105_port { struct sja1105_tagger_data *data; struct dsa_port *dp; bool hwts_tx_en; + u16 xmit_tpid; }; bool sja1105_can_use_vlan_as_tags(struct dsa_switch *ds); diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index 5368cd34bcf4..0a95fdd7bff8 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c @@ -96,6 +96,11 @@ static struct sk_buff *sja1105_defer_xmit(struct sja1105_port *sp, return NULL; } +static u16 sja1105_xmit_tpid(struct sja1105_port *sp) +{ + return sp->xmit_tpid; +} + static struct sk_buff *sja1105_xmit(struct sk_buff *skb, struct net_device *netdev) { @@ -111,15 +116,7 @@ static struct sk_buff *sja1105_xmit(struct sk_buff *skb, if (unlikely(sja1105_is_link_local(skb))) return sja1105_defer_xmit(dp->priv, skb); - /* If we are under a vlan_filtering bridge, IP termination on - * switch ports based on 802.1Q tags is simply too brittle to - * be passable. So just defer to the dsa_slave_notag_xmit - * implementation. - */ - if (dsa_port_is_vlan_filtering(dp)) - return skb; - - return dsa_8021q_xmit(skb, netdev, ETH_P_SJA1105, + return dsa_8021q_xmit(skb, netdev, sja1105_xmit_tpid(dp->priv), ((pcp << VLAN_PRIO_SHIFT) | tx_vid)); } @@ -258,7 +255,7 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, hdr = eth_hdr(skb); tpid = ntohs(hdr->h_proto); - is_tagged = (tpid == ETH_P_SJA1105); + is_tagged = (tpid == ETH_P_SJA1105 || tpid == ETH_P_8021Q); is_link_local = sja1105_is_link_local(skb); is_meta = sja1105_is_meta_frame(skb); From patchwork Sun May 10 16:42:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287236 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=DTrdB0Ly; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49KqdZ3dpPz9sRY for ; Mon, 11 May 2020 02:43:46 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729214AbgEJQno (ORCPT ); Sun, 10 May 2020 12:43:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34862 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729183AbgEJQnj (ORCPT ); Sun, 10 May 2020 12:43:39 -0400 Received: from mail-wm1-x342.google.com (mail-wm1-x342.google.com [IPv6:2a00:1450:4864:20::342]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 87B45C061A0C; Sun, 10 May 2020 09:43:39 -0700 (PDT) Received: by mail-wm1-x342.google.com with SMTP id n5so1409112wmd.0; Sun, 10 May 2020 09:43:39 -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=t9KvHDraVVPmHpvZiB0/h0nDTyCPGJWmh64wEtbHJ+Q=; b=DTrdB0LylJIANXRrxiVKVFJiNGuWqowDtrC8DJJ5iILZGivzSWDlouwe3Uonv1yZHp GH6AoL6guuLtiv4C8tV3m0aHHUPaMmIGu8EnU6ehNgKk6IQy1M9VLCpTJ7XuNqOFJMSB EjGXq7yObAO7IcnQF0auLXMW94hdTG7wWEGI6z43N/liwG8tl7/hYqOi0FWQ/YyhZFwV Nz7V6u5yvM6nbLfoeu+yLidK+z79OqNgbQYhc6qeMrwCxixrzo2WDt9/mpdEHHpVP1vQ s0lw0Gjyg74t8+n8iXccv5OzGYaPkKHHE5HVxaY9SD1rZarEqSEPY08Tgx3rJzlCkBGR ivPw== 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=t9KvHDraVVPmHpvZiB0/h0nDTyCPGJWmh64wEtbHJ+Q=; b=Kn9YUFvhWV9EhZfqVVDm18WZxsH1ml619lJqPAIssfbNIk55xXLA1FLSD0Lv6GquPB 0lJimK/LJaG8E/HzO1fCGs1KNz0BGdz6rY76k9ZPqjnnHnHGkBjo/OhEO1CLV4neHB0S M7wguEOMVpGaZ8bhj3dZb0sAWyP//IqVktKJ9Wjr/1GeRyXdMdWeqK9/5A2hbjPFSOYj hn4rMNX+3NDVvtreWzmwQQ+02AVlWdxofLc0vhSfuL5dezNPUheZa1v6svF9x30iVnTc 2E665gdYdOMyUz+RlUB5i94MalTuGat0hH7UOjcAC5qnAkvrQ5RWWL3BNVHm3nPez8NA Oq/w== X-Gm-Message-State: AGi0Pub2LdzyDK4T8Tsv5NdILaLudC4m0tLJnndf8aHr9+Apy2Nu/xZx j0Fx6TKmflgAq88esHQnLzU= X-Google-Smtp-Source: APiQypK+BXYktn4GfvAGyzcTUp7mwnwYXtA9XFtA5mpOpsRga3mHKxnh4E3HfYZqzxLEHhYUZKflBg== X-Received: by 2002:a1c:6142:: with SMTP id v63mr21164002wmb.61.1589129018242; Sun, 10 May 2020 09:43:38 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:37 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 09/15] net: dsa: tag_8021q: support up to 8 VLANs per port using sub-VLANs Date: Sun, 10 May 2020 19:42:49 +0300 Message-Id: <20200510164255.19322-10-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean For switches that support VLAN retagging, such as sja1105, we extend dsa_8021q by encoding a "sub-VLAN" into the remaining 3 free bits in the dsa_8021q tag. A sub-VLAN is nothing more than a number in the range 0-7, which serves as an index into a per-port driver lookup table. The sub-VLAN value of zero means that traffic is untagged (this is also backwards-compatible with dsa_8021q without retagging). The switch should be configured to retag VLAN-tagged traffic that gets transmitted towards the CPU port (and towards the CPU only). Example: bridge vlan add dev sw1p0 vid 100 The switch retags frames received on port 0, going to the CPU, and having VID 100, to the VID of 1104 (0x0450). In dsa_8021q language: | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | +-----------+-----+-----------------+-----------+-----------------------+ | DIR | SVL | SWITCH_ID | SUBVLAN | PORT | +-----------+-----+-----------------+-----------+-----------------------+ 0x0450 means: - DIR = 0b01: this is an RX VLAN - SUBVLAN = 0b001: this is subvlan #1 - SWITCH_ID = 0b001: this is switch 1 (see the name "sw1p0") - PORT = 0b0000: this is port 0 (see the name "sw1p0") The driver also remembers the "1 -> 100" mapping. In the hotpath, if the sub-VLAN from the tag encodes a non-untagged frame, this mapping is used to create a VLAN hwaccel tag, with the value of 100. Signed-off-by: Vladimir Oltean --- include/linux/dsa/8021q.h | 16 +++++++++++ net/dsa/tag_8021q.c | 56 +++++++++++++++++++++++++++++++++------ 2 files changed, 64 insertions(+), 8 deletions(-) diff --git a/include/linux/dsa/8021q.h b/include/linux/dsa/8021q.h index 404bd2cce642..311aa04e7520 100644 --- a/include/linux/dsa/8021q.h +++ b/include/linux/dsa/8021q.h @@ -20,6 +20,8 @@ struct dsa_8021q_crosschip_link { refcount_t refcount; }; +#define DSA_8021Q_N_SUBVLAN 8 + #if IS_ENABLED(CONFIG_NET_DSA_TAG_8021Q) int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int index, @@ -42,10 +44,14 @@ u16 dsa_8021q_tx_vid(struct dsa_switch *ds, int port); u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port); +u16 dsa_8021q_rx_vid_subvlan(struct dsa_switch *ds, int port, u16 subvlan); + int dsa_8021q_rx_switch_id(u16 vid); int dsa_8021q_rx_source_port(u16 vid); +u16 dsa_8021q_rx_subvlan(u16 vid); + bool vid_is_dsa_8021q(u16 vid); #else @@ -88,6 +94,11 @@ u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port) return 0; } +u16 dsa_8021q_rx_vid_subvlan(struct dsa_switch *ds, int port, u16 subvlan) +{ + return 0; +} + int dsa_8021q_rx_switch_id(u16 vid) { return 0; @@ -98,6 +109,11 @@ int dsa_8021q_rx_source_port(u16 vid) return 0; } +u16 dsa_8021q_rx_subvlan(u16 vid) +{ + return 0; +} + bool vid_is_dsa_8021q(u16 vid) { return false; diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c index 3236fbbf85b9..3052da668156 100644 --- a/net/dsa/tag_8021q.c +++ b/net/dsa/tag_8021q.c @@ -17,7 +17,7 @@ * * | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * +-----------+-----+-----------------+-----------+-----------------------+ - * | DIR | RSV | SWITCH_ID | RSV | PORT | + * | DIR | SVL | SWITCH_ID | SUBVLAN | PORT | * +-----------+-----+-----------------+-----------+-----------------------+ * * DIR - VID[11:10]: @@ -27,17 +27,24 @@ * These values make the special VIDs of 0, 1 and 4095 to be left * unused by this coding scheme. * - * RSV - VID[9]: - * To be used for further expansion of SWITCH_ID or for other purposes. - * Must be transmitted as zero and ignored on receive. + * SVL/SUBVLAN - { VID[9], VID[5:4] }: + * Sub-VLAN encoding. Valid only when DIR indicates an RX VLAN. + * * 0 (0b000): Field does not encode a sub-VLAN, either because + * received traffic is untagged, PVID-tagged or because a second + * VLAN tag is present after this tag and not inside of it. + * * 1 (0b001): Received traffic is tagged with a VID value private + * to the host. This field encodes the index in the host's lookup + * table through which the value of the ingress VLAN ID can be + * recovered. + * * 2 (0b010): Field encodes a sub-VLAN. + * ... + * * 7 (0b111): Field encodes a sub-VLAN. + * When DIR indicates a TX VLAN, SUBVLAN must be transmitted as zero + * (by the host) and ignored on receive (by the switch). * * SWITCH_ID - VID[8:6]: * Index of switch within DSA tree. Must be between 0 and 7. * - * RSV - VID[5:4]: - * To be used for further expansion of PORT or for other purposes. - * Must be transmitted as zero and ignored on receive. - * * PORT - VID[3:0]: * Index of switch port. Must be between 0 and 15. */ @@ -54,6 +61,18 @@ #define DSA_8021Q_SWITCH_ID(x) (((x) << DSA_8021Q_SWITCH_ID_SHIFT) & \ DSA_8021Q_SWITCH_ID_MASK) +#define DSA_8021Q_SUBVLAN_HI_SHIFT 9 +#define DSA_8021Q_SUBVLAN_HI_MASK GENMASK(9, 9) +#define DSA_8021Q_SUBVLAN_LO_SHIFT 4 +#define DSA_8021Q_SUBVLAN_LO_MASK GENMASK(4, 3) +#define DSA_8021Q_SUBVLAN_HI(x) (((x) & GENMASK(2, 2)) >> 2) +#define DSA_8021Q_SUBVLAN_LO(x) ((x) & GENMASK(1, 0)) +#define DSA_8021Q_SUBVLAN(x) \ + (((DSA_8021Q_SUBVLAN_LO(x) << DSA_8021Q_SUBVLAN_LO_SHIFT) & \ + DSA_8021Q_SUBVLAN_LO_MASK) | \ + ((DSA_8021Q_SUBVLAN_HI(x) << DSA_8021Q_SUBVLAN_HI_SHIFT) & \ + DSA_8021Q_SUBVLAN_HI_MASK)) + #define DSA_8021Q_PORT_SHIFT 0 #define DSA_8021Q_PORT_MASK GENMASK(3, 0) #define DSA_8021Q_PORT(x) (((x) << DSA_8021Q_PORT_SHIFT) & \ @@ -79,6 +98,13 @@ u16 dsa_8021q_rx_vid(struct dsa_switch *ds, int port) } EXPORT_SYMBOL_GPL(dsa_8021q_rx_vid); +u16 dsa_8021q_rx_vid_subvlan(struct dsa_switch *ds, int port, u16 subvlan) +{ + return DSA_8021Q_DIR_RX | DSA_8021Q_SWITCH_ID(ds->index) | + DSA_8021Q_PORT(port) | DSA_8021Q_SUBVLAN(subvlan); +} +EXPORT_SYMBOL_GPL(dsa_8021q_rx_vid_subvlan); + /* Returns the decoded switch ID from the RX VID. */ int dsa_8021q_rx_switch_id(u16 vid) { @@ -93,6 +119,20 @@ int dsa_8021q_rx_source_port(u16 vid) } EXPORT_SYMBOL_GPL(dsa_8021q_rx_source_port); +/* Returns the decoded subvlan from the RX VID. */ +u16 dsa_8021q_rx_subvlan(u16 vid) +{ + u16 svl_hi, svl_lo; + + svl_hi = (vid & DSA_8021Q_SUBVLAN_HI_MASK) >> + DSA_8021Q_SUBVLAN_HI_SHIFT; + svl_lo = (vid & DSA_8021Q_SUBVLAN_LO_MASK) >> + DSA_8021Q_SUBVLAN_LO_SHIFT; + + return (svl_hi << 2) | svl_lo; +} +EXPORT_SYMBOL_GPL(dsa_8021q_rx_subvlan); + bool vid_is_dsa_8021q(u16 vid) { return ((vid & DSA_8021Q_DIR_MASK) == DSA_8021Q_DIR_RX || From patchwork Sun May 10 16:42:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287235 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=un/h33bc; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49KqdX0V94z9sRY for ; Mon, 11 May 2020 02:43:44 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729204AbgEJQnn (ORCPT ); Sun, 10 May 2020 12:43:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34868 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1728360AbgEJQnk (ORCPT ); Sun, 10 May 2020 12:43:40 -0400 Received: from mail-wm1-x341.google.com (mail-wm1-x341.google.com [IPv6:2a00:1450:4864:20::341]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 79E0FC061A0C; Sun, 10 May 2020 09:43:40 -0700 (PDT) Received: by mail-wm1-x341.google.com with SMTP id h4so15412221wmb.4; Sun, 10 May 2020 09:43:40 -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=tjPoKBQLdBCmIv/BSjsK87xqPqvAOHh8klv/pK8e1nA=; b=un/h33bcQW0CA+P9TMKksDpA5sJguFfJ+QITRgP5pmZQnYoMKZtbuk0a1P7Dw9PavX XhdTuNFNLySQw9o9X+/a5aGw94D5dEcUvI0XLcnxwGkgGkgHDlHbOJzy9F6VefYyHmxt gWbEs/y97eqJi7aJA2n1ppIAOOYeIEvkOSp40vTcGPjoXVR4f9oJyxcRyVpAK17WpVhs XqdjIslnhGEurANXbUQdibWwKf4Ne3XyravWIF/nYNBpv27wpE26KEOYi/jHaH1WRCvK tJVR/R5Bw8gbEHRvStakhh8gW7k9e/iKAqkvHMBDM+5GStPEGbIyBOFyv2M/ql0TmPMP U6Vw== 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=tjPoKBQLdBCmIv/BSjsK87xqPqvAOHh8klv/pK8e1nA=; b=dBKO1LOq/EnEGQBllquIMx2GBYyvKjjImFbUqPsByldNWdCUDYfJvxBLamAYYKZien 6jbS/qbsHVgd6NVrDSkleBOfXsI2VugPApcnGDCI9HkKci1FAiIMB4iL1LUCpJV8Sr1C bRzNMvScj114rH2+ZZA3k+msIXfr8MDaW+K16n/G/1iP1XKksBbRLAmYpJjeAm4PApTL e+s/pqRH6HtOf74Dr5XozhEuf6S65KJ1mepq1QOvS5XwY4+ZSjJqehU5dkt7/KG3JeAZ 2vDML7+FlNaCyzelipF7+qAZ/th40Xp2A6buElmMPpYTqHfo6FOMwrNVu8d1WHFt+Aej ZTFw== X-Gm-Message-State: AGi0PuaUFtfuBcywkLEFlmuc0zr8x1Dd6U30hH4aKKjpiE4PVjE17gE6 qNXqeZcp/iwJwKjVX40dPHQ= X-Google-Smtp-Source: APiQypKctZhDDaokPrvj/CLeh1F0VT57/ZccBOyC+PN5589x+zoyvnvIMjqRF0eYr5+FRyaoXmqaYA== X-Received: by 2002:a1c:750a:: with SMTP id o10mr26541341wmc.124.1589129019252; Sun, 10 May 2020 09:43:39 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:38 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 10/15] net: dsa: tag_sja1105: implement sub-VLAN decoding Date: Sun, 10 May 2020 19:42:50 +0300 Message-Id: <20200510164255.19322-11-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Create a subvlan_map as part of each port's tagger private structure. This keeps reverse mappings of bridge-to-dsa_8021q VLAN retagging rules. Note that as of this patch, this piece of code is never engaged, due to the fact that the driver hasn't installed any retagging rule, so we'll always see packets with a subvlan code of 0 (untagged). Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105_main.c | 4 ++++ include/linux/dsa/sja1105.h | 1 + net/dsa/tag_sja1105.c | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 34006b2def32..d298098232cb 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -2835,6 +2835,7 @@ static int sja1105_probe(struct spi_device *spi) struct sja1105_port *sp = &priv->ports[port]; struct dsa_port *dp = dsa_to_port(ds, port); struct net_device *slave; + int subvlan; if (!dsa_is_user_port(ds, port)) continue; @@ -2855,6 +2856,9 @@ static int sja1105_probe(struct spi_device *spi) } skb_queue_head_init(&sp->xmit_queue); sp->xmit_tpid = ETH_P_SJA1105; + + for (subvlan = 0; subvlan < DSA_8021Q_N_SUBVLAN; subvlan++) + sp->subvlan_map[subvlan] = VLAN_N_VID; } return 0; diff --git a/include/linux/dsa/sja1105.h b/include/linux/dsa/sja1105.h index e47acf0965c5..cac168852321 100644 --- a/include/linux/dsa/sja1105.h +++ b/include/linux/dsa/sja1105.h @@ -54,6 +54,7 @@ struct sja1105_skb_cb { ((struct sja1105_skb_cb *)DSA_SKB_CB_PRIV(skb)) struct sja1105_port { + u16 subvlan_map[DSA_8021Q_N_SUBVLAN]; struct kthread_worker *xmit_worker; struct kthread_work xmit_work; struct sk_buff_head xmit_queue; diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index 0a95fdd7bff8..f690511b6d31 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c @@ -241,6 +241,20 @@ static struct sk_buff return skb; } +static void sja1105_decode_subvlan(struct sk_buff *skb, u16 subvlan) +{ + struct dsa_port *dp = dsa_slave_to_port(skb->dev); + struct sja1105_port *sp = dp->priv; + u16 vid = sp->subvlan_map[subvlan]; + u16 vlan_tci; + + if (vid == VLAN_N_VID) + return; + + vlan_tci = (skb->priority << VLAN_PRIO_SHIFT) | vid; + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci); +} + static struct sk_buff *sja1105_rcv(struct sk_buff *skb, struct net_device *netdev, struct packet_type *pt) @@ -250,6 +264,7 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, struct ethhdr *hdr; u16 tpid, vid, tci; bool is_link_local; + u16 subvlan = 0; bool is_tagged; bool is_meta; @@ -273,6 +288,7 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, source_port = dsa_8021q_rx_source_port(vid); switch_id = dsa_8021q_rx_switch_id(vid); skb->priority = (tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; + subvlan = dsa_8021q_rx_subvlan(vid); } else if (is_link_local) { /* Management traffic path. Switch embeds the switch ID and * port ID into bytes of the destination MAC, courtesy of @@ -297,6 +313,9 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, return NULL; } + if (subvlan) + sja1105_decode_subvlan(skb, subvlan); + return sja1105_rcv_meta_state_machine(skb, &meta, is_link_local, is_meta); } From patchwork Sun May 10 16:42:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287239 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=sChnG59u; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49Kqdz2vBPz9sNH for ; Mon, 11 May 2020 02:44:07 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729245AbgEJQns (ORCPT ); Sun, 10 May 2020 12:43:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34870 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729154AbgEJQnl (ORCPT ); Sun, 10 May 2020 12:43:41 -0400 Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 883B6C061A0C; Sun, 10 May 2020 09:43:41 -0700 (PDT) Received: by mail-wr1-x443.google.com with SMTP id y3so7936796wrt.1; Sun, 10 May 2020 09:43:41 -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=evCDaaGvKeikSrgDPwn+au2FyzoFxP/big4rQtX74Ik=; b=sChnG59u1yaACxcAAqbXQKYd/5879TmvYa9HMTnUiJh8wIIuPUuWR8PM45oX/iw9hM 7roFQpREEBcUZlBai/R4AeuH0fOj3jmgoHvtF2hxAwdn1KQlQ8cXYu89YHRZfQuNfZP6 J57pLgMXQ3J9s3mRiUk0t0TfnOCtNNnLuEVqDz92Al8pl16JyJuLJeYz3G8jpEOLWe73 JGbmq7lDtJ2FqtxGk/qQ4OkWlS2L6YMKqZ5e7Zh5UvJGe/4SKOjxYGClN71j96hQzHP8 8i0IexW91s27C9tisGNVl6Rg0rBruzgtQy47W83hWcjOFzKuvVwD/Y2oaepzzJLaCIUx 1ebQ== 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=evCDaaGvKeikSrgDPwn+au2FyzoFxP/big4rQtX74Ik=; b=JzoKOjcZOQg05Yu9VPAE2uvmJ/vWFCofq6cHZPtlknSB0joQWtqYm0dZJhjmRfKM2Y NoobPUdQVfLdrFCDeOnffHbFv4nNdeZT6ys8B58vJJdpfbgyOuwPAXrEAuleiuWshbCx kwIAsJ9zV7SND9E+K5n0z6wqL7kGmhEEJvMI9FuGOJc2a/HTB9jbdtoLTw6i53OaG0DP 3fgJh3U1SEYHxy3XyI/afwLRGVhoKT+Z3L2Rxdjxnlwhqwiuu76AERkDYyvnJOG3rWJI 35nNSnantC5R+x/iWVg2nXoImJ/fK7XNyNubjQoie8D1Cge+DzacrHJiiLZnGnAvFx50 2KkQ== X-Gm-Message-State: AGi0PuZOphe7xVZSd1904SMk1s1dMsjs44Av5jFs4xin+Huw/mtc8SlJ nPL8Og20UBa98kweEoUr+Xg= X-Google-Smtp-Source: APiQypKvZULPbqkiOHxwi8Q3FbAwprrKJPa9dlEfLBsO78Dg1eitKGGp+xNfZI6IHPXwMOXbgz0cyw== X-Received: by 2002:a5d:4bc6:: with SMTP id l6mr12735096wrt.112.1589129020265; Sun, 10 May 2020 09:43:40 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:39 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 11/15] net: dsa: sja1105: add a new best_effort_vlan_filtering devlink parameter Date: Sun, 10 May 2020 19:42:51 +0300 Message-Id: <20200510164255.19322-12-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean This devlink parameter enables the handling of DSA tags when enslaved to a bridge with vlan_filtering=1. There are very good reasons to want this, but there are also very good reasons for not enabling it by default. So a devlink param named best_effort_vlan_filtering, currently driver-specific and exported only by sja1105, is used to configure this. In practice, this is perhaps the way that most users are going to use the switch in. It assumes that no more than 7 VLANs are needed per port. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105.h | 2 + drivers/net/dsa/sja1105/sja1105_main.c | 117 ++++++++++++++++++++++++- 2 files changed, 115 insertions(+), 4 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index a019ffae38f1..1dcaecab0912 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -194,6 +194,7 @@ struct sja1105_bridge_vlan { enum sja1105_vlan_state { SJA1105_VLAN_UNAWARE, + SJA1105_VLAN_BEST_EFFORT, SJA1105_VLAN_FILTERING_FULL, }; @@ -201,6 +202,7 @@ struct sja1105_private { struct sja1105_static_config static_config; bool rgmii_rx_delay[SJA1105_NUM_PORTS]; bool rgmii_tx_delay[SJA1105_NUM_PORTS]; + bool best_effort_vlan_filtering; const struct sja1105_info *info; struct gpio_desc *reset_gpio; struct spi_device *spidev; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index d298098232cb..4ea77e829d70 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -2115,6 +2115,7 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) enum sja1105_vlan_state state; struct sja1105_table *table; struct sja1105_rule *rule; + bool want_tagging; u16 tpid, tpid2; int rc; @@ -2147,6 +2148,8 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) if (!enabled) state = SJA1105_VLAN_UNAWARE; + else if (priv->best_effort_vlan_filtering) + state = SJA1105_VLAN_BEST_EFFORT; else state = SJA1105_VLAN_FILTERING_FULL; @@ -2154,6 +2157,8 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) return 0; priv->vlan_state = state; + want_tagging = (state == SJA1105_VLAN_UNAWARE || + state == SJA1105_VLAN_BEST_EFFORT); table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS]; general_params = table->entries; @@ -2167,8 +2172,10 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) general_params->incl_srcpt1 = enabled; general_params->incl_srcpt0 = enabled; + want_tagging = priv->best_effort_vlan_filtering || !enabled; + /* VLAN filtering => independent VLAN learning. - * No VLAN filtering => shared VLAN learning. + * No VLAN filtering (or best effort) => shared VLAN learning. * * In shared VLAN learning mode, untagged traffic still gets * pvid-tagged, and the FDB table gets populated with entries @@ -2187,7 +2194,7 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) */ table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS]; l2_lookup_params = table->entries; - l2_lookup_params->shared_learn = !enabled; + l2_lookup_params->shared_learn = want_tagging; rc = sja1105_static_config_reload(priv, SJA1105_VLAN_FILTERING); if (rc) @@ -2195,9 +2202,10 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) /* Switch port identification based on 802.1Q is only passable * if we are not under a vlan_filtering bridge. So make sure - * the two configurations are mutually exclusive. + * the two configurations are mutually exclusive (of course, the + * user may know better, i.e. best_effort_vlan_filtering). */ - return sja1105_setup_8021q_tagging(ds, !enabled); + return sja1105_setup_8021q_tagging(ds, want_tagging); } bool sja1105_can_use_vlan_as_tags(struct dsa_switch *ds) @@ -2288,6 +2296,100 @@ static int sja1105_vlan_del(struct dsa_switch *ds, int port, return sja1105_build_vlan_table(priv, true); } +static int sja1105_best_effort_vlan_filtering_get(struct sja1105_private *priv, + bool *be_vlan) +{ + *be_vlan = priv->best_effort_vlan_filtering; + + return 0; +} + +static int sja1105_best_effort_vlan_filtering_set(struct sja1105_private *priv, + bool be_vlan) +{ + struct dsa_switch *ds = priv->ds; + bool vlan_filtering; + int port; + int rc; + + vlan_filtering = dsa_port_is_vlan_filtering(dsa_to_port(ds, 0)); + priv->best_effort_vlan_filtering = be_vlan; + + rtnl_lock(); + for (port = 0; port < ds->num_ports; port++) { + if (!dsa_is_user_port(ds, port)) + continue; + rc = sja1105_vlan_filtering(ds, port, vlan_filtering); + if (rc) + break; + } + rtnl_unlock(); + + return rc; +} + +enum sja1105_devlink_param_id { + SJA1105_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, + SJA1105_DEVLINK_PARAM_ID_BEST_EFFORT_VLAN_FILTERING, +}; + +static int sja1105_devlink_param_get(struct dsa_switch *ds, u32 id, + struct devlink_param_gset_ctx *ctx) +{ + struct sja1105_private *priv = ds->priv; + int err; + + switch (id) { + case SJA1105_DEVLINK_PARAM_ID_BEST_EFFORT_VLAN_FILTERING: + err = sja1105_best_effort_vlan_filtering_get(priv, + &ctx->val.vbool); + break; + default: + err = -EOPNOTSUPP; + break; + } + + return err; +} + +static int sja1105_devlink_param_set(struct dsa_switch *ds, u32 id, + struct devlink_param_gset_ctx *ctx) +{ + struct sja1105_private *priv = ds->priv; + int err; + + switch (id) { + case SJA1105_DEVLINK_PARAM_ID_BEST_EFFORT_VLAN_FILTERING: + err = sja1105_best_effort_vlan_filtering_set(priv, + ctx->val.vbool); + break; + default: + err = -EOPNOTSUPP; + break; + } + + return err; +} + +static const struct devlink_param sja1105_devlink_params[] = { + DSA_DEVLINK_PARAM_DRIVER(SJA1105_DEVLINK_PARAM_ID_BEST_EFFORT_VLAN_FILTERING, + "best_effort_vlan_filtering", + DEVLINK_PARAM_TYPE_BOOL, + BIT(DEVLINK_PARAM_CMODE_RUNTIME)), +}; + +static int sja1105_setup_devlink_params(struct dsa_switch *ds) +{ + return dsa_devlink_params_register(ds, sja1105_devlink_params, + ARRAY_SIZE(sja1105_devlink_params)); +} + +static void sja1105_teardown_devlink_params(struct dsa_switch *ds) +{ + dsa_devlink_params_unregister(ds, sja1105_devlink_params, + ARRAY_SIZE(sja1105_devlink_params)); +} + /* The programming model for the SJA1105 switch is "all-at-once" via static * configuration tables. Some of these can be dynamically modified at runtime, * but not the xMII mode parameters table. @@ -2354,6 +2456,10 @@ static int sja1105_setup(struct dsa_switch *ds) ds->mtu_enforcement_ingress = true; ds->vlan_bridge_vtu = true; + rc = sja1105_setup_devlink_params(ds); + if (rc < 0) + return rc; + /* The DSA/switchdev model brings up switch ports in standalone mode by * default, and that means vlan_filtering is 0 since they're not under * a bridge, so it's safe to set up switch tagging at this time. @@ -2376,6 +2482,7 @@ static void sja1105_teardown(struct dsa_switch *ds) kthread_destroy_worker(sp->xmit_worker); } + sja1105_teardown_devlink_params(ds); sja1105_flower_teardown(ds); sja1105_tas_teardown(ds); sja1105_ptp_clock_unregister(ds); @@ -2717,6 +2824,8 @@ static const struct dsa_switch_ops sja1105_switch_ops = { .cls_flower_stats = sja1105_cls_flower_stats, .crosschip_bridge_join = sja1105_crosschip_bridge_join, .crosschip_bridge_leave = sja1105_crosschip_bridge_leave, + .devlink_param_get = sja1105_devlink_param_get, + .devlink_param_set = sja1105_devlink_param_set, }; static int sja1105_check_device_id(struct sja1105_private *priv) From patchwork Sun May 10 16:42:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287237 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=UrUQoNX4; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49Kqdg0bRyz9sRf for ; Mon, 11 May 2020 02:43:51 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729261AbgEJQnt (ORCPT ); Sun, 10 May 2020 12:43:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34878 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729201AbgEJQnn (ORCPT ); Sun, 10 May 2020 12:43:43 -0400 Received: from mail-wm1-x341.google.com (mail-wm1-x341.google.com [IPv6:2a00:1450:4864:20::341]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A39E3C061A0C; Sun, 10 May 2020 09:43:42 -0700 (PDT) Received: by mail-wm1-x341.google.com with SMTP id y24so16339812wma.4; Sun, 10 May 2020 09:43:42 -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=1VdKd6xGfS37QzUTdaLfq1NQgQ9fEEFw3sewt9lmK54=; b=UrUQoNX4lPJGUBHFd4HobxStJcitHeDESrFfSKeb7HE3p6ohtdaO2Cz6nTrkAzovwW KJPa0TlA6WdBC7gE8bA6MPGN0qHE0Fu5w8BSyNZx1YEhLnyxSpul9G2Xg5B49D/joVjx 0SWj22xiJuIC5nEWYfmNNgm98z5HSo+IeO6pZA4nqv1sBKeToyicCiMVk0s+BCYJP7wB CN8zleDtRCxTLAVCLaESkPs8Sm2/4YnB0lffm9jh7YSmiTZMZrxt0P2VTqjEKLc0XpjL Yb++VyB3YftQRAGY57xjO/pUzyL/Q7Z8epCYJ/Szr7eO+8UN1JkxhvZdnPeQ9mT6qykm EhDA== 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=1VdKd6xGfS37QzUTdaLfq1NQgQ9fEEFw3sewt9lmK54=; b=dsX8lbOvui9s3YrhoEdYoZjzDorNi2yD9IXlfg7wEibbIYdLfICCsb3PlQ01XGlWVO NGP6rtBdghULYe9uGi4fI1q0IoOmE4LOUvrnpa/lPJ2bO8ugDqfrKZmGf6lfGi3UN7KU V5nqvvia9bFDD/6VfkHr252/pXXFF5cxnff3HmMGBJXgpU4yPZpZpRPXyVg8XrC96kx+ vP4hRMSKDYd2TFxqqyOidiZA6+oM6ed3+vZtnuJSy7pN6uxzs4CeBgaQ0VA4szsaFZBR l8N40CLU6+VthaorHPBTGkKYFGKtFyWpUpod9PLKqKo3IlqiqV0hY5cCY1hxDeOb9NRx jPMg== X-Gm-Message-State: AGi0PubR5IadTdDdzbVt8dJatNmtIa9v78Ji8hvd/yIO8eBHxjRFLFEb FZ7uYz+edBX+7hiuhuRAWt4= X-Google-Smtp-Source: APiQypK2BfXvtruj/lCsY5fnh0o70oE1swLovd6jqvlZYx40GEpogsh3nrVA2Kjp+Kb559d0hu27dg== X-Received: by 2002:a05:600c:218e:: with SMTP id e14mr28366696wme.140.1589129021306; Sun, 10 May 2020 09:43:41 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:40 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 12/15] net: dsa: sja1105: add packing ops for the Retagging Table Date: Sun, 10 May 2020 19:42:52 +0300 Message-Id: <20200510164255.19322-13-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean The Retagging Table is an optional feature that allows the switch to match frames against a {ingress port, egress port, vid} rule and change their VLAN ID. The retagged frames are by default clones of the original ones (since the hardware-foreseen use case was to mirror traffic for debugging purposes and to tag it with a special VLAN for this purpose), but we can force the original frames to be dropped by removing the pre-retagging VLAN from the port membership list of the egress port. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105.h | 2 + .../net/dsa/sja1105/sja1105_dynamic_config.c | 33 ++++++++++ .../net/dsa/sja1105/sja1105_static_config.c | 62 ++++++++++++++++++- .../net/dsa/sja1105/sja1105_static_config.h | 15 +++++ 4 files changed, 110 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index 1dcaecab0912..1ecdfd6be4c2 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -328,6 +328,8 @@ size_t sja1105et_l2_lookup_entry_packing(void *buf, void *entry_ptr, enum packing_op op); size_t sja1105_vlan_lookup_entry_packing(void *buf, void *entry_ptr, enum packing_op op); +size_t sja1105_retagging_entry_packing(void *buf, void *entry_ptr, + enum packing_op op); size_t sja1105pqrs_mac_config_entry_packing(void *buf, void *entry_ptr, enum packing_op op); size_t sja1105pqrs_avb_params_entry_packing(void *buf, void *entry_ptr, diff --git a/drivers/net/dsa/sja1105/sja1105_dynamic_config.c b/drivers/net/dsa/sja1105/sja1105_dynamic_config.c index bdee01811960..2a8fbd7fdedc 100644 --- a/drivers/net/dsa/sja1105/sja1105_dynamic_config.c +++ b/drivers/net/dsa/sja1105/sja1105_dynamic_config.c @@ -133,6 +133,9 @@ #define SJA1105PQRS_SIZE_AVB_PARAMS_DYN_CMD \ (SJA1105_SIZE_DYN_CMD + SJA1105PQRS_SIZE_AVB_PARAMS_ENTRY) +#define SJA1105_SIZE_RETAGGING_DYN_CMD \ + (SJA1105_SIZE_DYN_CMD + SJA1105_SIZE_RETAGGING_ENTRY) + #define SJA1105_MAX_DYN_CMD_SIZE \ SJA1105PQRS_SIZE_MAC_CONFIG_DYN_CMD @@ -525,6 +528,20 @@ sja1105pqrs_avb_params_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op); } +static void +sja1105_retagging_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd, + enum packing_op op) +{ + u8 *p = buf + SJA1105_SIZE_RETAGGING_ENTRY; + const int size = SJA1105_SIZE_DYN_CMD; + + sja1105_packing(p, &cmd->valid, 31, 31, size, op); + sja1105_packing(p, &cmd->errors, 30, 30, size, op); + sja1105_packing(p, &cmd->valident, 29, 29, size, op); + sja1105_packing(p, &cmd->rdwrset, 28, 28, size, op); + sja1105_packing(p, &cmd->index, 5, 0, size, op); +} + #define OP_READ BIT(0) #define OP_WRITE BIT(1) #define OP_DEL BIT(2) @@ -606,6 +623,14 @@ struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = { .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD, .addr = 0x34, }, + [BLK_IDX_RETAGGING] = { + .entry_packing = sja1105_retagging_entry_packing, + .cmd_packing = sja1105_retagging_cmd_packing, + .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, + .access = (OP_WRITE | OP_DEL), + .packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD, + .addr = 0x31, + }, [BLK_IDX_XMII_PARAMS] = {0}, }; @@ -692,6 +717,14 @@ struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = { .packed_size = SJA1105ET_SIZE_GENERAL_PARAMS_DYN_CMD, .addr = 0x34, }, + [BLK_IDX_RETAGGING] = { + .entry_packing = sja1105_retagging_entry_packing, + .cmd_packing = sja1105_retagging_cmd_packing, + .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, + .access = (OP_READ | OP_WRITE | OP_DEL), + .packed_size = SJA1105_SIZE_RETAGGING_DYN_CMD, + .addr = 0x38, + }, [BLK_IDX_XMII_PARAMS] = {0}, }; diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.c b/drivers/net/dsa/sja1105/sja1105_static_config.c index b68c9c92c248..780aca034cdc 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.c +++ b/drivers/net/dsa/sja1105/sja1105_static_config.c @@ -541,6 +541,22 @@ static size_t sja1105_xmii_params_entry_packing(void *buf, void *entry_ptr, return size; } +size_t sja1105_retagging_entry_packing(void *buf, void *entry_ptr, + enum packing_op op) +{ + struct sja1105_retagging_entry *entry = entry_ptr; + const size_t size = SJA1105_SIZE_RETAGGING_ENTRY; + + sja1105_packing(buf, &entry->egr_port, 63, 59, size, op); + sja1105_packing(buf, &entry->ing_port, 58, 54, size, op); + sja1105_packing(buf, &entry->vlan_ing, 53, 42, size, op); + sja1105_packing(buf, &entry->vlan_egr, 41, 30, size, op); + sja1105_packing(buf, &entry->do_not_learn, 29, 29, size, op); + sja1105_packing(buf, &entry->use_dest_ports, 28, 28, size, op); + sja1105_packing(buf, &entry->destports, 27, 23, size, op); + return size; +} + size_t sja1105_table_header_packing(void *buf, void *entry_ptr, enum packing_op op) { @@ -603,6 +619,7 @@ static u64 blk_id_map[BLK_IDX_MAX] = { [BLK_IDX_L2_FORWARDING_PARAMS] = BLKID_L2_FORWARDING_PARAMS, [BLK_IDX_AVB_PARAMS] = BLKID_AVB_PARAMS, [BLK_IDX_GENERAL_PARAMS] = BLKID_GENERAL_PARAMS, + [BLK_IDX_RETAGGING] = BLKID_RETAGGING, [BLK_IDX_XMII_PARAMS] = BLKID_XMII_PARAMS, }; @@ -646,7 +663,7 @@ static_config_check_memory_size(const struct sja1105_table *tables) { const struct sja1105_l2_forwarding_params_entry *l2_fwd_params; const struct sja1105_vl_forwarding_params_entry *vl_fwd_params; - int i, mem = 0; + int i, max_mem, mem = 0; l2_fwd_params = tables[BLK_IDX_L2_FORWARDING_PARAMS].entries; @@ -659,7 +676,12 @@ static_config_check_memory_size(const struct sja1105_table *tables) mem += vl_fwd_params->partspc[i]; } - if (mem > SJA1105_MAX_FRAME_MEMORY) + if (tables[BLK_IDX_RETAGGING].entry_count) + max_mem = SJA1105_MAX_FRAME_MEMORY_RETAGGING; + else + max_mem = SJA1105_MAX_FRAME_MEMORY; + + if (mem > max_mem) return SJA1105_OVERCOMMITTED_FRAME_MEMORY; return SJA1105_CONFIG_OK; @@ -881,6 +903,12 @@ struct sja1105_table_ops sja1105e_table_ops[BLK_IDX_MAX] = { .packed_entry_size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY, .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, }, + [BLK_IDX_RETAGGING] = { + .packing = sja1105_retagging_entry_packing, + .unpacked_entry_size = sizeof(struct sja1105_retagging_entry), + .packed_entry_size = SJA1105_SIZE_RETAGGING_ENTRY, + .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, + }, [BLK_IDX_XMII_PARAMS] = { .packing = sja1105_xmii_params_entry_packing, .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry), @@ -993,6 +1021,12 @@ struct sja1105_table_ops sja1105t_table_ops[BLK_IDX_MAX] = { .packed_entry_size = SJA1105ET_SIZE_GENERAL_PARAMS_ENTRY, .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, }, + [BLK_IDX_RETAGGING] = { + .packing = sja1105_retagging_entry_packing, + .unpacked_entry_size = sizeof(struct sja1105_retagging_entry), + .packed_entry_size = SJA1105_SIZE_RETAGGING_ENTRY, + .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, + }, [BLK_IDX_XMII_PARAMS] = { .packing = sja1105_xmii_params_entry_packing, .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry), @@ -1065,6 +1099,12 @@ struct sja1105_table_ops sja1105p_table_ops[BLK_IDX_MAX] = { .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY, .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, }, + [BLK_IDX_RETAGGING] = { + .packing = sja1105_retagging_entry_packing, + .unpacked_entry_size = sizeof(struct sja1105_retagging_entry), + .packed_entry_size = SJA1105_SIZE_RETAGGING_ENTRY, + .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, + }, [BLK_IDX_XMII_PARAMS] = { .packing = sja1105_xmii_params_entry_packing, .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry), @@ -1177,6 +1217,12 @@ struct sja1105_table_ops sja1105q_table_ops[BLK_IDX_MAX] = { .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY, .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, }, + [BLK_IDX_RETAGGING] = { + .packing = sja1105_retagging_entry_packing, + .unpacked_entry_size = sizeof(struct sja1105_retagging_entry), + .packed_entry_size = SJA1105_SIZE_RETAGGING_ENTRY, + .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, + }, [BLK_IDX_XMII_PARAMS] = { .packing = sja1105_xmii_params_entry_packing, .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry), @@ -1249,6 +1295,12 @@ struct sja1105_table_ops sja1105r_table_ops[BLK_IDX_MAX] = { .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY, .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, }, + [BLK_IDX_RETAGGING] = { + .packing = sja1105_retagging_entry_packing, + .unpacked_entry_size = sizeof(struct sja1105_retagging_entry), + .packed_entry_size = SJA1105_SIZE_RETAGGING_ENTRY, + .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, + }, [BLK_IDX_XMII_PARAMS] = { .packing = sja1105_xmii_params_entry_packing, .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry), @@ -1361,6 +1413,12 @@ struct sja1105_table_ops sja1105s_table_ops[BLK_IDX_MAX] = { .packed_entry_size = SJA1105PQRS_SIZE_GENERAL_PARAMS_ENTRY, .max_entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT, }, + [BLK_IDX_RETAGGING] = { + .packing = sja1105_retagging_entry_packing, + .unpacked_entry_size = sizeof(struct sja1105_retagging_entry), + .packed_entry_size = SJA1105_SIZE_RETAGGING_ENTRY, + .max_entry_count = SJA1105_MAX_RETAGGING_COUNT, + }, [BLK_IDX_XMII_PARAMS] = { .packing = sja1105_xmii_params_entry_packing, .unpacked_entry_size = sizeof(struct sja1105_xmii_params_entry), diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.h b/drivers/net/dsa/sja1105/sja1105_static_config.h index b569e3de3590..d96044d86b11 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.h +++ b/drivers/net/dsa/sja1105/sja1105_static_config.h @@ -20,6 +20,7 @@ #define SJA1105_SIZE_VLAN_LOOKUP_ENTRY 8 #define SJA1105_SIZE_L2_FORWARDING_ENTRY 8 #define SJA1105_SIZE_L2_FORWARDING_PARAMS_ENTRY 12 +#define SJA1105_SIZE_RETAGGING_ENTRY 8 #define SJA1105_SIZE_XMII_PARAMS_ENTRY 4 #define SJA1105_SIZE_SCHEDULE_PARAMS_ENTRY 12 #define SJA1105_SIZE_SCHEDULE_ENTRY_POINTS_PARAMS_ENTRY 4 @@ -54,6 +55,7 @@ enum { BLKID_L2_FORWARDING_PARAMS = 0x0E, BLKID_AVB_PARAMS = 0x10, BLKID_GENERAL_PARAMS = 0x11, + BLKID_RETAGGING = 0x12, BLKID_XMII_PARAMS = 0x4E, }; @@ -75,6 +77,7 @@ enum sja1105_blk_idx { BLK_IDX_L2_FORWARDING_PARAMS, BLK_IDX_AVB_PARAMS, BLK_IDX_GENERAL_PARAMS, + BLK_IDX_RETAGGING, BLK_IDX_XMII_PARAMS, BLK_IDX_MAX, /* Fake block indices that are only valid for dynamic access */ @@ -99,10 +102,12 @@ enum sja1105_blk_idx { #define SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT 1 #define SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT 1 #define SJA1105_MAX_GENERAL_PARAMS_COUNT 1 +#define SJA1105_MAX_RETAGGING_COUNT 32 #define SJA1105_MAX_XMII_PARAMS_COUNT 1 #define SJA1105_MAX_AVB_PARAMS_COUNT 1 #define SJA1105_MAX_FRAME_MEMORY 929 +#define SJA1105_MAX_FRAME_MEMORY_RETAGGING 910 #define SJA1105E_DEVICE_ID 0x9C00000Cull #define SJA1105T_DEVICE_ID 0x9E00030Eull @@ -273,6 +278,16 @@ struct sja1105_mac_config_entry { u64 ingress; }; +struct sja1105_retagging_entry { + u64 egr_port; + u64 ing_port; + u64 vlan_ing; + u64 vlan_egr; + u64 do_not_learn; + u64 use_dest_ports; + u64 destports; +}; + struct sja1105_xmii_params_entry { u64 phy_mac[5]; u64 xmii_mode[5]; From patchwork Sun May 10 16:42:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287242 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=YUNYevQ0; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49KqfC27HHz9sNH for ; Mon, 11 May 2020 02:44:19 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729325AbgEJQoS (ORCPT ); Sun, 10 May 2020 12:44:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34880 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729215AbgEJQnp (ORCPT ); Sun, 10 May 2020 12:43:45 -0400 Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B0637C061A0C; Sun, 10 May 2020 09:43:43 -0700 (PDT) Received: by mail-wr1-x444.google.com with SMTP id e16so7922827wra.7; Sun, 10 May 2020 09:43:43 -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=l8yu63bzu9EKtUcTab5iO3gnV0kmnc7EqpMOcQXFQvg=; b=YUNYevQ0UNIGvx85zB3sVCx9g7ar7pBDkt4kCRxexjEbek2e8/0934Ijp0s87zUBxE UDPKM9GQKs7r2HOlh968aJcYWhFm25QQPzqri2dU/okDOHjb4qfuGOG7vx3p9I3qLMwH KckumHE0kc64ueNfJ9z5C8eZC7Ofr9mlSeLToWi28dRa0tTqG3OwVoD0RYtPcK26Or8r RikAek5PEes7MpLo/L7U5vpImVdSJbZLRGPtA4l7u4rzkhFBqWOIRSlkQKcpTG3ggBdl WIIAL66suyiYNVd8p4PdaIgJBm2GQHWKvZA+0NmuV0Fb44ndBOjqSxNIuFEodBIjLOj9 EH7w== 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=l8yu63bzu9EKtUcTab5iO3gnV0kmnc7EqpMOcQXFQvg=; b=nvNJ/7S4sJGLoXRHSXnWYrRyUhp24/uW7fm47lCRAzQ1OV5m5A9KFVaYeo+oOY8qfQ m9IcjlthLKBAAksfOT14dN0tv+TShADJAUYCDp8uOY8CHYAbK7G9PS/CTSjvcAMc36eQ +b4FxceZCWjWUArc9FUyXQQMMTLefSx+kfTPVQwITvCyD3yVHYbPuY1zfSU1WUGGeRiH TtASNNpsUWeReeOnveOhHATsRa/XDBVwDba8PeugMSXo8tVz0GO1xJ3aCPDjwcQo5UZe BOYRKPCl9xW4Bn66Xqr1rmYl9YWJSEYqyWzmucyOrhmDHYUmrvOmXMPJWVwCRM0Z2IM0 oNbw== X-Gm-Message-State: AGi0PuYkXBZ38+VgLgWc/CwFEUhpF5F/2iuUq5iuSAe18PezJ096sATZ XfagGS+uyyQUdrgkgN5i670= X-Google-Smtp-Source: APiQypIPQNCYU6ysbOb8zMT4G8P6PRZpRjQEND+e/XYCxKXrhzNPj535kJ7R9L/UB/AmSmlzmp+QFA== X-Received: by 2002:adf:8563:: with SMTP id 90mr13754478wrh.74.1589129022388; Sun, 10 May 2020 09:43:42 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:41 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 13/15] net: dsa: sja1105: implement a common frame memory partitioning function Date: Sun, 10 May 2020 19:42:53 +0300 Message-Id: <20200510164255.19322-14-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean There are 2 different features that require some reserved frame memory space: VLAN retagging and virtual links. Create a central function that modifies the static config and ensures frame memory is never overcommitted. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105.h | 2 + drivers/net/dsa/sja1105/sja1105_main.c | 37 +++++++++++++++++++ .../net/dsa/sja1105/sja1105_static_config.h | 1 + drivers/net/dsa/sja1105/sja1105_vl.c | 20 +--------- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index 1ecdfd6be4c2..198d2a7d7f95 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -244,6 +244,8 @@ enum sja1105_reset_reason { int sja1105_static_config_reload(struct sja1105_private *priv, enum sja1105_reset_reason reason); +void sja1105_frame_memory_partitioning(struct sja1105_private *priv); + /* From sja1105_spi.c */ int sja1105_xfer_buf(const struct sja1105_private *priv, sja1105_spi_rw_mode_t rw, u64 reg_addr, diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 4ea77e829d70..9e93a9af4913 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -412,6 +412,41 @@ static int sja1105_init_l2_forwarding_params(struct sja1105_private *priv) return 0; } +void sja1105_frame_memory_partitioning(struct sja1105_private *priv) +{ + struct sja1105_l2_forwarding_params_entry *l2_fwd_params; + struct sja1105_vl_forwarding_params_entry *vl_fwd_params; + struct sja1105_table *table; + int max_mem; + + /* VLAN retagging is implemented using a loopback port that consumes + * frame buffers. That leaves less for us. + */ + if (priv->vlan_state == SJA1105_VLAN_BEST_EFFORT) + max_mem = SJA1105_MAX_FRAME_MEMORY_RETAGGING; + else + max_mem = SJA1105_MAX_FRAME_MEMORY; + + table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING_PARAMS]; + l2_fwd_params = table->entries; + l2_fwd_params->part_spc[0] = max_mem; + + /* If we have any critical-traffic virtual links, we need to reserve + * some frame buffer memory for them. At the moment, hardcode the value + * at 100 blocks of 128 bytes of memory each. This leaves 829 blocks + * remaining for best-effort traffic. TODO: figure out a more flexible + * way to perform the frame buffer partitioning. + */ + if (!priv->static_config.tables[BLK_IDX_VL_FORWARDING].entry_count) + return; + + table = &priv->static_config.tables[BLK_IDX_VL_FORWARDING_PARAMS]; + vl_fwd_params = table->entries; + + l2_fwd_params->part_spc[0] -= SJA1105_VL_FRAME_MEMORY; + vl_fwd_params->partspc[0] = SJA1105_VL_FRAME_MEMORY; +} + static int sja1105_init_general_params(struct sja1105_private *priv) { struct sja1105_general_params_entry default_general_params = { @@ -2196,6 +2231,8 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) l2_lookup_params = table->entries; l2_lookup_params->shared_learn = want_tagging; + sja1105_frame_memory_partitioning(priv); + rc = sja1105_static_config_reload(priv, SJA1105_VLAN_FILTERING); if (rc) dev_err(ds->dev, "Failed to change VLAN Ethertype\n"); diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.h b/drivers/net/dsa/sja1105/sja1105_static_config.h index d96044d86b11..5946847bb5b9 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.h +++ b/drivers/net/dsa/sja1105/sja1105_static_config.h @@ -108,6 +108,7 @@ enum sja1105_blk_idx { #define SJA1105_MAX_FRAME_MEMORY 929 #define SJA1105_MAX_FRAME_MEMORY_RETAGGING 910 +#define SJA1105_VL_FRAME_MEMORY 100 #define SJA1105E_DEVICE_ID 0x9C00000Cull #define SJA1105T_DEVICE_ID 0x9E00030Eull diff --git a/drivers/net/dsa/sja1105/sja1105_vl.c b/drivers/net/dsa/sja1105/sja1105_vl.c index aa9b0b92f437..9ce2b15b65d8 100644 --- a/drivers/net/dsa/sja1105/sja1105_vl.c +++ b/drivers/net/dsa/sja1105/sja1105_vl.c @@ -5,7 +5,6 @@ #include #include "sja1105.h" -#define SJA1105_VL_FRAME_MEMORY 100 #define SJA1105_SIZE_VL_STATUS 8 /* The switch flow classification core implements TTEthernet, which 'thinks' in @@ -141,8 +140,6 @@ static bool sja1105_vl_key_lower(struct sja1105_vl_lookup_entry *a, static int sja1105_init_virtual_links(struct sja1105_private *priv, struct netlink_ext_ack *extack) { - struct sja1105_l2_forwarding_params_entry *l2_fwd_params; - struct sja1105_vl_forwarding_params_entry *vl_fwd_params; struct sja1105_vl_policing_entry *vl_policing; struct sja1105_vl_forwarding_entry *vl_fwd; struct sja1105_vl_lookup_entry *vl_lookup; @@ -153,10 +150,6 @@ static int sja1105_init_virtual_links(struct sja1105_private *priv, int max_sharindx = 0; int i, j, k; - table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING_PARAMS]; - l2_fwd_params = table->entries; - l2_fwd_params->part_spc[0] = SJA1105_MAX_FRAME_MEMORY; - /* Figure out the dimensioning of the problem */ list_for_each_entry(rule, &priv->flow_block.rules, list) { if (rule->type != SJA1105_RULE_VL) @@ -308,17 +301,6 @@ static int sja1105_init_virtual_links(struct sja1105_private *priv, if (!table->entries) return -ENOMEM; table->entry_count = 1; - vl_fwd_params = table->entries; - - /* Reserve some frame buffer memory for the critical-traffic virtual - * links (this needs to be done). At the moment, hardcode the value - * at 100 blocks of 128 bytes of memory each. This leaves 829 blocks - * remaining for best-effort traffic. TODO: figure out a more flexible - * way to perform the frame buffer partitioning. - */ - l2_fwd_params->part_spc[0] = SJA1105_MAX_FRAME_MEMORY - - SJA1105_VL_FRAME_MEMORY; - vl_fwd_params->partspc[0] = SJA1105_VL_FRAME_MEMORY; for (i = 0; i < num_virtual_links; i++) { unsigned long cookie = vl_lookup[i].flow_cookie; @@ -342,6 +324,8 @@ static int sja1105_init_virtual_links(struct sja1105_private *priv, } } + sja1105_frame_memory_partitioning(priv); + return 0; } From patchwork Sun May 10 16:42:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287238 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=td7ha/KH; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49Kqdh3fYhz9sSW for ; Mon, 11 May 2020 02:43:52 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729272AbgEJQnv (ORCPT ); Sun, 10 May 2020 12:43:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34886 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729216AbgEJQnp (ORCPT ); Sun, 10 May 2020 12:43:45 -0400 Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 04C8EC061A0E; Sun, 10 May 2020 09:43:45 -0700 (PDT) Received: by mail-wr1-x443.google.com with SMTP id y16so739926wrs.3; Sun, 10 May 2020 09:43:44 -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=QI0sGT61QNjkAsm4hnHTocIk57rUXJXZziq0gMlf4xw=; b=td7ha/KHaJ8Bq5ajDl0zi903V6ryU/sgabM6zVjagKzQxmKcR4Dvb1RbOYNwySxqZr MeWahe6SYmsn3w/Ci1SeqzWbXZrnOZBz0abslSpgEcHTKdLafQHrTyHSTNs17Jmq2T4L i79mMOnuYOT5y9U34ykqH/AdQDUsD8ElH1TE/TKdk8nQdqnhWKGkL5jHjAcwGFXNltbt OOBV/L0eoy5JYInUoTOxgXaZDA2/e8LThcoqsK8rSJw3yarHoKoMn/a5uzadYeka/IcP oTidrVzU2z8z5jNw3Y/Bz1KqvQrHJfblppBbUEZI93vKC4DYQN+Q/YN1XAuSxILHetZH emhQ== 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=QI0sGT61QNjkAsm4hnHTocIk57rUXJXZziq0gMlf4xw=; b=IUviKqhAjhPrywz44/uumb+9W1CRWa6e8A2fF+cND5mCk4c2S4Y/ZMCzUmyYahSIM4 W/qsbmWkqR6zCBYI9Qb+o6QJ/+FU1pfHp6S7wRXV/1CfvH9j2+mbOUpp3vlsHK2F9sjB uS43q46dlIWqExCdJG5muVJx+9JRCWzPD+o/fpN30S+/wvqOjr7mbkYWN1P0gFWeSrm0 +Tz4ygQilQYby45CN0+TNuEngKhYjuBYt/zwDc4L2CfqE5dRWyVtUg9vqC+9M2XUzwwS ChlhzZEu0eq1WadvYJXd1p1mUATISIJnKrzoSztaoLX+dZ53iXHIYcV0nY1tvClEv+l8 U/2A== X-Gm-Message-State: AGi0PuaLn3Q84ba2k7o9u44XWz9+FP51uHZtiOcY/3MvTy8QVJJYII2G Uarlx4Q03dOcGsGmc9wTuxc= X-Google-Smtp-Source: APiQypIG6R4zKgnl/PGN2KxF+mf+XKvgHN9PT526RTpyHPzlGkwETkjQMaOgngnBHHmc4OjaQ+XEyQ== X-Received: by 2002:a5d:6702:: with SMTP id o2mr8246235wru.231.1589129023588; Sun, 10 May 2020 09:43:43 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:43 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 14/15] net: dsa: sja1105: implement VLAN retagging for dsa_8021q sub-VLANs Date: Sun, 10 May 2020 19:42:54 +0300 Message-Id: <20200510164255.19322-15-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean Expand the delta commit procedure for VLANs with additional logic for treating bridge_vlans in the newly introduced operating mode, SJA1105_VLAN_BEST_EFFORT. For every bridge VLAN on every user port, a sub-VLAN index is calculated and retagging rules are installed towards a dsa_8021q rx_vid that encodes that sub-VLAN index. This way, the tagger can identify the original VLANs. Extra care is taken for VLANs to still work as intended in cross-chip scenarios. Retagging may have unintended consequences for these because a sub-VLAN encoding that works for the CPU does not make any sense for a front-panel port. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/sja1105/sja1105_main.c | 412 ++++++++++++++++++++++++- 1 file changed, 409 insertions(+), 3 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 9e93a9af4913..f974d2ace72b 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1849,6 +1849,57 @@ sja1105_get_tag_protocol(struct dsa_switch *ds, int port, return DSA_TAG_PROTO_SJA1105; } +static int sja1105_find_free_subvlan(u16 *subvlan_map, bool pvid) +{ + int subvlan; + + if (pvid) + return 0; + + for (subvlan = 1; subvlan < DSA_8021Q_N_SUBVLAN; subvlan++) + if (subvlan_map[subvlan] == VLAN_N_VID) + return subvlan; + + return -1; +} + +static int sja1105_find_subvlan(u16 *subvlan_map, u16 vid) +{ + int subvlan; + + for (subvlan = 0; subvlan < DSA_8021Q_N_SUBVLAN; subvlan++) + if (subvlan_map[subvlan] == vid) + return subvlan; + + return -1; +} + +static int sja1105_find_committed_subvlan(struct sja1105_private *priv, + int port, u16 vid) +{ + struct sja1105_port *sp = &priv->ports[port]; + + return sja1105_find_subvlan(sp->subvlan_map, vid); +} + +static void sja1105_init_subvlan_map(u16 *subvlan_map) +{ + int subvlan; + + for (subvlan = 0; subvlan < DSA_8021Q_N_SUBVLAN; subvlan++) + subvlan_map[subvlan] = VLAN_N_VID; +} + +static void sja1105_commit_subvlan_map(struct sja1105_private *priv, int port, + u16 *subvlan_map) +{ + struct sja1105_port *sp = &priv->ports[port]; + int subvlan; + + for (subvlan = 0; subvlan < DSA_8021Q_N_SUBVLAN; subvlan++) + sp->subvlan_map[subvlan] = subvlan_map[subvlan]; +} + static int sja1105_is_vlan_configured(struct sja1105_private *priv, u16 vid) { struct sja1105_vlan_lookup_entry *vlan; @@ -1865,9 +1916,29 @@ static int sja1105_is_vlan_configured(struct sja1105_private *priv, u16 vid) return -1; } +static int +sja1105_find_retagging_entry(struct sja1105_retagging_entry *retagging, + int count, int from_port, u16 from_vid, + u16 to_vid) +{ + int i; + + for (i = 0; i < count; i++) + if (retagging[i].ing_port == BIT(from_port) && + retagging[i].vlan_ing == from_vid && + retagging[i].vlan_egr == to_vid) + return i; + + /* Return an invalid entry index if not found */ + return -1; +} + static int sja1105_commit_vlans(struct sja1105_private *priv, - struct sja1105_vlan_lookup_entry *new_vlan) + struct sja1105_vlan_lookup_entry *new_vlan, + struct sja1105_retagging_entry *new_retagging, + int num_retagging) { + struct sja1105_retagging_entry *retagging; struct sja1105_vlan_lookup_entry *vlan; struct sja1105_table *table; int num_vlans = 0; @@ -1927,9 +1998,50 @@ static int sja1105_commit_vlans(struct sja1105_private *priv, vlan[k++] = new_vlan[i]; } + /* VLAN Retagging Table */ + table = &priv->static_config.tables[BLK_IDX_RETAGGING]; + retagging = table->entries; + + for (i = 0; i < table->entry_count; i++) { + rc = sja1105_dynamic_config_write(priv, BLK_IDX_RETAGGING, + i, &retagging[i], false); + if (rc) + return rc; + } + + if (table->entry_count) + kfree(table->entries); + + table->entries = kcalloc(num_retagging, table->ops->unpacked_entry_size, + GFP_KERNEL); + if (!table->entries) + return -ENOMEM; + + table->entry_count = num_retagging; + retagging = table->entries; + + for (i = 0; i < num_retagging; i++) { + retagging[i] = new_retagging[i]; + + /* Update entry */ + rc = sja1105_dynamic_config_write(priv, BLK_IDX_RETAGGING, + i, &retagging[i], true); + if (rc < 0) + return rc; + } + return 0; } +struct sja1105_crosschip_vlan { + struct list_head list; + u16 vid; + bool untagged; + int port; + int other_port; + struct dsa_switch *other_ds; +}; + struct sja1105_crosschip_switch { struct list_head list; struct dsa_switch *other_ds; @@ -2001,6 +2113,265 @@ sja1105_build_dsa_8021q_vlans(struct sja1105_private *priv, return 0; } +static int sja1105_build_subvlans(struct sja1105_private *priv, + u16 subvlan_map[][DSA_8021Q_N_SUBVLAN], + struct sja1105_vlan_lookup_entry *new_vlan, + struct sja1105_retagging_entry *new_retagging, + int *num_retagging) +{ + struct sja1105_bridge_vlan *v; + int k = *num_retagging; + + if (priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) + return 0; + + list_for_each_entry(v, &priv->bridge_vlans, list) { + int upstream = dsa_upstream_port(priv->ds, v->port); + int match, subvlan; + u16 rx_vid; + + /* Only sub-VLANs on user ports need to be applied. + * Bridge VLANs also include VLANs added automatically + * by DSA on the CPU port. + */ + if (!dsa_is_user_port(priv->ds, v->port)) + continue; + + subvlan = sja1105_find_subvlan(subvlan_map[v->port], + v->vid); + if (subvlan < 0) { + subvlan = sja1105_find_free_subvlan(subvlan_map[v->port], + v->pvid); + if (subvlan < 0) { + dev_err(priv->ds->dev, "No more free subvlans\n"); + return -ENOSPC; + } + } + + rx_vid = dsa_8021q_rx_vid_subvlan(priv->ds, v->port, subvlan); + + /* @v->vid on @v->port needs to be retagged to @rx_vid + * on @upstream. Assume @v->vid on @v->port and on + * @upstream was already configured by the previous + * iteration over bridge_vlans. + */ + match = rx_vid; + new_vlan[match].vlanid = rx_vid; + new_vlan[match].vmemb_port |= BIT(v->port); + new_vlan[match].vmemb_port |= BIT(upstream); + new_vlan[match].vlan_bc |= BIT(v->port); + new_vlan[match].vlan_bc |= BIT(upstream); + /* The "untagged" flag is set the same as for the + * original VLAN + */ + if (!v->untagged) + new_vlan[match].tag_port |= BIT(v->port); + /* But it's always tagged towards the CPU */ + new_vlan[match].tag_port |= BIT(upstream); + + /* The Retagging Table generates packet *clones* with + * the new VLAN. This is a very odd hardware quirk + * which we need to suppress by dropping the original + * packet. + * Deny egress of the original VLAN towards the CPU + * port. This will force the switch to drop it, and + * we'll see only the retagged packets. + */ + match = v->vid; + new_vlan[match].vlan_bc &= ~BIT(upstream); + + /* And the retagging itself */ + new_retagging[k].vlan_ing = v->vid; + new_retagging[k].vlan_egr = rx_vid; + new_retagging[k].ing_port = BIT(v->port); + new_retagging[k].egr_port = BIT(upstream); + if (k++ == SJA1105_MAX_RETAGGING_COUNT) { + dev_err(priv->ds->dev, "No more retagging rules\n"); + return -ENOSPC; + } + + subvlan_map[v->port][subvlan] = v->vid; + } + + *num_retagging = k; + + return 0; +} + +/* Sadly, in crosschip scenarios where the CPU port is also the link to another + * switch, we should retag backwards (the dsa_8021q vid to the original vid) on + * the CPU port of neighbour switches. + */ +static int +sja1105_build_crosschip_subvlans(struct sja1105_private *priv, + struct sja1105_vlan_lookup_entry *new_vlan, + struct sja1105_retagging_entry *new_retagging, + int *num_retagging) +{ + struct sja1105_crosschip_vlan *tmp, *pos; + struct dsa_8021q_crosschip_link *c; + struct sja1105_bridge_vlan *v, *w; + struct list_head crosschip_vlans; + int k = *num_retagging; + int rc = 0; + + if (priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) + return 0; + + INIT_LIST_HEAD(&crosschip_vlans); + + list_for_each_entry(c, &priv->crosschip_links, list) { + struct sja1105_private *other_priv = c->other_ds->priv; + + if (other_priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) + continue; + + /* Crosschip links are also added to the CPU ports. + * Ignore those. + */ + if (!dsa_is_user_port(priv->ds, c->port)) + continue; + if (!dsa_is_user_port(c->other_ds, c->other_port)) + continue; + + /* Search for VLANs on the remote port */ + list_for_each_entry(v, &other_priv->bridge_vlans, list) { + bool already_added = false; + bool we_have_it = false; + + if (v->port != c->other_port) + continue; + + /* If @v is a pvid on @other_ds, it does not need + * re-retagging, because its SVL field is 0 and we + * already allow that, via the dsa_8021q crosschip + * links. + */ + if (v->pvid) + continue; + + /* Search for the VLAN on our local port */ + list_for_each_entry(w, &priv->bridge_vlans, list) { + if (w->port == c->port && w->vid == v->vid) { + we_have_it = true; + break; + } + } + + if (!we_have_it) + continue; + + list_for_each_entry(tmp, &crosschip_vlans, list) { + if (tmp->vid == v->vid && + tmp->untagged == v->untagged && + tmp->port == c->port && + tmp->other_port == v->port && + tmp->other_ds == c->other_ds) { + already_added = true; + break; + } + } + + if (already_added) + continue; + + tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) { + dev_err(priv->ds->dev, "Failed to allocate memory\n"); + rc = -ENOMEM; + goto out; + } + tmp->vid = v->vid; + tmp->port = c->port; + tmp->other_port = v->port; + tmp->other_ds = c->other_ds; + tmp->untagged = v->untagged; + list_add(&tmp->list, &crosschip_vlans); + } + } + + list_for_each_entry(tmp, &crosschip_vlans, list) { + struct sja1105_private *other_priv = tmp->other_ds->priv; + int upstream = dsa_upstream_port(priv->ds, tmp->port); + int match, subvlan; + u16 rx_vid; + + subvlan = sja1105_find_committed_subvlan(other_priv, + tmp->other_port, + tmp->vid); + /* If this happens, it's a bug. The neighbour switch does not + * have a subvlan for tmp->vid on tmp->other_port, but it + * should, since we already checked for its vlan_state. + */ + if (WARN_ON(subvlan < 0)) { + rc = -EINVAL; + goto out; + } + + rx_vid = dsa_8021q_rx_vid_subvlan(tmp->other_ds, + tmp->other_port, + subvlan); + + /* The @rx_vid retagged from @tmp->vid on + * {@tmp->other_ds, @tmp->other_port} needs to be + * re-retagged to @tmp->vid on the way back to us. + * + * Assume the original @tmp->vid is already configured + * on this local switch, otherwise we wouldn't be + * retagging its subvlan on the other switch in the + * first place. We just need to add a reverse retagging + * rule for @rx_vid and install @rx_vid on our ports. + */ + match = rx_vid; + new_vlan[match].vlanid = rx_vid; + new_vlan[match].vmemb_port |= BIT(tmp->port); + new_vlan[match].vmemb_port |= BIT(upstream); + /* The "untagged" flag is set the same as for the + * original VLAN. And towards the CPU, it doesn't + * really matter, because @rx_vid will only receive + * traffic on that port. For consistency with other dsa_8021q + * VLANs, we'll keep the CPU port tagged. + */ + if (!tmp->untagged) + new_vlan[match].tag_port |= BIT(tmp->port); + new_vlan[match].tag_port |= BIT(upstream); + /* Deny egress of @rx_vid towards our front-panel port. + * This will force the switch to drop it, and we'll see + * only the re-retagged packets (having the original, + * pre-initial-retagging, VLAN @tmp->vid). + */ + new_vlan[match].vlan_bc &= ~BIT(tmp->port); + + /* On reverse retagging, the same ingress VLAN goes to multiple + * ports. So we have an opportunity to create composite rules + * to not waste the limited space in the retagging table. + */ + k = sja1105_find_retagging_entry(new_retagging, *num_retagging, + upstream, rx_vid, tmp->vid); + if (k < 0) { + if (*num_retagging == SJA1105_MAX_RETAGGING_COUNT) { + dev_err(priv->ds->dev, "No more retagging rules\n"); + rc = -ENOSPC; + goto out; + } + k = (*num_retagging)++; + } + /* And the retagging itself */ + new_retagging[k].vlan_ing = rx_vid; + new_retagging[k].vlan_egr = tmp->vid; + new_retagging[k].ing_port = BIT(upstream); + new_retagging[k].egr_port |= BIT(tmp->port); + } + +out: + list_for_each_entry_safe(tmp, pos, &crosschip_vlans, list) { + list_del(&tmp->list); + kfree(tmp); + } + + return rc; +} + static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify); static int sja1105_notify_crosschip_switches(struct sja1105_private *priv) @@ -2054,10 +2425,12 @@ static int sja1105_notify_crosschip_switches(struct sja1105_private *priv) static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) { + u16 subvlan_map[SJA1105_NUM_PORTS][DSA_8021Q_N_SUBVLAN]; + struct sja1105_retagging_entry *new_retagging; struct sja1105_vlan_lookup_entry *new_vlan; struct sja1105_table *table; + int i, num_retagging = 0; int rc; - int i; table = &priv->static_config.tables[BLK_IDX_VLAN_LOOKUP]; new_vlan = kcalloc(VLAN_N_VID, @@ -2065,9 +2438,23 @@ static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) if (!new_vlan) return -ENOMEM; + table = &priv->static_config.tables[BLK_IDX_VLAN_LOOKUP]; + new_retagging = kcalloc(SJA1105_MAX_RETAGGING_COUNT, + table->ops->unpacked_entry_size, GFP_KERNEL); + if (!new_retagging) { + kfree(new_vlan); + return -ENOMEM; + } + for (i = 0; i < VLAN_N_VID; i++) new_vlan[i].vlanid = VLAN_N_VID; + for (i = 0; i < SJA1105_MAX_RETAGGING_COUNT; i++) + new_retagging[i].vlan_ing = VLAN_N_VID; + + for (i = 0; i < priv->ds->num_ports; i++) + sja1105_init_subvlan_map(subvlan_map[i]); + /* Bridge VLANs */ rc = sja1105_build_bridge_vlans(priv, new_vlan); if (rc) @@ -2082,7 +2469,22 @@ static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) if (rc) goto out; - rc = sja1105_commit_vlans(priv, new_vlan); + /* Private VLANs necessary for dsa_8021q operation, which we need to + * determine on our own: + * - Sub-VLANs + * - Sub-VLANs of crosschip switches + */ + rc = sja1105_build_subvlans(priv, subvlan_map, new_vlan, new_retagging, + &num_retagging); + if (rc) + goto out; + + rc = sja1105_build_crosschip_subvlans(priv, new_vlan, new_retagging, + &num_retagging); + if (rc) + goto out; + + rc = sja1105_commit_vlans(priv, new_vlan, new_retagging, num_retagging); if (rc) goto out; @@ -2090,6 +2492,9 @@ static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) if (rc) goto out; + for (i = 0; i < priv->ds->num_ports; i++) + sja1105_commit_subvlan_map(priv, i, subvlan_map[i]); + if (notify) { rc = sja1105_notify_crosschip_switches(priv); if (rc) @@ -2098,6 +2503,7 @@ static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) out: kfree(new_vlan); + kfree(new_retagging); return rc; } From patchwork Sun May 10 16:42:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 1287241 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=QgeegJyE; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 49Kqf36RfMz9sNH for ; Mon, 11 May 2020 02:44:11 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729314AbgEJQoL (ORCPT ); Sun, 10 May 2020 12:44:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34888 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1729225AbgEJQnq (ORCPT ); Sun, 10 May 2020 12:43:46 -0400 Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1D707C05BD09; Sun, 10 May 2020 09:43:46 -0700 (PDT) Received: by mail-wr1-x444.google.com with SMTP id s8so7910044wrt.9; Sun, 10 May 2020 09:43:46 -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=Vv8Y68lEcckqpjaX1Ww0vGpx3GEjoFzLyevxXV72hA0=; b=QgeegJyEmcC2D4fjl1YELffkihWsvPVrFdyQFtT4BQcK0VeLvSJ0q3w7MjnnptpvQL KuMElZoJ0SgcoW3nr7I9WThP3CmXhWGZmIH0AmZr506JugGBlONdYbGW28XtOosgLoxZ /RRvXVXd6gV36efojgqBdOxVWKOJPshYGVR1JyFwa7v1X3pfm2W/0n71NnqwEgAOGHd2 S5a1+oJ8PVMjfioPVD4yDKeo64djrOdzDowY0urwqDVSmXRP9GZLlJQHtzagPVk2LNMq 8zXO84mi5tDm49qWoV3tLLkpdxSQops/AbCrcbhqO+vAuIHvjrh2n74BvyUnObIjhNJ6 P3Ew== 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=Vv8Y68lEcckqpjaX1Ww0vGpx3GEjoFzLyevxXV72hA0=; b=r3cttg26Y3fpBSmqqrKFZsxOFKGPpFPvef7YhXyTXi26jOaNW/Yrpl+zLwtJ1SlTBJ +14RgJKrWFIaFbbWuq5UJ7Bw+JHj9bp0h/Bcx2mMfNXXGX2ac686K/9/V3FDcVVA3P/U DYLtBaytPCORFD4+R7B8+5i0Cqzp1KpctHatv6KSsTivOEEhNwfUASYHEVdDrfGa0Szc qEMqmh1u5vPKZDOlXsXCWRYJQ7+v4CCxEiS0CsCbU8Bmo2azjzaNLW48TCEVIcZdwnyz bIK4JcXlxE7Sm1SBVx3CR+s6DM62xD/hiBzXNYNA1YIbkaU5nXJA8fTkvyOounWChZIW 7dPg== X-Gm-Message-State: AGi0PubKt0VVkRKGSIwOvCrQPEdm8ezN2jI1qz/dUne0cT/hW9qMDWI6 5U/GFZV5U2GSp73pf6X1W70= X-Google-Smtp-Source: APiQypLeDMIVEjJAI62Dun/oS3tU2pZUmWVo4IQGM9RqdKqiCc0n4bXjDYQvjAByu5L9UY9Wb++6Ag== X-Received: by 2002:adf:b301:: with SMTP id j1mr13872024wrd.221.1589129024736; Sun, 10 May 2020 09:43:44 -0700 (PDT) Received: from localhost.localdomain ([86.121.118.29]) by smtp.gmail.com with ESMTPSA id i1sm13390916wrx.22.2020.05.10.09.43.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 May 2020 09:43:44 -0700 (PDT) From: Vladimir Oltean To: andrew@lunn.ch, f.fainelli@gmail.com, vivien.didelot@gmail.com Cc: davem@davemloft.net, kuba@kernel.org, rmk+kernel@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next 15/15] docs: net: dsa: sja1105: document the best_effort_vlan_filtering option Date: Sun, 10 May 2020 19:42:55 +0300 Message-Id: <20200510164255.19322-16-olteanv@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200510164255.19322-1-olteanv@gmail.com> References: <20200510164255.19322-1-olteanv@gmail.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean Signed-off-by: Vladimir Oltean --- .../networking/devlink-params-sja1105.txt | 27 +++ Documentation/networking/dsa/sja1105.rst | 211 +++++++++++++++--- 2 files changed, 212 insertions(+), 26 deletions(-) create mode 100644 Documentation/networking/devlink-params-sja1105.txt diff --git a/Documentation/networking/devlink-params-sja1105.txt b/Documentation/networking/devlink-params-sja1105.txt new file mode 100644 index 000000000000..1d71742e270a --- /dev/null +++ b/Documentation/networking/devlink-params-sja1105.txt @@ -0,0 +1,27 @@ +best_effort_vlan_filtering + [DEVICE, DRIVER-SPECIFIC] + Allow plain ETH_P_8021Q headers to be used as DSA tags. + Benefits: + - Can terminate untagged traffic over switch net + devices even when enslaved to a bridge with + vlan_filtering=1. + - Can terminate VLAN-tagged traffic over switch net + devices even when enslaved to a bridge with + vlan_filtering=1, with some constraints (no more than + 7 non-pvid VLANs per user port). + - Can do QoS based on VLAN PCP and VLAN membership + admission control for autonomously forwarded frames + (regardless of whether they can be terminated on the + CPU or not). + Drawbacks: + - User cannot use VLANs in range 1024-3071. If the + switch receives frames with such VIDs, it will + misinterpret them as DSA tags. + - Switch uses Shared VLAN Learning (FDB lookup uses + only DMAC as key). + - When VLANs span cross-chip topologies, the total + number of permitted VLANs may be less than 7 per + port, due to a maximum number of 32 VLAN retagging + rules per switch. + Configuration mode: runtime + Type: bool. diff --git a/Documentation/networking/dsa/sja1105.rst b/Documentation/networking/dsa/sja1105.rst index 34581629dd3f..b6bbc17814fb 100644 --- a/Documentation/networking/dsa/sja1105.rst +++ b/Documentation/networking/dsa/sja1105.rst @@ -66,34 +66,193 @@ reprogrammed with the updated static configuration. Traffic support =============== -The switches do not support switch tagging in hardware. But they do support -customizing the TPID by which VLAN traffic is identified as such. The switch -driver is leveraging ``CONFIG_NET_DSA_TAG_8021Q`` by requesting that special -VLANs (with a custom TPID of ``ETH_P_EDSA`` instead of ``ETH_P_8021Q``) are -installed on its ports when not in ``vlan_filtering`` mode. This does not -interfere with the reception and transmission of real 802.1Q-tagged traffic, -because the switch does no longer parse those packets as VLAN after the TPID -change. -The TPID is restored when ``vlan_filtering`` is requested by the user through -the bridge layer, and general IP termination becomes no longer possible through -the switch netdevices in this mode. - -The switches have two programmable filters for link-local destination MACs. +The switches do not have hardware support for DSA tags, except for "slow +protocols" for switch control as STP and PTP. For these, the switches have two +programmable filters for link-local destination MACs. These are used to trap BPDUs and PTP traffic to the master netdevice, and are further used to support STP and 1588 ordinary clock/boundary clock -functionality. - -The following traffic modes are supported over the switch netdevices: - -+--------------------+------------+------------------+------------------+ -| | Standalone | Bridged with | Bridged with | -| | ports | vlan_filtering 0 | vlan_filtering 1 | -+====================+============+==================+==================+ -| Regular traffic | Yes | Yes | No (use master) | -+--------------------+------------+------------------+------------------+ -| Management traffic | Yes | Yes | Yes | -| (BPDU, PTP) | | | | -+--------------------+------------+------------------+------------------+ +functionality. For frames trapped to the CPU, source port and switch ID +information is encoded by the hardware into the frames. + +But by leveraging ``CONFIG_NET_DSA_TAG_8021Q`` (a software-defined DSA tagging +format based on VLANs), general-purpose traffic termination through the network +stack can be supported under certain circumstances. + +Depending on VLAN awareness state, the following operating modes are possible +with the switch: + +- Mode 1 (VLAN-unaware): a port is in this mode when it is used as a standalone + net device, or when it is enslaved to a bridge with ``vlan_filtering=0``. +- Mode 2 (fully VLAN-aware): a port is in this mode when it is enslaved to a + bridge with ``vlan_filtering=1``. Access to the entire VLAN range is given to + the user through ``bridge vlan`` commands, but general-purpose (anything + other than STP, PTP etc) traffic termination is not possible through the + switch net devices. The other packets can be still by user space processed + through the DSA master interface (similar to ``DSA_TAG_PROTO_NONE``). +- Mode 3 (best-effort VLAN-aware): a port is in this mode when enslaved to a + bridge with ``vlan_filtering=1``, and the devlink property of its parent + switch named ``best_effort_vlan_filtering`` is set to ``true``. When + configured like this, the range of usable VIDs is reduced (0 to 1023 and 3072 + to 4094), so is the number of usable VIDs (maximum of 7 non-pvid VLANs per + port*), and shared VLAN learning is performed (FDB lookup is done only by + DMAC, not also by VID). + +To summarize, in each mode, the following types of traffic are supported over +the switch net devices: + ++-------------+-----------+--------------+------------+ +| | Mode 1 | Mode 2 | Mode 3 | ++=============+===========+==============+============+ +| Regular | Yes | No | Yes | +| traffic | | (use master) | | ++-------------+-----------+--------------+------------+ +| Management | Yes | Yes | Yes | +| traffic | | | | +| (BPDU, PTP) | | | | ++-------------+-----------+--------------+------------+ + +To configure the switch to operate in Mode 3, the following steps can be +followed:: + + ip link add dev br0 type bridge + # swp2 operates in Mode 1 now + ip link set dev swp2 master br0 + # swp2 temporarily moves to Mode 2 + ip link set dev br0 type bridge vlan_filtering 1 + [ 61.204770] sja1105 spi0.1: Reset switch and programmed static config. Reason: VLAN filtering + [ 61.239944] sja1105 spi0.1: Disabled switch tagging + # swp3 now operates in Mode 3 + devlink dev param set spi/spi0.1 name best_effort_vlan_filtering value true cmode runtime + [ 64.682927] sja1105 spi0.1: Reset switch and programmed static config. Reason: VLAN filtering + [ 64.711925] sja1105 spi0.1: Enabled switch tagging + # Cannot use VLANs in range 1024-3071 while in Mode 3. + bridge vlan add dev swp2 vid 1025 untagged pvid + RTNETLINK answers: Operation not permitted + bridge vlan add dev swp2 vid 100 + bridge vlan add dev swp2 vid 101 untagged + bridge vlan + port vlan ids + swp5 1 PVID Egress Untagged + + swp2 1 PVID Egress Untagged + 100 + 101 Egress Untagged + + swp3 1 PVID Egress Untagged + + swp4 1 PVID Egress Untagged + + br0 1 PVID Egress Untagged + bridge vlan add dev swp2 vid 102 + bridge vlan add dev swp2 vid 103 + bridge vlan add dev swp2 vid 104 + bridge vlan add dev swp2 vid 105 + bridge vlan add dev swp2 vid 106 + bridge vlan add dev swp2 vid 107 + # Cannot use mode than 7 VLANs per port while in Mode 3. + [ 3885.216832] sja1105 spi0.1: No more free subvlans + +\* "maximum of 7 non-pvid VLANs per port": Decoding VLAN-tagged packets on the +CPU in mode 3 is possible through VLAN retagging of packets that go from the +switch to the CPU. In cross-chip topologies, the port that goes to the CPU +might also go to other switches. In that case, those other switches will see +only a retagged packet (which only has meaning for the CPU). So if they are +interested in this VLAN, they need to apply retagging in the reverse direction, +to recover the original value from it. This consumes extra hardware resources +for this switch. There is a maximum of 32 entries in the Retagging Table of +each switch device. + +As an example, consider this cross-chip topology:: + + +-------------------------------------------------+ + | Host SoC | + | +-------------------------+ | + | | DSA master for embedded | | + | | switch (non-sja1105) | | + | +--------+-------------------------+--------+ | + | | embedded L2 switch | | + | | | | + | | +--------------+ +--------------+ | | + | | |DSA master for| |DSA master for| | | + | | | SJA1105 1 | | SJA1105 2 | | | + +--+---+--------------+-----+--------------+---+--+ + + +-----------------------+ +-----------------------+ + | SJA1105 switch 1 | | SJA1105 switch 2 | + +-----+-----+-----+-----+ +-----+-----+-----+-----+ + |sw1p0|sw1p1|sw1p2|sw1p3| |sw2p0|sw2p1|sw2p2|sw2p3| + +-----+-----+-----+-----+ +-----+-----+-----+-----+ + +To reach the CPU, SJA1105 switch 1 (spi/spi2.1) uses the same port as is uses +to reach SJA1105 switch 2 (spi/spi2.2), which would be port 4 (not drawn). +Similarly for SJA1105 switch 2. + +Also consider the following commands, that add VLAN 100 to every sja1105 user +port:: + + devlink dev param set spi/spi2.1 name best_effort_vlan_filtering value true cmode runtime + devlink dev param set spi/spi2.2 name best_effort_vlan_filtering value true cmode runtime + ip link add dev br0 type bridge + for port in sw1p0 sw1p1 sw1p2 sw1p3 \ + sw2p0 sw2p1 sw2p2 sw2p3; do + ip link set dev $port master br0 + done + ip link set dev br0 type bridge vlan_filtering 1 + for port in sw1p0 sw1p1 sw1p2 sw1p3 \ + sw2p0 sw2p1 sw2p2; do + bridge vlan add dev $port vid 100 + done + ip link add link br0 name br0.100 type vlan id 100 && ip link set dev br0.100 up + ip addr add 192.168.100.3/24 dev br0.100 + bridge vlan add dev br0 vid 100 self + + bridge vlan + port vlan ids + sw1p0 1 PVID Egress Untagged + 100 + + sw1p1 1 PVID Egress Untagged + 100 + + sw1p2 1 PVID Egress Untagged + 100 + + sw1p3 1 PVID Egress Untagged + 100 + + sw2p0 1 PVID Egress Untagged + 100 + + sw2p1 1 PVID Egress Untagged + 100 + + sw2p2 1 PVID Egress Untagged + 100 + + sw2p3 1 PVID Egress Untagged + + br0 1 PVID Egress Untagged + 100 + +SJA1105 switch 1 consumes 1 retagging entry for each VLAN on each user port +towards the CPU. It also consumes 1 retagging entry for each non-pvid VLAN that +it is also interested in, which is configured on any port of any neighbor +switch. + +In this case, SJA1105 switch 1 consumes a total of 11 retagging entries, as +follows: +- 8 retagging entries for VLANs 1 and 100 installed on its user ports + (``sw1p0`` - ``sw1p3``) +- 3 retagging entries for VLAN 100 installed on the user ports of SJA1105 + switch 2 (``sw2p0`` - ``sw2p2``), because it also has ports that are + interested in it. The VLAN 1 is a pvid on SJA1105 switch 2 and does not need + reverse retagging. + +SJA1105 switch 2 also consumes 11 retagging entries, but organized as follows: +- 7 retagging entries for the bridge VLANs on its user ports (``sw2p0`` - + ``sw2p3``). +- 4 retagging entries for VLAN 100 installed on the user ports of SJA1105 + switch 1 (``sw1p0`` - ``sw1p3``). Switching features ==================