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:   Mon, 4 May 2020 20:47:29 +0800
From:   DENG Qingfang <dqfext@...il.com>
To:     Vladimir Oltean <olteanv@...il.com>
Cc:     netdev <netdev@...r.kernel.org>,
        Sean Wang <sean.wang@...iatek.com>,
        Andrew Lunn <andrew@...n.ch>,
        Vivien Didelot <vivien.didelot@...il.com>,
        Florian Fainelli <f.fainelli@...il.com>,
        "David S . Miller" <davem@...emloft.net>,
        "moderated list:ARM/Mediatek SoC support" 
        <linux-mediatek@...ts.infradead.org>,
        Russell King <linux@...linux.org.uk>,
        Matthias Brugger <matthias.bgg@...il.com>,
        René van Dorst <opensource@...rst.com>,
        Tom James <tj17@...com>,
        Stijn Segers <foss@...atilesystems.org>,
        riddlariddla@...mail.com, Szabolcs Hubai <szab.hu@...il.com>,
        Paul Fertser <fercerpav@...il.com>
Subject: Re: [RFC PATCH net-next] net: dsa: mt7530: fix roaming from DSA user ports

Hi Vladimir,

On Mon, May 4, 2020 at 6:23 PM Vladimir Oltean <olteanv@...il.com> wrote:
>
> Hi Qingfang,
>
> On Sat, 25 Apr 2020 at 15:03, DENG Qingfang <dqfext@...il.com> wrote:
> >
> > When a client moves from a DSA user port to a software port in a bridge,
> > it cannot reach any other clients that connected to the DSA user ports.
> > That is because SA learning on the CPU port is disabled, so the switch
> > ignores the client's frames from the CPU port and still thinks it is at
> > the user port.
> >
> > Fix it by enabling SA learning on the CPU port.
> >
> > To prevent the switch from learning from flooding frames from the CPU
> > port, set skb->offload_fwd_mark to 1 for unicast and broadcast frames,
> > and let the switch flood them instead of trapping to the CPU port.
> > Multicast frames still need to be trapped to the CPU port for snooping,
> > so set the SA_DIS bit of the MTK tag to 1 when transmitting those frames
> > to disable SA learning.
> >
> > Fixes: b8f126a8d543 ("net-next: dsa: add dsa support for Mediatek MT7530 switch")
> > Signed-off-by: DENG Qingfang <dqfext@...il.com>
> > ---
>
> I think enabling learning on the CPU port would fix the problem
> sometimes, but not always. (actually nothing can solve it always, see
> below)
> The switch learns the new route only if it receives any packets from
> the CPU port, with a SA equal to the station you're trying to reach.
> But what if the station is not sending any traffic at the moment,
> because it is simply waiting for connections to it first (just an
> example)?
> Unless there is any traffic already coming from the destination
> station too, your patch won't work.
> I am currently facing a similar situation with the ocelot/felix
> switches, but in that case, enabling SA learning on the CPU port is
> not possible.

Why is it not possible?

Then try my previous RFC patch
"net: bridge: fix client roaming from DSA user port"
It tries removing entries from the switch when the client moves to another port.

> The way I dealt with it is by forcing a flush of the FDB entries on
> the port, in the following scenarios:
> - link goes down
> - port leaves its bridge
> So traffic towards a destination that has migrated away will
> temporarily be flooded again (towards the CPU port as well).
> There is still one case which isn't treated using this approach: when
> the station migrates away from a switch port that is not directly
> connected to this one. So no "link down" events would get generated in
> that case. We would still have to wait until the address expires in
> that case. I don't think that particular situation can be solved.

You're right. Every switch has this issue, even Linux bridge.

