net: dsa: add master helper to look up slaves

The DSA tagging code does not need to know about the DSA architecture,
it only needs to return the slave device corresponding to the source
port index (and eventually the source device index for cascade-capable
switches) parsed from the frame received on the master device.

For this purpose, provide an inline dsa_master_get_slave helper which
validates the device and port indexes and look up the slave device.

This makes the tagging rcv functions more concise and robust, and also
makes dsa_get_cpu_port obsolete.

Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Vivien Didelot 2017-09-29 17:19:15 -04:00 committed by David S. Miller
parent 075cfdd659
commit 3775b1b7f0
9 changed files with 39 additions and 101 deletions

View File

@ -113,6 +113,25 @@ int dsa_legacy_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
int dsa_master_ethtool_setup(struct net_device *dev); int dsa_master_ethtool_setup(struct net_device *dev);
void dsa_master_ethtool_restore(struct net_device *dev); void dsa_master_ethtool_restore(struct net_device *dev);
static inline struct net_device *dsa_master_get_slave(struct net_device *dev,
int device, int port)
{
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_switch *ds;
if (device < 0 || device >= DSA_MAX_SWITCHES)
return NULL;
ds = dst->ds[device];
if (!ds)
return NULL;
if (port < 0 || port >= ds->num_ports)
return NULL;
return ds->ports[port].netdev;
}
/* port.c */ /* port.c */
int dsa_port_set_state(struct dsa_port *dp, u8 state, int dsa_port_set_state(struct dsa_port *dp, u8 state,
struct switchdev_trans *trans); struct switchdev_trans *trans);
@ -182,9 +201,4 @@ static inline struct net_device *dsa_master_netdev(struct dsa_slave_priv *p)
return p->dp->cpu_dp->netdev; return p->dp->cpu_dp->netdev;
} }
static inline struct dsa_port *dsa_get_cpu_port(struct dsa_switch_tree *dst)
{
return dst->cpu_dp;
}
#endif #endif

View File

@ -92,9 +92,6 @@ static struct sk_buff *brcm_tag_xmit(struct sk_buff *skb, struct net_device *dev
static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev, static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
struct dsa_switch *ds = cpu_dp->ds;
int source_port; int source_port;
u8 *brcm_tag; u8 *brcm_tag;
@ -117,8 +114,8 @@ static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
/* Locate which port this is coming from */ /* Locate which port this is coming from */
source_port = brcm_tag[3] & BRCM_EG_PID_MASK; source_port = brcm_tag[3] & BRCM_EG_PID_MASK;
/* Validate port against switch setup, either the port is totally */ skb->dev = dsa_master_get_slave(dev, 0, source_port);
if (source_port >= ds->num_ports || !ds->ports[source_port].netdev) if (!skb->dev)
return NULL; return NULL;
/* Remove Broadcom tag and update checksum */ /* Remove Broadcom tag and update checksum */
@ -129,8 +126,6 @@ static struct sk_buff *brcm_tag_rcv(struct sk_buff *skb, struct net_device *dev,
skb->data - ETH_HLEN - BRCM_TAG_LEN, skb->data - ETH_HLEN - BRCM_TAG_LEN,
2 * ETH_ALEN); 2 * ETH_ALEN);
skb->dev = ds->ports[source_port].netdev;
return skb; return skb;
} }

View File

@ -67,8 +67,6 @@ static struct sk_buff *dsa_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev, static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_switch *ds;
u8 *dsa_header; u8 *dsa_header;
int source_device; int source_device;
int source_port; int source_port;
@ -93,18 +91,8 @@ static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev,
source_device = dsa_header[0] & 0x1f; source_device = dsa_header[0] & 0x1f;
source_port = (dsa_header[1] >> 3) & 0x1f; source_port = (dsa_header[1] >> 3) & 0x1f;
/* skb->dev = dsa_master_get_slave(dev, source_device, source_port);
* Check that the source device exists and that the source if (!skb->dev)
* port is a registered DSA port.
*/
if (source_device >= DSA_MAX_SWITCHES)
return NULL;
ds = dst->ds[source_device];
if (!ds)
return NULL;
if (source_port >= ds->num_ports || !ds->ports[source_port].netdev)
return NULL; return NULL;
/* /*
@ -153,8 +141,6 @@ static struct sk_buff *dsa_rcv(struct sk_buff *skb, struct net_device *dev,
2 * ETH_ALEN); 2 * ETH_ALEN);
} }
skb->dev = ds->ports[source_port].netdev;
return skb; return skb;
} }

View File

@ -80,8 +80,6 @@ static struct sk_buff *edsa_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev, static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_switch *ds;
u8 *edsa_header; u8 *edsa_header;
int source_device; int source_device;
int source_port; int source_port;
@ -106,18 +104,8 @@ static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
source_device = edsa_header[0] & 0x1f; source_device = edsa_header[0] & 0x1f;
source_port = (edsa_header[1] >> 3) & 0x1f; source_port = (edsa_header[1] >> 3) & 0x1f;
/* skb->dev = dsa_master_get_slave(dev, source_device, source_port);
* Check that the source device exists and that the source if (!skb->dev)
* port is a registered DSA port.
*/
if (source_device >= DSA_MAX_SWITCHES)
return NULL;
ds = dst->ds[source_device];
if (!ds)
return NULL;
if (source_port >= ds->num_ports || !ds->ports[source_port].netdev)
return NULL; return NULL;
/* /*
@ -172,8 +160,6 @@ static struct sk_buff *edsa_rcv(struct sk_buff *skb, struct net_device *dev,
2 * ETH_ALEN); 2 * ETH_ALEN);
} }
skb->dev = ds->ports[source_port].netdev;
return skb; return skb;
} }

View File

@ -80,22 +80,19 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev, static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
struct dsa_switch *ds = cpu_dp->ds;
u8 *tag; u8 *tag;
int source_port; int source_port;
tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN; tag = skb_tail_pointer(skb) - KSZ_EGRESS_TAG_LEN;
source_port = tag[0] & 7; source_port = tag[0] & 7;
if (source_port >= ds->num_ports || !ds->ports[source_port].netdev)
skb->dev = dsa_master_get_slave(dev, 0, source_port);
if (!skb->dev)
return NULL; return NULL;
pskb_trim_rcsum(skb, skb->len - KSZ_EGRESS_TAG_LEN); pskb_trim_rcsum(skb, skb->len - KSZ_EGRESS_TAG_LEN);
skb->dev = ds->ports[source_port].netdev;
return skb; return skb;
} }

View File

@ -71,17 +71,8 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
u16 *lan9303_tag; u16 *lan9303_tag;
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_switch *ds;
unsigned int source_port; unsigned int source_port;
ds = dst->ds[0];
if (unlikely(!ds)) {
dev_warn_ratelimited(&dev->dev, "Dropping packet, due to missing DSA switch device\n");
return NULL;
}
if (unlikely(!pskb_may_pull(skb, LAN9303_TAG_LEN))) { if (unlikely(!pskb_may_pull(skb, LAN9303_TAG_LEN))) {
dev_warn_ratelimited(&dev->dev, dev_warn_ratelimited(&dev->dev,
"Dropping packet, cannot pull\n"); "Dropping packet, cannot pull\n");
@ -103,16 +94,12 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
source_port = ntohs(lan9303_tag[1]) & 0x3; source_port = ntohs(lan9303_tag[1]) & 0x3;
if (source_port >= ds->num_ports) { skb->dev = dsa_master_get_slave(dev, 0, source_port);
if (!skb->dev) {
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid source port\n"); dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid source port\n");
return NULL; return NULL;
} }
if (!ds->ports[source_port].netdev) {
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid netdev or device\n");
return NULL;
}
/* remove the special VLAN tag between the MAC addresses /* remove the special VLAN tag between the MAC addresses
* and the current ethertype field. * and the current ethertype field.
*/ */
@ -120,9 +107,6 @@ static struct sk_buff *lan9303_rcv(struct sk_buff *skb, struct net_device *dev,
memmove(skb->data - ETH_HLEN, skb->data - (ETH_HLEN + LAN9303_TAG_LEN), memmove(skb->data - ETH_HLEN, skb->data - (ETH_HLEN + LAN9303_TAG_LEN),
2 * ETH_ALEN); 2 * ETH_ALEN);
/* forward the packet to the dedicated interface */
skb->dev = ds->ports[source_port].netdev;
return skb; return skb;
} }

