lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 18 Sep 2019 17:36:08 +0300
From:   Vladimir Oltean <olteanv@...il.com>
To:     Sascha Hauer <s.hauer@...gutronix.de>
Cc:     netdev <netdev@...r.kernel.org>, Andrew Lunn <andrew@...n.ch>,
        Vivien Didelot <vivien.didelot@...oirfairelinux.com>,
        Florian Fainelli <f.fainelli@...il.com>, kernel@...gutronix.de
Subject: Re: dsa traffic priorization

Hi Sascha,

On Wed, 18 Sep 2019 at 17:03, Sascha Hauer <s.hauer@...gutronix.de> wrote:
>
> Hi All,
>
> We have a customer using a Marvell 88e6240 switch with Ethercat on one port and
> regular network traffic on another port. The customer wants to configure two things
> on the switch: First Ethercat traffic shall be priorized over other network traffic
> (effectively prioritizing traffic based on port). Second the ethernet controller
> in the CPU is not able to handle full bandwidth traffic, so the traffic to the CPU
> port shall be rate limited.
>

You probably already know this, but egress shaping will not drop
frames, just let them accumulate in the egress queue until something
else happens (e.g. queue occupancy threshold triggers pause frames, or
tail dropping is enabled, etc). Is this what you want? It sounds a bit
strange to me to configure egress shaping on the CPU port of a DSA
switch. That literally means you are buffering frames inside the
system. What about ingress policing?

> For reference the patch below configures the switch to their needs. Now the question
> is how this can be implemented in a way suitable for mainline. It looks like the per
> port priority mapping for VLAN tagged packets could be done via ip link add link ...
> ingress-qos-map QOS-MAP. How the default priority would be set is unclear to me.
>

Technically, configuring a match-all rxnfc rule with ethtool would
count as 'default priority' - I have proposed that before. Now I'm not
entirely sure how intuitive it is, but I'm also interested in being
able to configure this.

