Commit 964dbf18 authored by Álvaro Fernández Rojas's avatar Álvaro Fernández Rojas Committed by David S. Miller

net: dsa: tag_brcm: add support for legacy tags

Add support for legacy Broadcom tags, which are similar to DSA_TAG_PROTO_BRCM.
These tags are used on BCM5325, BCM5365 and BCM63xx switches.
Signed-off-by: default avatarÁlvaro Fernández Rojas <noltari@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 73a2218c
...@@ -49,10 +49,12 @@ struct phylink_link_state; ...@@ -49,10 +49,12 @@ struct phylink_link_state;
#define DSA_TAG_PROTO_XRS700X_VALUE 19 #define DSA_TAG_PROTO_XRS700X_VALUE 19
#define DSA_TAG_PROTO_OCELOT_8021Q_VALUE 20 #define DSA_TAG_PROTO_OCELOT_8021Q_VALUE 20
#define DSA_TAG_PROTO_SEVILLE_VALUE 21 #define DSA_TAG_PROTO_SEVILLE_VALUE 21
#define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22
enum dsa_tag_protocol { enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE, DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE, DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE,
DSA_TAG_PROTO_BRCM_LEGACY = DSA_TAG_PROTO_BRCM_LEGACY_VALUE,
DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE, DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE,
DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE, DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE,
DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE, DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE,
......
...@@ -48,6 +48,13 @@ config NET_DSA_TAG_BRCM ...@@ -48,6 +48,13 @@ config NET_DSA_TAG_BRCM
Say Y if you want to enable support for tagging frames for the Say Y if you want to enable support for tagging frames for the
Broadcom switches which place the tag after the MAC source address. Broadcom switches which place the tag after the MAC source address.
config NET_DSA_TAG_BRCM_LEGACY
tristate "Tag driver for Broadcom legacy switches using in-frame headers"
select NET_DSA_TAG_BRCM_COMMON
help
Say Y if you want to enable support for tagging frames for the
Broadcom legacy switches which place the tag after the MAC source
address.
config NET_DSA_TAG_BRCM_PREPEND config NET_DSA_TAG_BRCM_PREPEND
tristate "Tag driver for Broadcom switches using prepended headers" tristate "Tag driver for Broadcom switches using prepended headers"
......
...@@ -12,9 +12,26 @@ ...@@ -12,9 +12,26 @@
#include "dsa_priv.h" #include "dsa_priv.h"
/* This tag length is 4 bytes, older ones were 6 bytes, we do not /* Legacy Broadcom tag (6 bytes) */
* handle them #define BRCM_LEG_TAG_LEN 6
*/
/* Type fields */
/* 1st byte in the tag */
#define BRCM_LEG_TYPE_HI 0x88
/* 2nd byte in the tag */
#define BRCM_LEG_TYPE_LO 0x74
/* Tag fields */
/* 3rd byte in the tag */
#define BRCM_LEG_UNICAST (0 << 5)
#define BRCM_LEG_MULTICAST (1 << 5)
#define BRCM_LEG_EGRESS (2 << 5)
#define BRCM_LEG_INGRESS (3 << 5)
/* 6th byte in the tag */
#define BRCM_LEG_PORT_ID (0xf)
/* Newer Broadcom tag (4 bytes) */
#define BRCM_TAG_LEN 4 #define BRCM_TAG_LEN 4
/* Tag is constructed and desconstructed using byte by byte access /* Tag is constructed and desconstructed using byte by byte access
...@@ -195,6 +212,87 @@ DSA_TAG_DRIVER(brcm_netdev_ops); ...@@ -195,6 +212,87 @@ DSA_TAG_DRIVER(brcm_netdev_ops);
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM); MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM);
#endif #endif
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY)
static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct dsa_port *dp = dsa_slave_to_port(dev);
u8 *brcm_tag;
/* The Ethernet switch we are interfaced with needs packets to be at
* least 64 bytes (including FCS) otherwise they will be discarded when
* they enter the switch port logic. When Broadcom tags are enabled, we
* need to make sure that packets are at least 70 bytes
* (including FCS and tag) because the length verification is done after
* the Broadcom tag is stripped off the ingress packet.
*
* Let dsa_slave_xmit() free the SKB
*/
if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false))
return NULL;
skb_push(skb, BRCM_LEG_TAG_LEN);
memmove(skb->data, skb->data + BRCM_LEG_TAG_LEN, 2 * ETH_ALEN);
brcm_tag = skb->data + 2 * ETH_ALEN;
/* Broadcom tag type */
brcm_tag[0] = BRCM_LEG_TYPE_HI;
brcm_tag[1] = BRCM_LEG_TYPE_LO;
/* Broadcom tag value */
brcm_tag[2] = BRCM_LEG_EGRESS;
brcm_tag[3] = 0;
brcm_tag[4] = 0;
brcm_tag[5] = dp->index & BRCM_LEG_PORT_ID;
return skb;
}
static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt)
{
int source_port;
u8 *brcm_tag;
if (unlikely(!pskb_may_pull(skb, BRCM_LEG_PORT_ID)))
return NULL;
brcm_tag = skb->data - 2;
source_port = brcm_tag[5] & BRCM_LEG_PORT_ID;
skb->dev = dsa_master_find_slave(dev, 0, source_port);
if (!skb->dev)
return NULL;
/* Remove Broadcom tag and update checksum */
skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN);
skb->offload_fwd_mark = 1;
/* Move the Ethernet DA and SA */
memmove(skb->data - ETH_HLEN,
skb->data - ETH_HLEN - BRCM_LEG_TAG_LEN,
2 * ETH_ALEN);
return skb;
}
static const struct dsa_device_ops brcm_legacy_netdev_ops = {
.name = "brcm-legacy",
.proto = DSA_TAG_PROTO_BRCM_LEGACY,
.xmit = brcm_leg_tag_xmit,
.rcv = brcm_leg_tag_rcv,
.overhead = BRCM_LEG_TAG_LEN,
};
DSA_TAG_DRIVER(brcm_legacy_netdev_ops);
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY);
#endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY */
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND)
static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb, static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb,
struct net_device *dev) struct net_device *dev)
...@@ -227,6 +325,9 @@ static struct dsa_tag_driver *dsa_tag_driver_array[] = { ...@@ -227,6 +325,9 @@ static struct dsa_tag_driver *dsa_tag_driver_array[] = {
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM) #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM)
&DSA_TAG_DRIVER_NAME(brcm_netdev_ops), &DSA_TAG_DRIVER_NAME(brcm_netdev_ops),
#endif #endif
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY)
&DSA_TAG_DRIVER_NAME(brcm_legacy_netdev_ops),
#endif
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND) #if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND)
&DSA_TAG_DRIVER_NAME(brcm_prepend_netdev_ops), &DSA_TAG_DRIVER_NAME(brcm_prepend_netdev_ops),
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment