Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1613501 > unrolled thread

[PATCH net-next v2 0/9] net: dsa: mv88e6xxx: program cross-chip bridging

Started byVivien Didelot <vivien.didelot@savoirfairelinux.com>
First post2017-03-30 23:50 +0200
Last post2017-04-01 21:30 +0200
Articles 12 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH net-next v2 0/9] net: dsa: mv88e6xxx: program cross-chip bridging Vivien Didelot <vivien.didelot@savoirfairelinux.com> - 2017-03-30 23:50 +0200
    [PATCH net-next v2 2/9] net: dsa: mv88e6xxx: use 4-bit port for PVT data Vivien Didelot <vivien.didelot@savoirfairelinux.com> - 2017-03-30 23:50 +0200
      Re: [PATCH net-next v2 2/9] net: dsa: mv88e6xxx: use 4-bit port for  PVT data Andrew Lunn <andrew@lunn.ch> - 2017-03-31 18:40 +0200
    [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging Vivien Didelot <vivien.didelot@savoirfairelinux.com> - 2017-03-30 23:50 +0200
      Re: [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip  bridging Andrew Lunn <andrew@lunn.ch> - 2017-03-31 18:50 +0200
        Re: [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging Vivien Didelot <vivien.didelot@savoirfairelinux.com> - 2017-03-31 19:00 +0200
          Re: [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip  bridging Andrew Lunn <andrew@lunn.ch> - 2017-03-31 19:20 +0200
            Re: [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging Vivien Didelot <vivien.didelot@savoirfairelinux.com> - 2017-03-31 19:30 +0200
    [PATCH net-next v2 5/9] net: dsa: mv88e6xxx: rework in-chip bridging Vivien Didelot <vivien.didelot@savoirfairelinux.com> - 2017-03-30 23:50 +0200
    [PATCH net-next v2 6/9] net: dsa: mv88e6xxx: factorize in-chip bridge map Vivien Didelot <vivien.didelot@savoirfairelinux.com> - 2017-03-30 23:50 +0200
    [PATCH net-next v2 8/9] net: dsa: add cross-chip bridging operations Vivien Didelot <vivien.didelot@savoirfairelinux.com> - 2017-03-30 23:50 +0200
    Re: [PATCH net-next v2 0/9] net: dsa: mv88e6xxx: program  cross-chip bridging David Miller <davem@davemloft.net> - 2017-04-01 21:30 +0200

#1613501 — [PATCH net-next v2 0/9] net: dsa: mv88e6xxx: program cross-chip bridging

FromVivien Didelot <vivien.didelot@savoirfairelinux.com>
Date2017-03-30 23:50 +0200
Subject[PATCH net-next v2 0/9] net: dsa: mv88e6xxx: program cross-chip bridging
Message-ID<tqQ77-42d-9@gated-at.bofh.it>
The purpose of this patch series is to bring hardware cross-chip
bridging configuration to the DSA layer and the mv88e6xxx DSA driver.

Most recent Marvell switch chips have a Cross-chip Port Based VLAN Table
(PVT) used to restrict to which internal destination port an arbitrary
external source port is allowed to egress frames to.

The current behavior of the mv88e6xxx driver is to program this table
table with all ones, allowing any external ports to egress frames on any
internal ports. This means that carefully crafted Ethernet frames can
potentially bypass the user bridging configuration.

Patches 1 to 7 prepare the setup of this table and factorize the common
bits of both in-chip and cross-chip Marvell bridging code.

Patch 8 adds new optional cross-chip bridging operations to DSA switch.

Patch 9 switches the current behavior to program the table according to
the user bridging configuration when (cross-chip) ports get (un)bridged.

On a ZII Rev B board, bridging together the 3 user ports of both 88E6352
will result in the following PVTs on respectively switch 0 and switch 1:

    External   Internal Ports
    Dev Port   0  1  2  3  4  5  6

     1    0    *  *  *  -  -  *  *
     1    1    *  *  *  -  -  *  *
     1    2    *  *  *  -  -  *  *
     1    3    -  -  -  -  -  *  *
     1    4    -  -  -  -  -  *  *
     1    5    *  *  *  *  *  *  *
     1    6    *  *  *  *  *  *  *

     0    0    *  *  *  -  -  *  *
     0    1    *  *  *  -  -  *  *
     0    2    *  *  *  -  -  *  *
     0    3    -  -  -  -  -  *  *
     0    4    -  -  -  -  -  *  *
     0    5    *  *  *  *  *  *  *
     0    6    *  *  *  *  *  *  *

Changes since v2:
  - Define MV88E6XXX_MAX_PVT_SWITCHES and MV88E6XXX_MAX_PVT_PORTS
  - use mv88e6xxx_g2_misc_4_bit_port instead of the 5-bit variant
  - add Andrew's tags and reword commit 6/9


Vivien Didelot (9):
  net: dsa: mv88e6xxx: move PVT description in info
  net: dsa: mv88e6xxx: use 4-bit port for PVT data
  net: dsa: mv88e6xxx: program the PVT with all ones
  net: dsa: mv88e6xxx: allocate the number of ports
  net: dsa: mv88e6xxx: rework in-chip bridging
  net: dsa: mv88e6xxx: factorize in-chip bridge map
  net: dsa: mv88e6xxx: remap existing bridge members
  net: dsa: add cross-chip bridging operations
  net: dsa: mv88e6xxx: add cross-chip bridging

 drivers/net/dsa/mv88e6xxx/chip.c      | 212 ++++++++++++++++++++++++++++------
 drivers/net/dsa/mv88e6xxx/global2.c   |  77 ++++++++++--
 drivers/net/dsa/mv88e6xxx/global2.h   |  15 +++
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h |  37 +++---
 include/net/dsa.h                     |   8 ++
 net/dsa/switch.c                      |  12 +-
 6 files changed, 288 insertions(+), 73 deletions(-)

-- 
2.12.1

[toc] | [next] | [standalone]


#1613502 — [PATCH net-next v2 2/9] net: dsa: mv88e6xxx: use 4-bit port for PVT data

FromVivien Didelot <vivien.didelot@savoirfairelinux.com>
Date2017-03-30 23:50 +0200
Subject[PATCH net-next v2 2/9] net: dsa: mv88e6xxx: use 4-bit port for PVT data
Message-ID<tqQ78-42d-29@gated-at.bofh.it>
In reply to#1613501
The Cross-chip Port Based VLAN Table (PVT) supports two indexing modes,
one using 5-bit for device and 4-bit for port, the other using 4-bit for
device and 5-bit for port, configured via the Global 2 Misc register.

Only 4 bits for the source port are needed when interconnecting 88E6xxx
switch devices since they all support less than 16 physical ports. The
full 5 bits are needed when interconnecting a device with 98DXxxx switch
devices since they support more than 16 physical ports.

Add a mv88e6xxx_pvt_setup helper to set the 4-bit port PVT mode, which
will be extended later to also initialize the PVT content.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 drivers/net/dsa/mv88e6xxx/chip.c      | 15 +++++++++++++++
 drivers/net/dsa/mv88e6xxx/global2.c   | 25 +++++++++++++++++++++++++
 drivers/net/dsa/mv88e6xxx/global2.h   |  7 +++++++
 drivers/net/dsa/mv88e6xxx/mv88e6xxx.h |  1 +
 4 files changed, 48 insertions(+)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 8f1f881d0375..2a32bb490f92 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1198,6 +1198,17 @@ static int mv88e6xxx_atu_setup(struct mv88e6xxx_chip *chip)
 	return mv88e6xxx_g1_atu_set_age_time(chip, 300000);
 }
 
+static int mv88e6xxx_pvt_setup(struct mv88e6xxx_chip *chip)
+{
+	if (!mv88e6xxx_has_pvt(chip))
+		return 0;
+
+	/* Clear 5 Bit Port for usage with Marvell Link Street devices:
+	 * use 4 bits for the Src_Port/Src_Trunk and 5 bits for the Src_Dev.
+	 */
+	return mv88e6xxx_g2_misc_4_bit_port(chip);
+}
+
 static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
 {
 	struct mv88e6xxx_chip *chip = ds->priv;
@@ -2594,6 +2605,10 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
 			goto unlock;
 	}
 
+	err = mv88e6xxx_pvt_setup(chip);
+	if (err)
+		goto unlock;
+
 	err = mv88e6xxx_atu_setup(chip);
 	if (err)
 		goto unlock;
diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
index 6228aab2ad35..d64f4c15ccb7 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.c
+++ b/drivers/net/dsa/mv88e6xxx/global2.c
@@ -784,6 +784,31 @@ static int mv88e6xxx_g2_watchdog_setup(struct mv88e6xxx_chip *chip)
 	return err;
 }
 
+/* Offset 0x1D: Misc Register */
+
+static int mv88e6xxx_g2_misc_5_bit_port(struct mv88e6xxx_chip *chip,
+					bool port_5_bit)
+{
+	u16 val;
+	int err;
+
+	err = mv88e6xxx_g2_read(chip, GLOBAL2_MISC, &val);
+	if (err)
+		return err;
+
+	if (port_5_bit)
+		val |= GLOBAL2_MISC_5_BIT_PORT;
+	else
+		val &= ~GLOBAL2_MISC_5_BIT_PORT;
+
+	return mv88e6xxx_g2_write(chip, GLOBAL2_MISC, val);
+}
+
+int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)
+{
+	return mv88e6xxx_g2_misc_5_bit_port(chip, false);
+}
+
 static void mv88e6xxx_g2_irq_mask(struct irq_data *d)
 {
 	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h
index f8b6dd93213a..71fb2ff541ba 100644
--- a/drivers/net/dsa/mv88e6xxx/global2.h
+++ b/drivers/net/dsa/mv88e6xxx/global2.h
@@ -42,6 +42,8 @@ int mv88e6xxx_g2_get_eeprom16(struct mv88e6xxx_chip *chip,
 int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
 			      struct ethtool_eeprom *eeprom, u8 *data);
 
+int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip);
+
 int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip);
 int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip);
 void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip);