View File

@ -46,8 +46,6 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev, static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_switch *ds;
int port; int port;
__be16 *phdr, hdr; __be16 *phdr, hdr;
@ -68,20 +66,12 @@ static struct sk_buff *mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
skb->data - ETH_HLEN - MTK_HDR_LEN, skb->data - ETH_HLEN - MTK_HDR_LEN,
2 * ETH_ALEN); 2 * ETH_ALEN);
/* This protocol doesn't support cascading multiple
* switches so it's safe to assume the switch is first
* in the tree.
*/
ds = dst->ds[0];
if (!ds)
return NULL;
/* Get source port information */ /* Get source port information */
port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK); port = (hdr & MTK_HDR_RECV_SOURCE_PORT_MASK);
if (!ds->ports[port].netdev)
return NULL;
skb->dev = ds->ports[port].netdev; skb->dev = dsa_master_get_slave(dev, 0, port);
if (!skb->dev)
return NULL;
return skb; return skb;
} }

View File

@ -65,9 +65,6 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev, static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
struct dsa_switch *ds;
u8 ver; u8 ver;
int port; int port;
__be16 *phdr, hdr; __be16 *phdr, hdr;
@ -92,20 +89,12 @@ static struct sk_buff *qca_tag_rcv(struct sk_buff *skb, struct net_device *dev,
memmove(skb->data - ETH_HLEN, skb->data - ETH_HLEN - QCA_HDR_LEN, memmove(skb->data - ETH_HLEN, skb->data - ETH_HLEN - QCA_HDR_LEN,
ETH_HLEN - QCA_HDR_LEN); ETH_HLEN - QCA_HDR_LEN);
/* This protocol doesn't support cascading multiple switches so it's
* safe to assume the switch is first in the tree
*/
ds = cpu_dp->ds;
if (!ds)
return NULL;
/* Get source port information */ /* Get source port information */
port = (hdr & QCA_HDR_RECV_SOURCE_PORT_MASK); port = (hdr & QCA_HDR_RECV_SOURCE_PORT_MASK);
if (!ds->ports[port].netdev)
return NULL;
/* Update skb & forward the frame accordingly */ skb->dev = dsa_master_get_slave(dev, 0, port);
skb->dev = ds->ports[port].netdev; if (!skb->dev)
return NULL;
return skb; return skb;
} }

View File

@ -58,9 +58,6 @@ static struct sk_buff *trailer_xmit(struct sk_buff *skb, struct net_device *dev)
static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev, static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
struct dsa_switch_tree *dst = dev->dsa_ptr;
struct dsa_port *cpu_dp = dsa_get_cpu_port(dst);
struct dsa_switch *ds = cpu_dp->ds;
u8 *trailer; u8 *trailer;
int source_port; int source_port;
@ -73,13 +70,13 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev,
return NULL; return NULL;
source_port = trailer[1] & 7; source_port = trailer[1] & 7;
if (source_port >= ds->num_ports || !ds->ports[source_port].netdev)
skb->dev = dsa_master_get_slave(dev, 0, source_port);
if (!skb->dev)
return NULL; return NULL;
pskb_trim_rcsum(skb, skb->len - 4); pskb_trim_rcsum(skb, skb->len - 4);
skb->dev = ds->ports[source_port].netdev;
return skb; return skb;
} }