> The other part of the problem seems to be that the CPU port has no network device
> representation in Linux, so there's no interface to configure the egress limits via tc.
> This has been discussed before, but it seems there hasn't been any consensous regarding how
> we want to proceed?
>
> Sascha
>
> -----------------------------8<-----------------------------------
>
>  drivers/net/dsa/mv88e6xxx/chip.c | 54 +++++++++++++++++++-
>  drivers/net/dsa/mv88e6xxx/port.c | 87 ++++++++++++++++++++++++++++++++
>  drivers/net/dsa/mv88e6xxx/port.h | 19 +++++++
>  3 files changed, 159 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
> index d0a97eb73a37..2a15cf259d04 100644
> --- a/drivers/net/dsa/mv88e6xxx/chip.c
> +++ b/drivers/net/dsa/mv88e6xxx/chip.c
> @@ -2090,7 +2090,9 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
>  {
>          struct dsa_switch *ds = chip->ds;
>          int err;
> +        u16 addr;
>          u16 reg;
> +        u16 val;
>
>          chip->ports[port].chip = chip;
>          chip->ports[port].port = port;
> @@ -2246,7 +2248,57 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
>          /* Default VLAN ID and priority: don't set a default VLAN
>           * ID, and set the default packet priority to zero.
>           */
> -        return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN, 0);
> +        err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_DEFAULT_VLAN, 0);
> +        if (err)
> +                return err;
> +
> +#define SWITCH_CPU_PORT 5
> +#define SWITCH_ETHERCAT_PORT 3
> +
> +        /* set the egress rate */
> +        switch (port) {
> +                case SWITCH_CPU_PORT:
> +                        err = mv88e6xxx_port_set_egress_rate(chip, port,
> +                                        MV88E6XXX_PORT_EGRESS_RATE_CTL2_COUNT_MODE_FRAME, 30000);
> +                        break;
> +                default:
> +                        err = mv88e6xxx_port_set_egress_rate(chip, port,
> +                                        MV88E6XXX_PORT_EGRESS_RATE_CTL2_COUNT_MODE_FRAME, 0);
> +                        break;
> +        }
> +
> +        if (err)
> +                return err;
> +
> +        /* set the output queue usage */
> +        switch (port) {
> +                case SWITCH_CPU_PORT:
> +                        err = mv88e6xxx_port_set_output_queue_schedule(chip, port,
> +                                        MV88E6XXX_PORT_EGRESS_RATE_CTL2_SCHEDULE_Q3_STRICT);
> +                        break;
> +                default:
> +                        err = mv88e6xxx_port_set_output_queue_schedule(chip, port,
> +                                        MV88E6XXX_PORT_EGRESS_RATE_CTL2_SCHEDULE_NONE_STRICT);
> +                        break;
> +        }
> +
> +        if (err)
> +                return err;
> +
> +        /* set the default QPri */
> +        switch (port) {
> +                case SWITCH_ETHERCAT_PORT:
> +                        err = mv88e6xxx_port_set_default_qpri(chip, port, 3);
> +                        break;
> +                default:
> +                        err = mv88e6xxx_port_set_default_qpri(chip, port, 2);
> +                        break;
> +        }
> +
> +        if (err)
> +                return err;
> +
> +        return 0;
>  }
>
>  static int mv88e6xxx_port_enable(struct dsa_switch *ds, int port,
> diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
> index 04309ef0a1cc..e03f24308f15 100644
> --- a/drivers/net/dsa/mv88e6xxx/port.c
> +++ b/drivers/net/dsa/mv88e6xxx/port.c
> @@ -1147,6 +1147,22 @@ int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
>          return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
>  }
>
> +int mv88e6xxx_port_set_default_qpri(struct mv88e6xxx_chip *chip, int port, int qpri)
> +{
> +        u16 reg;
> +        int err;
> +
> +        err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_CTL2, &reg);
> +        if (err)
> +                return err;
> +
> +        reg &= ~MV88E6XXX_PORT_CTL2_DEF_QPRI_MASK;
> +        reg |= (qpri << 1) & MV88E6XXX_PORT_CTL2_DEF_QPRI_MASK;
> +        reg |= MV88E6XXX_PORT_CTL2_USE_DEF_QPRI;
> +
> +        return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL2, reg);
> +}
> +
>  /* Offset 0x09: Port Rate Control */
>
>  int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
> @@ -1161,6 +1177,77 @@ int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
>                                      0x0001);
>  }
>
> +int mv88e6xxx_port_set_output_queue_schedule(struct mv88e6xxx_chip *chip, int port,
> +                                             u16 schedule)
> +{
> +        u16 reg;
> +        int err;
> +
> +        err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL2, &reg);
> +        if (err)
> +                return err;
> +
> +        reg &= ~MV88E6XXX_PORT_EGRESS_RATE_CTL2_SCHEDULE_MASK;
> +        reg |= schedule;
> +
> +        return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL2, reg);
> +}
> +
> +static int _mv88e6xxx_egress_rate_calc_frames(u32 rate, u16 *egress_rate_val)
> +{
> +        const volatile u32 scale_factor = (1000 * 1000 * 1000);
> +        volatile u32 u;
> +
> +        if (rate > 1488000)
> +                return EINVAL;
> +
> +        if (rate < 7600)
> +                return EINVAL;
> +
> +        u = 32 * rate;
> +        u = scale_factor / u; /* scale_factor used to convert 32s into 32ns */
> +
> +        *egress_rate_val = (u16)u;
> +
> +        return 0;
> +}
> +
> +int mv88e6xxx_port_set_egress_rate(struct mv88e6xxx_chip *chip, int port, u16 type,
> +                                   u32 rate)
> +{
> +        u16 reg;
> +        int err;
> +        u16 egress_rate_val;
> +
> +        err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL2, &reg);
> +        if (err)
> +                return err;
> +
> +        reg &= ~MV88E6XXX_PORT_EGRESS_RATE_CTL2_RATE_MASK;
> +
> +        if (rate) {
> +                reg &= ~MV88E6XXX_PORT_EGRESS_RATE_CTL2_COUNT_MODE_MASK;
> +                reg |= type;
> +
> +                switch (type) {
> +                        case MV88E6XXX_PORT_EGRESS_RATE_CTL2_COUNT_MODE_FRAME:
> +                                err = _mv88e6xxx_egress_rate_calc_frames(rate, &egress_rate_val);
> +                                if (err)
> +                                        return err;
> +                                reg |= egress_rate_val & 0x0FFF;
> +                                break;
> +                        case MV88E6XXX_PORT_EGRESS_RATE_CTL2_COUNT_MODE_L1:
> +                        case MV88E6XXX_PORT_EGRESS_RATE_CTL2_COUNT_MODE_L2:
> +                        case MV88E6XXX_PORT_EGRESS_RATE_CTL2_COUNT_MODE_L3:
> +                                return EINVAL; /* ToDo */
> +                        default:
> +                                return EINVAL;
> +                }
> +        }
> +
> +        return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL2, reg);
> +}
> +
>  /* Offset 0x0C: Port ATU Control */
>
>  int mv88e6xxx_port_disable_learn_limit(struct mv88e6xxx_chip *chip, int port)
> diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
> index 8d5a6cd6fb19..cdd057c52ab8 100644
> --- a/drivers/net/dsa/mv88e6xxx/port.h
> +++ b/drivers/net/dsa/mv88e6xxx/port.h
> @@ -197,6 +197,8 @@
>  #define MV88E6XXX_PORT_CTL2_DEFAULT_FORWARD                0x0040
>  #define MV88E6XXX_PORT_CTL2_EGRESS_MONITOR                0x0020
>  #define MV88E6XXX_PORT_CTL2_INGRESS_MONITOR                0x0010
> +#define MV88E6XXX_PORT_CTL2_USE_DEF_QPRI        0x0008
> +#define MV88E6XXX_PORT_CTL2_DEF_QPRI_MASK        0x0006
>  #define MV88E6095_PORT_CTL2_CPU_PORT_MASK                0x000f
>
>  /* Offset 0x09: Egress Rate Control */
> @@ -204,6 +206,17 @@
>
>  /* Offset 0x0A: Egress Rate Control 2 */
>  #define MV88E6XXX_PORT_EGRESS_RATE_CTL2                0x0a
> +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_COUNT_MODE_MASK 0xC000
> +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_COUNT_MODE_FRAME 0x0000
> +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_COUNT_MODE_L1 0x4000
> +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_COUNT_MODE_L2 0x8000
> +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_COUNT_MODE_L3 0xC000
> +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_SCHEDULE_MASK 0x3000
> +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_SCHEDULE_NONE_STRICT 0x0000
> +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_SCHEDULE_Q3_STRICT 0x1000
> +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_SCHEDULE_Q3_Q2_STRICT 0x2000
> +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_SCHEDULE_ALL_STRICT 0x3000
> +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_RATE_MASK 0x0FFF
>
>  /* Offset 0x0B: Port Association Vector */
>  #define MV88E6XXX_PORT_ASSOC_VECTOR                        0x0b
> @@ -326,8 +339,14 @@ int mv88e6xxx_port_set_message_port(struct mv88e6xxx_chip *chip, int port,
>                                      bool message_port);
>  int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chip *chip, int port,
>                                    size_t size);
> +int mv88e6xxx_port_set_default_qpri(struct mv88e6xxx_chip *chip, int port,
> +                                  int qpri);
>  int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
>  int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
> +int mv88e6xxx_port_set_output_queue_schedule(struct mv88e6xxx_chip *chip, int port,
> +                                  u16 schedule);
> +int mv88e6xxx_port_set_egress_rate(struct mv88e6xxx_chip *chip, int port,
> +                                  u16 type, u32 rate);
>  int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
>                                 u8 out);
>  int mv88e6390_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 in,
> --
> 2.23.0
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

Regards,
-Vladimir

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