@@ -110,6 +112,11 @@ static inline int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
 	return -EOPNOTSUPP;
 }
 
+int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)
+{
+	return -EOPNOTSUPP;
+}
+
 static inline int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
 {
 	return -EOPNOTSUPP;
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index 97dd3e2d2a56..bcaa55b20f5a 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -439,6 +439,7 @@
 #define GLOBAL2_WDOG_FORCE_IRQ			BIT(0)
 #define GLOBAL2_QOS_WEIGHT	0x1c
 #define GLOBAL2_MISC		0x1d
+#define GLOBAL2_MISC_5_BIT_PORT	BIT(14)
 
 #define MV88E6XXX_N_FID		4096
 
-- 
2.12.1

[toc] | [prev] | [next] | [standalone]


#1614139 — Re: [PATCH net-next v2 2/9] net: dsa: mv88e6xxx: use 4-bit port for PVT data

FromAndrew Lunn <andrew@lunn.ch>
Date2017-03-31 18:40 +0200
SubjectRe: [PATCH net-next v2 2/9] net: dsa: mv88e6xxx: use 4-bit port for PVT data
Message-ID<tr7KF-714-5@gated-at.bofh.it>
In reply to#1613502
> +/* Offset 0x1D: Misc Register */
> +
> +static int mv88e6xxx_g2_misc_5_bit_port(struct mv88e6xxx_chip *chip,
> +					bool port_5_bit)
> +{
> +	u16 val;
> +	int err;
> +
> +	err = mv88e6xxx_g2_read(chip, GLOBAL2_MISC, &val);
> +	if (err)
> +		return err;
> +
> +	if (port_5_bit)
> +		val |= GLOBAL2_MISC_5_BIT_PORT;
> +	else
> +		val &= ~GLOBAL2_MISC_5_BIT_PORT;
> +
> +	return mv88e6xxx_g2_write(chip, GLOBAL2_MISC, val);
> +}
> +
> +int mv88e6xxx_g2_misc_4_bit_port(struct mv88e6xxx_chip *chip)
> +{
> +	return mv88e6xxx_g2_misc_5_bit_port(chip, false);
> +}

Hi Vivien

Yes, i know, i'm nit-picking. The function naming is confusing here.
What would you call this function:

int mv88e6xxx_g2_misc_XXXXX(struct mv88e6xxx_chip *chip)
{
	return mv88e6xxx_g2_misc_5_bit_port(chip, true);
}

Thanks
	Andrew

[toc] | [prev] | [next] | [standalone]


#1613503 — [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging

FromVivien Didelot <vivien.didelot@savoirfairelinux.com>
Date2017-03-30 23:50 +0200
Subject[PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging
Message-ID<tqQ78-42d-31@gated-at.bofh.it>
In reply to#1613501
Implement the DSA cross-chip bridging operations by remapping the local
ports an external source port can egress frames to, when this cross-chip
port joins or leaves a bridge.

The PVT is no longer configured with all ones allowing any external
frame to egress any local port. Only DSA and CPU ports, as well as
bridge group members, can egress frames on local ports.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 drivers/net/dsa/mv88e6xxx/chip.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index c6f45a2a9335..44ba8cff5631 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1222,7 +1222,7 @@ static int mv88e6xxx_pvt_map(struct mv88e6xxx_chip *chip, int dev, int port)
 
 	/* Skip the local source device, which uses in-chip port VLAN */
 	if (dev != chip->ds->index)
-		pvlan = mv88e6xxx_port_mask(chip);
+		pvlan = mv88e6xxx_port_vlan(chip, dev, port);
 
 	return mv88e6xxx_g2_pvt_write(chip, dev, port, pvlan);
 }
@@ -2203,6 +2203,36 @@ static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port,
 	mutex_unlock(&chip->reg_lock);
 }
 
