[PATCH net-next v2] net: dsa: Mock-up driver
This patch adds support for a DSA mock-up driver which essentially does the following: - registers/unregisters 4 fixed PHYs to the slave network devices - uses eth0 (configurable) as the master netdev - registers the switch as a fixed MDIO device against the fixed MDIO bus at address 31 - includes dynamic debug prints for dsa_switch_ops functions that can be enabled to get call traces This is a good way to test modular builds as well as exercise the DSA APIs without requiring access to real hardware. This does not test the data-path, although this could be added later on. Signed-off-by: Florian Fainelli --- Changes in v2; - removed an unnecessary change to include/linux/fixed_phy.h drivers/net/dsa/Kconfig | 8 + drivers/net/dsa/Makefile | 2 +- drivers/net/dsa/dsa_loop.c| 329 ++ drivers/net/dsa/dsa_loop.h| 19 +++ drivers/net/dsa/dsa_loop_bdinfo.c | 34 5 files changed, 391 insertions(+), 1 deletion(-) create mode 100644 drivers/net/dsa/dsa_loop.c create mode 100644 drivers/net/dsa/dsa_loop.h create mode 100644 drivers/net/dsa/dsa_loop_bdinfo.c diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig index 564b267c8428..ba2e655eec19 100644 --- a/drivers/net/dsa/Kconfig +++ b/drivers/net/dsa/Kconfig @@ -34,4 +34,12 @@ config NET_DSA_QCA8K This enables support for the Qualcomm Atheros QCA8K Ethernet switch chips. +config NET_DSA_LOOP + tristate "DSA mock-up Ethernet switch chip support" + depends on NET_DSA + select FIXED_PHY + ---help--- + This enables support for a fake mock-up switch chip which + exercises the DSA APIs. + endmenu diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile index a3c941632217..5c8830991041 100644 --- a/drivers/net/dsa/Makefile +++ b/drivers/net/dsa/Makefile @@ -2,6 +2,6 @@ obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o obj-$(CONFIG_NET_DSA_BCM_SF2) += bcm-sf2.o bcm-sf2-objs := bcm_sf2.o bcm_sf2_cfp.o obj-$(CONFIG_NET_DSA_QCA8K)+= qca8k.o - obj-y += b53/ obj-y += mv88e6xxx/ +obj-$(CONFIG_NET_DSA_LOOP) += dsa_loop.o dsa_loop_bdinfo.o diff --git a/drivers/net/dsa/dsa_loop.c b/drivers/net/dsa/dsa_loop.c new file mode 100644 index ..0a9a2f846efd --- /dev/null +++ b/drivers/net/dsa/dsa_loop.c @@ -0,0 +1,329 @@ +/* + * Distributed Switch Architecture loopback driver + * + * Copyright (C) 2016, Florian Fainelli + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dsa_loop.h" + +struct dsa_loop_vlan { + u16 members; + u16 untagged; +}; + +#define DSA_LOOP_VLANS 5 + +struct dsa_loop_priv { + struct mii_bus *bus; + unsigned intport_base; + struct dsa_loop_vlan vlans[DSA_LOOP_VLANS]; + struct net_device *netdev; + u16 pvid; +}; + +static struct phy_device *phydevs[PHY_MAX_ADDR]; + +static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds) +{ + dev_dbg(ds->dev, "%s\n", __func__); + + return DSA_TAG_PROTO_NONE; +} + +static int dsa_loop_setup(struct dsa_switch *ds) +{ + dev_dbg(ds->dev, "%s\n", __func__); + + return 0; +} + +static int dsa_loop_set_addr(struct dsa_switch *ds, u8 *addr) +{ + dev_dbg(ds->dev, "%s\n", __func__); + + return 0; +} + +static int dsa_loop_phy_read(struct dsa_switch *ds, int port, int regnum) +{ + struct dsa_loop_priv *ps = ds->priv; + struct mii_bus *bus = ps->bus; + + dev_dbg(ds->dev, "%s\n", __func__); + + return mdiobus_read_nested(bus, ps->port_base + port, regnum); +} + +static int dsa_loop_phy_write(struct dsa_switch *ds, int port, + int regnum, u16 value) +{ + struct dsa_loop_priv *ps = ds->priv; + struct mii_bus *bus = ps->bus; + + dev_dbg(ds->dev, "%s\n", __func__); + + return mdiobus_write_nested(bus, ps->port_base + port, regnum, value); +} + +static int dsa_loop_port_bridge_join(struct dsa_switch *ds, int port, +struct net_device *bridge) +{ + dev_dbg(ds->dev, "%s\n", __func__); + + return 0; +} + +static void dsa_loop_port_bridge_leave(struct dsa_switch *ds, int port, + struct net_device *bridge) +{ + dev_dbg(ds->dev, "%s\n", __func__); +} + +static void dsa_loop_port_stp_state_set(struct dsa_switch *ds, int port, + u8 state) +{ + dev_dbg(ds->dev, "%s\n", __func__); +} + +static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port, +
Re: [PATCH net-next v2] net: dsa: Mock-up driver
Hi Florian > +static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds) > +{ > + dev_dbg(ds->dev, "%s\n", __func__); > + > + return DSA_TAG_PROTO_NONE; > +} I'm wondering how safe this is: static const struct dsa_device_ops none_ops = { .xmit = dsa_slave_notag_xmit, .rcv= NULL, }; /* * If the CPU connects to this switch, set the switch tree * tagging protocol to the preferred tagging format of this * switch. */ if (dst->cpu_switch == ds) { enum dsa_tag_protocol tag_protocol; tag_protocol = ops->get_tag_protocol(ds); dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol); if (IS_ERR(dst->tag_ops)) return PTR_ERR(dst->tag_ops); dst->rcv = dst->tag_ops->rcv; } static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { struct dsa_switch_tree *dst = dev->dsa_ptr; if (unlikely(dst == NULL)) { kfree_skb(skb); return 0; } return dst->rcv(skb, dev, pt, orig_dev); } static struct packet_type dsa_pack_type __read_mostly = { .type = cpu_to_be16(ETH_P_XDSA), .func = dsa_switch_rcv, }; It looks like when a frame is received, we are going to dereference a NULL pointer. Either we need a NOP rcv function, or we don't register dsa_pack_type if rcv is NULL. Andrew
Re: [PATCH net-next v2] net: dsa: Mock-up driver
Hi Andrew, On 03/31/2017 09:06 AM, Andrew Lunn wrote: > Hi Florian > >> +static enum dsa_tag_protocol dsa_loop_get_protocol(struct dsa_switch *ds) >> +{ >> +dev_dbg(ds->dev, "%s\n", __func__); >> + >> +return DSA_TAG_PROTO_NONE; >> +} > > I'm wondering how safe this is: > > static const struct dsa_device_ops none_ops = { > .xmit = dsa_slave_notag_xmit, > .rcv= NULL, > }; > > /* > * If the CPU connects to this switch, set the switch tree > * tagging protocol to the preferred tagging format of this > * switch. > */ > if (dst->cpu_switch == ds) { > enum dsa_tag_protocol tag_protocol; > > tag_protocol = ops->get_tag_protocol(ds); > dst->tag_ops = dsa_resolve_tag_protocol(tag_protocol); > if (IS_ERR(dst->tag_ops)) > return PTR_ERR(dst->tag_ops); > > dst->rcv = dst->tag_ops->rcv; > } > > > static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, > struct packet_type *pt, struct net_device *orig_dev) > { > struct dsa_switch_tree *dst = dev->dsa_ptr; > > if (unlikely(dst == NULL)) { > kfree_skb(skb); > return 0; > } > > return dst->rcv(skb, dev, pt, orig_dev); > } > > static struct packet_type dsa_pack_type __read_mostly = { > .type = cpu_to_be16(ETH_P_XDSA), > .func = dsa_switch_rcv, > }; > > It looks like when a frame is received, we are going to dereference a > NULL pointer. Actually we do not, because netdev_uses_dsa() returns true only when dst->rcv is different from NULL. When dst->rcv is NULL we completely bypass the DSA hook in eth_type_trans() and everything is well, the master network device is the one receiving packets. This is actually the intended behavior for netdev_uses_dsa() because it really tells whether there is a DSA tagging protocol set-up and that is what NIC drivers (e.g: bcmsysport) would care about. Thanks! -- Florian
Re: [PATCH net-next v2] net: dsa: Mock-up driver
> Actually we do not, because netdev_uses_dsa() returns true only when > dst->rcv is different from NULL. When dst->rcv is NULL we completely > bypass the DSA hook in eth_type_trans() and everything is well, the > master network device is the one receiving packets. static inline bool netdev_uses_dsa(struct net_device *dev) { #if IS_ENABLED(CONFIG_NET_DSA) if (dev->dsa_ptr != NULL) return dsa_uses_tagged_protocol(dev->dsa_ptr); #endif return false; } and static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst) { return dst->rcv != NULL; } Yep, i just needed to dig further... Thanks Andrew
Re: [PATCH net-next v2] net: dsa: Mock-up driver
From: Florian Fainelli Date: Thu, 30 Mar 2017 18:43:21 -0700 > This patch adds support for a DSA mock-up driver which essentially does > the following: > > - registers/unregisters 4 fixed PHYs to the slave network devices > - uses eth0 (configurable) as the master netdev > - registers the switch as a fixed MDIO device against the fixed MDIO bus > at address 31 > - includes dynamic debug prints for dsa_switch_ops functions that can be > enabled to get call traces > > This is a good way to test modular builds as well as exercise the DSA > APIs without requiring access to real hardware. This does not test the > data-path, although this could be added later on. > > Signed-off-by: Florian Fainelli > --- > Changes in v2; > > - removed an unnecessary change to include/linux/fixed_phy.h This looks extremely useful, applied, thanks!