Skip to content

Commit 964dbf1

Browse files
Noltaridavem330
authored andcommitted
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: Álvaro Fernández Rojas <noltari@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 73a2218 commit 964dbf1

File tree

3 files changed

+113
-3
lines changed

3 files changed

+113
-3
lines changed

include/net/dsa.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,12 @@ struct phylink_link_state;
4949
#define DSA_TAG_PROTO_XRS700X_VALUE 19
5050
#define DSA_TAG_PROTO_OCELOT_8021Q_VALUE 20
5151
#define DSA_TAG_PROTO_SEVILLE_VALUE 21
52+
#define DSA_TAG_PROTO_BRCM_LEGACY_VALUE 22
5253

5354
enum dsa_tag_protocol {
5455
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
5556
DSA_TAG_PROTO_BRCM = DSA_TAG_PROTO_BRCM_VALUE,
57+
DSA_TAG_PROTO_BRCM_LEGACY = DSA_TAG_PROTO_BRCM_LEGACY_VALUE,
5658
DSA_TAG_PROTO_BRCM_PREPEND = DSA_TAG_PROTO_BRCM_PREPEND_VALUE,
5759
DSA_TAG_PROTO_DSA = DSA_TAG_PROTO_DSA_VALUE,
5860
DSA_TAG_PROTO_EDSA = DSA_TAG_PROTO_EDSA_VALUE,

net/dsa/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ config NET_DSA_TAG_BRCM
4848
Say Y if you want to enable support for tagging frames for the
4949
Broadcom switches which place the tag after the MAC source address.
5050

51+
config NET_DSA_TAG_BRCM_LEGACY
52+
tristate "Tag driver for Broadcom legacy switches using in-frame headers"
53+
select NET_DSA_TAG_BRCM_COMMON
54+
help
55+
Say Y if you want to enable support for tagging frames for the
56+
Broadcom legacy switches which place the tag after the MAC source
57+
address.
5158

5259
config NET_DSA_TAG_BRCM_PREPEND
5360
tristate "Tag driver for Broadcom switches using prepended headers"

net/dsa/tag_brcm.c

Lines changed: 104 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,26 @@
1212

1313
#include "dsa_priv.h"
1414

15-
/* This tag length is 4 bytes, older ones were 6 bytes, we do not
16-
* handle them
17-
*/
15+
/* Legacy Broadcom tag (6 bytes) */
16+
#define BRCM_LEG_TAG_LEN 6
17+
18+
/* Type fields */
19+
/* 1st byte in the tag */
20+
#define BRCM_LEG_TYPE_HI 0x88
21+
/* 2nd byte in the tag */
22+
#define BRCM_LEG_TYPE_LO 0x74
23+
24+
/* Tag fields */
25+
/* 3rd byte in the tag */
26+
#define BRCM_LEG_UNICAST (0 << 5)
27+
#define BRCM_LEG_MULTICAST (1 << 5)
28+
#define BRCM_LEG_EGRESS (2 << 5)
29+
#define BRCM_LEG_INGRESS (3 << 5)
30+
31+
/* 6th byte in the tag */
32+
#define BRCM_LEG_PORT_ID (0xf)
33+
34+
/* Newer Broadcom tag (4 bytes) */
1835
#define BRCM_TAG_LEN 4
1936

2037
/* Tag is constructed and desconstructed using byte by byte access
@@ -195,6 +212,87 @@ DSA_TAG_DRIVER(brcm_netdev_ops);
195212
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM);
196213
#endif
197214

215+
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY)
216+
static struct sk_buff *brcm_leg_tag_xmit(struct sk_buff *skb,
217+
struct net_device *dev)
218+
{
219+
struct dsa_port *dp = dsa_slave_to_port(dev);
220+
u8 *brcm_tag;
221+
222+
/* The Ethernet switch we are interfaced with needs packets to be at
223+
* least 64 bytes (including FCS) otherwise they will be discarded when
224+
* they enter the switch port logic. When Broadcom tags are enabled, we
225+
* need to make sure that packets are at least 70 bytes
226+
* (including FCS and tag) because the length verification is done after
227+
* the Broadcom tag is stripped off the ingress packet.
228+
*
229+
* Let dsa_slave_xmit() free the SKB
230+
*/
231+
if (__skb_put_padto(skb, ETH_ZLEN + BRCM_LEG_TAG_LEN, false))
232+
return NULL;
233+
234+
skb_push(skb, BRCM_LEG_TAG_LEN);
235+
236+
memmove(skb->data, skb->data + BRCM_LEG_TAG_LEN, 2 * ETH_ALEN);
237+
238+
brcm_tag = skb->data + 2 * ETH_ALEN;
239+
240+
/* Broadcom tag type */
241+
brcm_tag[0] = BRCM_LEG_TYPE_HI;
242+
brcm_tag[1] = BRCM_LEG_TYPE_LO;
243+
244+
/* Broadcom tag value */
245+
brcm_tag[2] = BRCM_LEG_EGRESS;
246+
brcm_tag[3] = 0;
247+
brcm_tag[4] = 0;
248+
brcm_tag[5] = dp->index & BRCM_LEG_PORT_ID;
249+
250+
return skb;
251+
}
252+
253+
static struct sk_buff *brcm_leg_tag_rcv(struct sk_buff *skb,
254+
struct net_device *dev,
255+
struct packet_type *pt)
256+
{
257+
int source_port;
258+
u8 *brcm_tag;
259+
260+
if (unlikely(!pskb_may_pull(skb, BRCM_LEG_PORT_ID)))
261+
return NULL;
262+
263+
brcm_tag = skb->data - 2;
264+
265+
source_port = brcm_tag[5] & BRCM_LEG_PORT_ID;
266+
267+
skb->dev = dsa_master_find_slave(dev, 0, source_port);
268+
if (!skb->dev)
269+
return NULL;
270+
271+
/* Remove Broadcom tag and update checksum */
272+
skb_pull_rcsum(skb, BRCM_LEG_TAG_LEN);
273+
274+
skb->offload_fwd_mark = 1;
275+
276+
/* Move the Ethernet DA and SA */
277+
memmove(skb->data - ETH_HLEN,
278+
skb->data - ETH_HLEN - BRCM_LEG_TAG_LEN,
279+
2 * ETH_ALEN);
280+
281+
return skb;
282+
}
283+
284+
static const struct dsa_device_ops brcm_legacy_netdev_ops = {
285+
.name = "brcm-legacy",
286+
.proto = DSA_TAG_PROTO_BRCM_LEGACY,
287+
.xmit = brcm_leg_tag_xmit,
288+
.rcv = brcm_leg_tag_rcv,
289+
.overhead = BRCM_LEG_TAG_LEN,
290+
};
291+
292+
DSA_TAG_DRIVER(brcm_legacy_netdev_ops);
293+
MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_BRCM_LEGACY);
294+
#endif /* CONFIG_NET_DSA_TAG_BRCM_LEGACY */
295+
198296
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND)
199297
static struct sk_buff *brcm_tag_xmit_prepend(struct sk_buff *skb,
200298
struct net_device *dev)
@@ -227,6 +325,9 @@ static struct dsa_tag_driver *dsa_tag_driver_array[] = {
227325
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM)
228326
&DSA_TAG_DRIVER_NAME(brcm_netdev_ops),
229327
#endif
328+
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_LEGACY)
329+
&DSA_TAG_DRIVER_NAME(brcm_legacy_netdev_ops),
330+
#endif
230331
#if IS_ENABLED(CONFIG_NET_DSA_TAG_BRCM_PREPEND)
231332
&DSA_TAG_DRIVER_NAME(brcm_prepend_netdev_ops),
232333
#endif

0 commit comments

Comments
 (0)