+static int mv88e6xxx_crosschip_bridge_join(struct dsa_switch *ds, int dev,
+					   int port, struct net_device *br)
+{
+	struct mv88e6xxx_chip *chip = ds->priv;
+	int err;
+
+	if (!mv88e6xxx_has_pvt(chip))
+		return 0;
+
+	mutex_lock(&chip->reg_lock);
+	err = mv88e6xxx_pvt_map(chip, dev, port);
+	mutex_unlock(&chip->reg_lock);
+
+	return err;
+}
+
+static void mv88e6xxx_crosschip_bridge_leave(struct dsa_switch *ds, int dev,
+					     int port, struct net_device *br)
+{
+	struct mv88e6xxx_chip *chip = ds->priv;
+
+	if (!mv88e6xxx_has_pvt(chip))
+		return;
+
+	mutex_lock(&chip->reg_lock);
+	if (mv88e6xxx_pvt_map(chip, dev, port))
+		dev_err(ds->dev, "failed to remap cross-chip Port VLAN\n");
+	mutex_unlock(&chip->reg_lock);
+}
+
 static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip)
 {
 	if (chip->info->ops->reset)
@@ -4313,6 +4343,8 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
 	.port_mdb_add           = mv88e6xxx_port_mdb_add,
 	.port_mdb_del           = mv88e6xxx_port_mdb_del,
 	.port_mdb_dump          = mv88e6xxx_port_mdb_dump,
+	.crosschip_bridge_join	= mv88e6xxx_crosschip_bridge_join,
+	.crosschip_bridge_leave	= mv88e6xxx_crosschip_bridge_leave,
 };
 
 static struct dsa_switch_driver mv88e6xxx_switch_drv = {
-- 
2.12.1

[toc] | [prev] | [next] | [standalone]


#1614147 — Re: [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging

FromAndrew Lunn <andrew@lunn.ch>
Date2017-03-31 18:50 +0200
SubjectRe: [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging
Message-ID<tr7Um-76y-15@gated-at.bofh.it>
In reply to#1613503
On Thu, Mar 30, 2017 at 05:37:15PM -0400, Vivien Didelot wrote:
> Implement the DSA cross-chip bridging operations by remapping the local
> ports an external source port can egress frames to, when this cross-chip
> port joins or leaves a bridge.
> 
> The PVT is no longer configured with all ones allowing any external
> frame to egress any local port. Only DSA and CPU ports, as well as
> bridge group members, can egress frames on local ports.

Hi Vivien

With the ZII devel B, we have two switches with PVT, and one
without. What happens in this setup? Can the non-PVT switch leak
frames out user ports which should otherwise be blocked?

Thanks
	Andrew

[toc] | [prev] | [next] | [standalone]


#1614156 — Re: [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging

FromVivien Didelot <vivien.didelot@savoirfairelinux.com>
Date2017-03-31 19:00 +0200
SubjectRe: [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging
Message-ID<tr842-7ax-11@gated-at.bofh.it>
In reply to#1614147
Hi Andrew,

Andrew Lunn <andrew@lunn.ch> writes:

> On Thu, Mar 30, 2017 at 05:37:15PM -0400, Vivien Didelot wrote:
>> Implement the DSA cross-chip bridging operations by remapping the local
>> ports an external source port can egress frames to, when this cross-chip
>> port joins or leaves a bridge.
>> 
>> The PVT is no longer configured with all ones allowing any external
>> frame to egress any local port. Only DSA and CPU ports, as well as
>> bridge group members, can egress frames on local ports.
>
> With the ZII devel B, we have two switches with PVT, and one
> without. What happens in this setup? Can the non-PVT switch leak
> frames out user ports which should otherwise be blocked?

If CONFIG_BRIDGE_VLAN_FILTERING isn't enabled in the kernel, the non-PVT
switch would indeed have no mean to restrict arbitrary external
frames. So in that setup, yes the switch can theorically leak frames.

With a VLAN-filtering aware system, the VTU policy and 802.1Q Secure
port mode should guard against that.

Thanks,

        Vivien

[toc] | [prev] | [next] | [standalone]


#1614172 — Re: [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging

FromAndrew Lunn <andrew@lunn.ch>
Date2017-03-31 19:20 +0200
SubjectRe: [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging
Message-ID<tr8nn-7xP-1@gated-at.bofh.it>
In reply to#1614156
On Fri, Mar 31, 2017 at 12:55:03PM -0400, Vivien Didelot wrote:
> Hi Andrew,
> 
> Andrew Lunn <andrew@lunn.ch> writes:
> 
> > On Thu, Mar 30, 2017 at 05:37:15PM -0400, Vivien Didelot wrote:
> >> Implement the DSA cross-chip bridging operations by remapping the local
> >> ports an external source port can egress frames to, when this cross-chip
> >> port joins or leaves a bridge.
> >> 
> >> The PVT is no longer configured with all ones allowing any external
> >> frame to egress any local port. Only DSA and CPU ports, as well as
> >> bridge group members, can egress frames on local ports.
> >
> > With the ZII devel B, we have two switches with PVT, and one
> > without. What happens in this setup? Can the non-PVT switch leak
> > frames out user ports which should otherwise be blocked?
> 
> If CONFIG_BRIDGE_VLAN_FILTERING isn't enabled in the kernel, the non-PVT
> switch would indeed have no mean to restrict arbitrary external
> frames. So in that setup, yes the switch can theorically leak frames.

I don't like the idea of leaking frames. It has security implications,
and hard to debug weird networking problems, like some other machine
is using my IP address, maybe spanning tree is broken if BPDUs leak,
even broadcast storms?

So we need to consider the complexity of detecting we have a non-PVT
destination switch, and forward it frames via the software bridge.

What about the case the non-PVT switch is in the middle of a chain of
PVT switches?

Maybe to start with, to keep it simple, we check all switches are PVT
capable. If they are not, we refuse to use PVT and all inter-switch
frames need to go via the Linux software bridge?

       Andrew

[toc] | [prev] | [next] | [standalone]


#1614177 — Re: [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging

FromVivien Didelot <vivien.didelot@savoirfairelinux.com>
Date2017-03-31 19:30 +0200
SubjectRe: [PATCH net-next v2 9/9] net: dsa: mv88e6xxx: add cross-chip bridging
Message-ID<tr8x3-7BG-3@gated-at.bofh.it>
In reply to#1614172
Hi Andrew,

Andrew Lunn <andrew@lunn.ch> writes:

> I don't like the idea of leaking frames.

I don't like it neither. That's why this patch series is out there. It
improves the security on PVT-capable Marvell switches by programming the
tables correctly on bridging events.

A next step can be to warn the user about the software or hardware
limitations (s)he is currently experiencing with something roughly like
this in cross-chip bridging operations:

    if (!mv88e6xxx_has_pvt(chip)) {
    #if IS_ENABLED(BRIDGE_VLAN_FILTERING)
        return 0;
    #else
        pr_err("Cross-chip bridging is forbidden on non-PVT hardware and
               non-VLAN-filtering aware systems\n");
        return -EINVAL;
    #endif
    }

But let's keep it simple for the moment and go baby steps. First program
PVT tables correctly as this patchset does, then figure out how to
handle non-PVT systems. That is a good topic for next week ;-)

Thanks,

        Vivien

[toc] | [prev] | [next] | [standalone]


#1613504 — [PATCH net-next v2 5/9] net: dsa: mv88e6xxx: rework in-chip bridging

FromVivien Didelot <vivien.didelot@savoirfairelinux.com>
Date2017-03-30 23:50 +0200
Subject[PATCH net-next v2 5/9] net: dsa: mv88e6xxx: rework in-chip bridging
Message-ID<tqQ78-42d-37@gated-at.bofh.it>
In reply to#1613501
All ports -- internal and external, for chips featuring a PVT -- have a
mask restricting to which internal ports a frame is allowed to egress.

Now that DSA exposes the number of ports and their bridge devices, it is
possible to extract the code generating the VLAN map and make it generic
so that it can be shared later with the cross-chip bridging code.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx/chip.c | 53 ++++++++++++++++++++++++++--------------
 1 file changed, 34 insertions(+), 19 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 28bdfadbf050..9b2d369715d7 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1123,27 +1123,42 @@ static int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
 	return err;
 }
 
+static u16 mv88e6xxx_port_vlan(struct mv88e6xxx_chip *chip, int dev, int port)
+{
+	struct dsa_switch *ds = NULL;
+	struct net_device *br;
+	u16 pvlan;
+	int i;
+
+	if (dev < DSA_MAX_SWITCHES)
+		ds = chip->ds->dst->ds[dev];
+
+	/* Prevent frames from unknown switch or port */
+	if (!ds || port >= ds->num_ports)
+		return 0;
+
+	/* Frames from DSA links and CPU ports can egress any local port */
+	if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
+		return mv88e6xxx_port_mask(chip);
+
+	br = ds->ports[port].bridge_dev;
+	pvlan = 0;
+
+	/* Frames from user ports can egress any local DSA links and CPU ports,
+	 * as well as any local member of their bridge group.
+	 */
+	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
+		if (dsa_is_cpu_port(chip->ds, i) ||
+		    dsa_is_dsa_port(chip->ds, i) ||
+		    (br && chip->ds->ports[i].bridge_dev == br))
+			pvlan |= BIT(i);
+
+	return pvlan;
+}
+
 static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port)
 {
-	struct dsa_switch *ds = chip->ds;
-	struct net_device *bridge = ds->ports[port].bridge_dev;
-	u16 output_ports = 0;
-	int i;
-
-	/* allow CPU port or DSA link(s) to send frames to every port */
-	if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
-		output_ports = ~0;
-	} else {
-		for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
-			/* allow sending frames to every group member */
-			if (bridge && ds->ports[i].bridge_dev == bridge)
-				output_ports |= BIT(i);
-
-			/* allow sending frames to CPU port and DSA link(s) */
-			if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
-				output_ports |= BIT(i);
-		}
-	}
+	u16 output_ports = mv88e6xxx_port_vlan(chip, chip->ds->index, port);
 
 	/* prevent frames from going back out of the port they came in on */
 	output_ports &= ~BIT(port);
-- 
2.12.1

[toc] | [prev] | [next] | [standalone]


#1613505 — [PATCH net-next v2 6/9] net: dsa: mv88e6xxx: factorize in-chip bridge map

FromVivien Didelot <vivien.didelot@savoirfairelinux.com>
Date2017-03-30 23:50 +0200
Subject[PATCH net-next v2 6/9] net: dsa: mv88e6xxx: factorize in-chip bridge map
Message-ID<tqQ79-42d-39@gated-at.bofh.it>
In reply to#1613501
Factorize the code in the DSA port_bridge_{join,leave} routines used to
program the port VLAN map of all local ports of a given bridge group.

At the same time shorten the _mv88e6xxx_port_based_vlan_map to get rid
of the old underscore prefix naming convention.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/net/dsa/mv88e6xxx/chip.c | 47 +++++++++++++++++++++-------------------
 1 file changed, 25 insertions(+), 22 deletions(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 9b2d369715d7..3802e1bdd111 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1156,7 +1156,7 @@ static u16 mv88e6xxx_port_vlan(struct mv88e6xxx_chip *chip, int dev, int port)
 	return pvlan;
 }
 
-static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port)
+static int mv88e6xxx_port_vlan_map(struct mv88e6xxx_chip *chip, int port)
 {
 	u16 output_ports = mv88e6xxx_port_vlan(chip, chip->ds->index, port);
 
@@ -2140,23 +2140,32 @@ static int mv88e6xxx_port_fdb_dump(struct dsa_switch *ds, int port,
 	return err;
 }
 
+static int mv88e6xxx_bridge_map(struct mv88e6xxx_chip *chip,
+				struct net_device *br)
+{
+	int port;
+	int err;
+
+	/* Remap the Port VLAN of each local bridge group member */
+	for (port = 0; port < mv88e6xxx_num_ports(chip); ++port) {
+		if (chip->ds->ports[port].bridge_dev == br) {
+			err = mv88e6xxx_port_vlan_map(chip, port);
+			if (err)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
 static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
 				      struct net_device *br)
 {
 	struct mv88e6xxx_chip *chip = ds->priv;
-	int i, err = 0;
+	int err;
 
 	mutex_lock(&chip->reg_lock);
-
-	/* Remap each port's VLANTable */
-	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
-		if (ds->ports[i].bridge_dev == br) {
-			err = _mv88e6xxx_port_based_vlan_map(chip, i);
-			if (err)
-				break;
-		}
-	}
-
+	err = mv88e6xxx_bridge_map(chip, br);
 	mutex_unlock(&chip->reg_lock);
 
 	return err;
@@ -2166,17 +2175,11 @@ static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port,
 					struct net_device *br)
 {
 	struct mv88e6xxx_chip *chip = ds->priv;
-	int i;
 
 	mutex_lock(&chip->reg_lock);
-
-	/* Remap each port's VLANTable */
-	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
-		if (i == port || ds->ports[i].bridge_dev == br)
-			if (_mv88e6xxx_port_based_vlan_map(chip, i))
-				netdev_warn(ds->ports[i].netdev,
-					    "failed to remap\n");
-
+	if (mv88e6xxx_bridge_map(chip, br) ||
+	    mv88e6xxx_port_vlan_map(chip, port))
+		dev_err(ds->dev, "failed to remap in-chip Port VLAN\n");
 	mutex_unlock(&chip->reg_lock);
 }
 
@@ -2490,7 +2493,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
 	if (err)
 		return err;
 
-	err = _mv88e6xxx_port_based_vlan_map(chip, port);
+	err = mv88e6xxx_port_vlan_map(chip, port);
 	if (err)
 		return err;
 
-- 
2.12.1

[toc] | [prev] | [next] | [standalone]


#1613506 — [PATCH net-next v2 8/9] net: dsa: add cross-chip bridging operations

FromVivien Didelot <vivien.didelot@savoirfairelinux.com>
Date2017-03-30 23:50 +0200
Subject[PATCH net-next v2 8/9] net: dsa: add cross-chip bridging operations
Message-ID<tqQ79-42d-41@gated-at.bofh.it>
In reply to#1613501
Introduce crosschip_bridge_{join,leave} operations in the dsa_switch_ops
structure, which can be used by switches supporting interconnection.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
 include/net/dsa.h |  8 ++++++++
 net/dsa/switch.c  | 12 ++++++------
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 951b5e49e899..ffe56cc338fe 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -456,6 +456,14 @@ struct dsa_switch_ops {
 				   bool ingress);
 	void	(*port_mirror_del)(struct dsa_switch *ds, int port,
 				   struct dsa_mall_mirror_tc_entry *mirror);
+
+	/*
+	 * Cross-chip operations
+	 */
+	int	(*crosschip_bridge_join)(struct dsa_switch *ds, int sw_index,
+					 int port, struct net_device *br);
+	void	(*crosschip_bridge_leave)(struct dsa_switch *ds, int sw_index,
+					  int port, struct net_device *br);
 };
 
 struct dsa_switch_driver {
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 7b6f38e5fef6..ca6e26e514f0 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -20,9 +20,9 @@ static int dsa_switch_bridge_join(struct dsa_switch *ds,
 	if (ds->index == info->sw_index && ds->ops->port_bridge_join)
 		return ds->ops->port_bridge_join(ds, info->port, info->br);
 
-	if (ds->index != info->sw_index)
-		dev_dbg(ds->dev, "crosschip DSA port %d.%d bridged to %s\n",
-			info->sw_index, info->port, netdev_name(info->br));
+	if (ds->index != info->sw_index && ds->ops->crosschip_bridge_join)
+		return ds->ops->crosschip_bridge_join(ds, info->sw_index,
+						      info->port, info->br);
 
 	return 0;
 }
@@ -33,9 +33,9 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds,
 	if (ds->index == info->sw_index && ds->ops->port_bridge_leave)
 		ds->ops->port_bridge_leave(ds, info->port, info->br);
 
-	if (ds->index != info->sw_index)
-		dev_dbg(ds->dev, "crosschip DSA port %d.%d unbridged from %s\n",
-			info->sw_index, info->port, netdev_name(info->br));
+	if (ds->index != info->sw_index && ds->ops->crosschip_bridge_leave)
+		ds->ops->crosschip_bridge_leave(ds, info->sw_index, info->port,
+						info->br);
 
 	return 0;
 }
-- 
2.12.1

[toc] | [prev] | [next] | [standalone]


#1614586 — Re: [PATCH net-next v2 0/9] net: dsa: mv88e6xxx: program cross-chip bridging

FromDavid Miller <davem@davemloft.net>
Date2017-04-01 21:30 +0200
SubjectRe: [PATCH net-next v2 0/9] net: dsa: mv88e6xxx: program cross-chip bridging
Message-ID<trwSK-6VO-13@gated-at.bofh.it>
In reply to#1613501
From: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Date: Thu, 30 Mar 2017 17:37:06 -0400

> The purpose of this patch series is to bring hardware cross-chip
> bridging configuration to the DSA layer and the mv88e6xxx DSA driver.

This series seems like a step in the right direction so I have applied
it to net-next.  We can address non-PVT setups and other issues in
follow-up changes.

Thanks!

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web