> My point is: if we agree that this is a larger problem, then DSA
> should have a .port_fdb_flush method and schedule a workqueue whenever
> necessary. Yes, it is a costly operation, but it will still probably
> take a lot less than the 300 seconds that the bridge configures for
> address ageing.
>
> Thoughts?
>
> >  drivers/net/dsa/mt7530.c |  9 ++-------
> >  drivers/net/dsa/mt7530.h |  1 +
> >  net/dsa/tag_mtk.c        | 15 +++++++++++++++
> >  3 files changed, 18 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
> > index 5c444cd722bd..34e4aadfa705 100644
> > --- a/drivers/net/dsa/mt7530.c
> > +++ b/drivers/net/dsa/mt7530.c
> > @@ -628,11 +628,8 @@ mt7530_cpu_port_enable(struct mt7530_priv *priv,
> >         mt7530_write(priv, MT7530_PVC_P(port),
> >                      PORT_SPEC_TAG);
> >
> > -       /* Disable auto learning on the cpu port */
> > -       mt7530_set(priv, MT7530_PSC_P(port), SA_DIS);
> > -
> > -       /* Unknown unicast frame fordwarding to the cpu port */
> > -       mt7530_set(priv, MT7530_MFC, UNU_FFP(BIT(port)));
> > +       /* Unknown multicast frame forwarding to the cpu port */
> > +       mt7530_rmw(priv, MT7530_MFC, UNM_FFP_MASK, UNM_FFP(BIT(port)));
> >
> >         /* Set CPU port number */
> >         if (priv->id == ID_MT7621)
> > @@ -1294,8 +1291,6 @@ mt7530_setup(struct dsa_switch *ds)
> >         /* Enable and reset MIB counters */
> >         mt7530_mib_reset(ds);
> >
> > -       mt7530_clear(priv, MT7530_MFC, UNU_FFP_MASK);
> > -
> >         for (i = 0; i < MT7530_NUM_PORTS; i++) {
> >                 /* Disable forwarding by default on all ports */
> >                 mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
> > diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
> > index 979bb6374678..82af4d2d406e 100644
> > --- a/drivers/net/dsa/mt7530.h
> > +++ b/drivers/net/dsa/mt7530.h
> > @@ -31,6 +31,7 @@ enum {
> >  #define MT7530_MFC                     0x10
> >  #define  BC_FFP(x)                     (((x) & 0xff) << 24)
> >  #define  UNM_FFP(x)                    (((x) & 0xff) << 16)
> > +#define  UNM_FFP_MASK                  UNM_FFP(~0)
> >  #define  UNU_FFP(x)                    (((x) & 0xff) << 8)
> >  #define  UNU_FFP_MASK                  UNU_FFP(~0)
> >  #define  CPU_EN                                BIT(7)
> > diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
> > index b5705cba8318..d6619edd53e5 100644
> > --- a/net/dsa/tag_mtk.c
> > +++ b/net/dsa/tag_mtk.c
> > @@ -15,6 +15,7 @@
> >  #define MTK_HDR_XMIT_TAGGED_TPID_8100  1
> >  #define MTK_HDR_RECV_SOURCE_PORT_MASK  GENMASK(2, 0)
> >  #define MTK_HDR_XMIT_DP_BIT_MASK       GENMASK(5, 0)
> > +#define MTK_HDR_XMIT_SA_DIS            BIT(6)
> >
> >  static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
> >                                     struct net_device *dev)
> > @@ -22,6 +23,9 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
> >         struct dsa_port *dp = dsa_slave_to_port(dev);
> >         u8 *mtk_tag;
> >         bool is_vlan_skb = true;
> > +       unsigned char *dest = eth_hdr(skb)->h_dest;
> > +       bool is_multicast_skb = is_multicast_ether_addr(dest) &&
> > +                               !is_broadcast_ether_addr(dest);
> >
> >         /* Build the special tag after the MAC Source Address. If VLAN header
> >          * is present, it's required that VLAN header and special tag is
> > @@ -47,6 +51,10 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
> >                      MTK_HDR_XMIT_UNTAGGED;
> >         mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
> >
> > +       /* Disable SA learning for multicast frames */
> > +       if (unlikely(is_multicast_skb))
> > +               mtk_tag[1] |= MTK_HDR_XMIT_SA_DIS;
> > +
> >         /* Tag control information is kept for 802.1Q */
> >         if (!is_vlan_skb) {
> >                 mtk_tag[2] = 0;
> > @@ -61,6 +69,9 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
> >  {
> >         int port;
> >         __be16 *phdr, hdr;
> > +       unsigned char *dest = eth_hdr(skb)->h_dest;
> > +       bool is_multicast_skb = is_multicast_ether_addr(dest) &&
> > +                               !is_broadcast_ether_addr(dest);
> >
> >         if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
> >                 return NULL;
> > @@ -86,6 +97,10 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
> >         if (!skb->dev)
> >                 return NULL;
> >
> > +       /* Only unicast or broadcast frames are offloaded */
> > +       if (likely(!is_multicast_skb))
> > +               skb->offload_fwd_mark = 1;
> > +
> >         return skb;
> >  }
> >
> > --
> > 2.26.1
> >
>
> Thanks,
> -Vladimir

Powered by blists - more mailing lists