Skip to content

Commit 8aa1053

Browse files
committed
Merge branch 'introduce-the-dsa_xmit_port_mask-tagging-protocol-helper'
Vladimir Oltean says: ==================== Introduce the dsa_xmit_port_mask() tagging protocol helper What ---- Some DSA tags have just the port number in the TX header format, others have a bit field where in theory, multiple bits can be set, even though DSA only sets one. The latter kind is now making use of a dsa_xmit_port_mask() helper, which will decide when to set more than 1 bit in that mask. Why --- David Yang has pointed out in a recently posted patch that HSR packet duplication on transmission can be offloaded even on HSR-unaware switches. This should be made generally available to all DSA switches. How to test ----------- These patches just lay the groundwork, and there should be no functional change - so for this set, regression testing is all that's necessary. For testing the HSR packet duplication idea, I've put together a branch: https://github.com/vladimiroltean/linux/commits/dsa-simple-hsr-offload/ where most drivers are patched to call dsa_port_simple_hsr_join() and dsa_port_simple_hsr_leave(). Assuming there are volunteers to also test the latter, one can enable CONFIG_HSR and create a HSR device using: $ ip link add name hsr0 type hsr slave1 swp0 slave2 swp1 supervision 45 version 1 This needs to be connected using 2 cables to another system where the same command was run. Then, one should be able to ping the other board through the hsr0 interface. Without the Github branch, a ping over HSR should increase the DSA conduit interface's TX counters by 2 packets. With the Github branch, the TX counters should increase by only 1 packet. Why so many patches ------------------- To avoid the situation where a patch has to be backported, conflicts with the work done here, pulls this in as a dependency, and that pulls in 13 other unrelated drivers. These don't have any dependencies between each other and can be cherry-picked at will (except they all depend on patch 1/15). ==================== Link: https://patch.msgid.link/20251127120902.292555-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents e48766e + 64b0d2e commit 8aa1053

15 files changed

Lines changed: 46 additions & 55 deletions

net/dsa/tag.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,24 @@ static inline void *dsa_etype_header_pos_tx(struct sk_buff *skb)
319319
return skb->data + 2 * ETH_ALEN;
320320
}
321321

322+
static inline unsigned long dsa_xmit_port_mask(const struct sk_buff *skb,
323+
const struct net_device *dev)
324+
{
325+
struct dsa_port *dp = dsa_user_to_port(dev);
326+
unsigned long mask = BIT(dp->index);
327+
328+
if (IS_ENABLED(CONFIG_HSR) &&
329+
unlikely(dev->features & NETIF_F_HW_HSR_DUP)) {
330+
struct net_device *hsr_dev = dp->hsr_dev;
331+
struct dsa_port *other_dp;
332+
333+
dsa_hsr_foreach_port(other_dp, dp->ds, hsr_dev)
334+
mask |= BIT(other_dp->index);
335+
}
336+
337+
return mask;
338+
}
339+
322340
/* Create 2 modaliases per tagging protocol, one to auto-load the module
323341
* given the ID reported by get_tag_protocol(), and the other by name.
324342
*/

net/dsa/tag_brcm.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ static struct sk_buff *brcm_tag_xmit_ll(struct sk_buff *skb,
9292
{
9393
struct dsa_port *dp = dsa_user_to_port(dev);
9494
u16 queue = skb_get_queue_mapping(skb);
95+
u16 port_mask;
9596
u8 *brcm_tag;
9697

9798
/* The Ethernet switch we are interfaced with needs packets to be at
@@ -119,10 +120,9 @@ static struct sk_buff *brcm_tag_xmit_ll(struct sk_buff *skb,
119120
brcm_tag[0] = (1 << BRCM_OPCODE_SHIFT) |
120121
((queue & BRCM_IG_TC_MASK) << BRCM_IG_TC_SHIFT);
121122
brcm_tag[1] = 0;
122-
brcm_tag[2] = 0;
123-
if (dp->index == 8)
124-
brcm_tag[2] = BRCM_IG_DSTMAP2_MASK;
125-
brcm_tag[3] = (1 << dp->index) & BRCM_IG_DSTMAP1_MASK;
123+
port_mask = dsa_xmit_port_mask(skb, dev);
124+
brcm_tag[2] = (port_mask >> 8) & BRCM_IG_DSTMAP2_MASK;
125+
brcm_tag[3] = port_mask & BRCM_IG_DSTMAP1_MASK;
126126

127127
/* Now tell the conduit network device about the desired output queue
128128
* as well

net/dsa/tag_gswip.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@
4848

4949
/* Byte 3 */
5050
#define GSWIP_TX_DPID_EN BIT(0)
51-
#define GSWIP_TX_PORT_MAP_SHIFT 1
52-
#define GSWIP_TX_PORT_MAP_MASK GENMASK(6, 1)
51+
#define GSWIP_TX_PORT_MAP GENMASK(6, 1)
5352

5453
#define GSWIP_RX_HEADER_LEN 8
5554

@@ -61,7 +60,6 @@
6160
static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb,
6261
struct net_device *dev)
6362
{
64-
struct dsa_port *dp = dsa_user_to_port(dev);
6563
u8 *gswip_tag;
6664

6765
skb_push(skb, GSWIP_TX_HEADER_LEN);
@@ -70,7 +68,7 @@ static struct sk_buff *gswip_tag_xmit(struct sk_buff *skb,
7068
gswip_tag[0] = GSWIP_TX_SLPID_CPU;
7169
gswip_tag[1] = GSWIP_TX_DPID_ELAN;
7270
gswip_tag[2] = GSWIP_TX_PORT_MAP_EN | GSWIP_TX_PORT_MAP_SEL;
73-
gswip_tag[3] = BIT(dp->index + GSWIP_TX_PORT_MAP_SHIFT) & GSWIP_TX_PORT_MAP_MASK;
71+
gswip_tag[3] = FIELD_PREP(GSWIP_TX_PORT_MAP, dsa_xmit_port_mask(skb, dev));
7472
gswip_tag[3] |= GSWIP_TX_DPID_EN;
7573

7674
return skb;

net/dsa/tag_hellcreek.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
static struct sk_buff *hellcreek_xmit(struct sk_buff *skb,
2121
struct net_device *dev)
2222
{
23-
struct dsa_port *dp = dsa_user_to_port(dev);
2423
u8 *tag;
2524

2625
/* Calculate checksums (if required) before adding the trailer tag to
@@ -33,7 +32,7 @@ static struct sk_buff *hellcreek_xmit(struct sk_buff *skb,
3332

3433
/* Tag encoding */
3534
tag = skb_put(skb, HELLCREEK_TAG_LEN);
36-
*tag = BIT(dp->index);
35+
*tag = dsa_xmit_port_mask(skb, dev);
3736

3837
return skb;
3938
}

net/dsa/tag_ksz.c

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
120120

121121
static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)
122122
{
123-
struct dsa_port *dp = dsa_user_to_port(dev);
124123
struct ethhdr *hdr;
125124
u8 *tag;
126125

@@ -131,7 +130,7 @@ static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)
131130
tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
132131
hdr = skb_eth_hdr(skb);
133132

134-
*tag = 1 << dp->index;
133+
*tag = dsa_xmit_port_mask(skb, dev);
135134
if (is_link_local_ether_addr(hdr->h_dest))
136135
*tag |= KSZ8795_TAIL_TAG_OVERRIDE;
137136

@@ -294,21 +293,12 @@ static struct sk_buff *ksz9477_xmit(struct sk_buff *skb,
294293
tag = skb_put(skb, KSZ9477_INGRESS_TAG_LEN);
295294
hdr = skb_eth_hdr(skb);
296295

297-
val = BIT(dp->index);
298-
296+
val = dsa_xmit_port_mask(skb, dev);
299297
val |= FIELD_PREP(KSZ9477_TAIL_TAG_PRIO, prio);
300298

301299
if (is_link_local_ether_addr(hdr->h_dest))
302300
val |= KSZ9477_TAIL_TAG_OVERRIDE;
303301

304-
if (dev->features & NETIF_F_HW_HSR_DUP) {
305-
struct net_device *hsr_dev = dp->hsr_dev;
306-
struct dsa_port *other_dp;
307-
308-
dsa_hsr_foreach_port(other_dp, dp->ds, hsr_dev)
309-
val |= BIT(other_dp->index);
310-
}
311-
312302
*tag = cpu_to_be16(val);
313303

314304
return ksz_defer_xmit(dp, skb);
@@ -371,8 +361,7 @@ static struct sk_buff *ksz9893_xmit(struct sk_buff *skb,
371361
tag = skb_put(skb, KSZ_INGRESS_TAG_LEN);
372362
hdr = skb_eth_hdr(skb);
373363

374-
*tag = BIT(dp->index);
375-
364+
*tag = dsa_xmit_port_mask(skb, dev);
376365
*tag |= FIELD_PREP(KSZ9893_TAIL_TAG_PRIO, prio);
377366

378367
if (is_link_local_ether_addr(hdr->h_dest))
@@ -436,8 +425,7 @@ static struct sk_buff *lan937x_xmit(struct sk_buff *skb,
436425

437426
tag = skb_put(skb, LAN937X_EGRESS_TAG_LEN);
438427

439-
val = BIT(dp->index);
440-
428+
val = dsa_xmit_port_mask(skb, dev);
441429
val |= FIELD_PREP(LAN937X_TAIL_TAG_PRIO, prio);
442430

443431
if (is_link_local_ether_addr(hdr->h_dest))

net/dsa/tag_mtk.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
5454
* whether that's a combined special tag with 802.1Q header.
5555
*/
5656
mtk_tag[0] = xmit_tpid;
57-
mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
57+
mtk_tag[1] = FIELD_PREP(MTK_HDR_XMIT_DP_BIT_MASK,
58+
dsa_xmit_port_mask(skb, dev));
5859

5960
/* Tag control information is kept for 802.1Q */
6061
if (xmit_tpid == MTK_HDR_XMIT_UNTAGGED) {

net/dsa/tag_mxl-gsw1xx.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343
static struct sk_buff *gsw1xx_tag_xmit(struct sk_buff *skb,
4444
struct net_device *dev)
4545
{
46-
struct dsa_port *dp = dsa_user_to_port(dev);
4746
__be16 *gsw1xx_tag;
47+
u16 tag;
4848

4949
/* provide additional space 'GSW1XX_HEADER_LEN' bytes */
5050
skb_push(skb, GSW1XX_HEADER_LEN);
@@ -55,9 +55,10 @@ static struct sk_buff *gsw1xx_tag_xmit(struct sk_buff *skb,
5555
/* special tag ingress */
5656
gsw1xx_tag = dsa_etype_header_pos_tx(skb);
5757
gsw1xx_tag[0] = htons(ETH_P_MXLGSW);
58-
gsw1xx_tag[1] = htons(GSW1XX_TX_PORT_MAP_EN | GSW1XX_TX_LRN_DIS |
59-
FIELD_PREP(GSW1XX_TX_PORT_MAP, BIT(dp->index)));
6058

59+
tag = FIELD_PREP(GSW1XX_TX_PORT_MAP, dsa_xmit_port_mask(skb, dev)) |
60+
GSW1XX_TX_PORT_MAP_EN | GSW1XX_TX_LRN_DIS;
61+
gsw1xx_tag[1] = htons(tag);
6162
gsw1xx_tag[2] = 0;
6263
gsw1xx_tag[3] = 0;
6364

net/dsa/tag_ocelot.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,21 @@ static void ocelot_xmit_common(struct sk_buff *skb, struct net_device *netdev,
4646
static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
4747
struct net_device *netdev)
4848
{
49-
struct dsa_port *dp = dsa_user_to_port(netdev);
5049
void *injection;
5150

5251
ocelot_xmit_common(skb, netdev, cpu_to_be32(0x8880000a), &injection);
53-
ocelot_ifh_set_dest(injection, BIT_ULL(dp->index));
52+
ocelot_ifh_set_dest(injection, dsa_xmit_port_mask(skb, netdev));
5453

5554
return skb;
5655
}
5756

5857
static struct sk_buff *seville_xmit(struct sk_buff *skb,
5958
struct net_device *netdev)
6059
{
61-
struct dsa_port *dp = dsa_user_to_port(netdev);
6260
void *injection;
6361

6462
ocelot_xmit_common(skb, netdev, cpu_to_be32(0x88800005), &injection);
65-
seville_ifh_set_dest(injection, BIT_ULL(dp->index));
63+
seville_ifh_set_dest(injection, dsa_xmit_port_mask(skb, netdev));
6664

6765
return skb;
6866
}

net/dsa/tag_qca.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev)
1616
{
17-
struct dsa_port *dp = dsa_user_to_port(dev);
1817
__be16 *phdr;
1918
u16 hdr;
2019

@@ -26,7 +25,7 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev)
2625
/* Set the version field, and set destination port information */
2726
hdr = FIELD_PREP(QCA_HDR_XMIT_VERSION, QCA_HDR_VERSION);
2827
hdr |= QCA_HDR_XMIT_FROM_CPU;
29-
hdr |= FIELD_PREP(QCA_HDR_XMIT_DP_BIT, BIT(dp->index));
28+
hdr |= FIELD_PREP(QCA_HDR_XMIT_DP_BIT, dsa_xmit_port_mask(skb, dev));
3029

3130
*phdr = htons(hdr);
3231

net/dsa/tag_rtl4_a.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ static struct sk_buff *rtl4a_tag_xmit(struct sk_buff *skb,
5757

5858
out = (RTL4_A_PROTOCOL_RTL8366RB << RTL4_A_PROTOCOL_SHIFT);
5959
/* The lower bits indicate the port number */
60-
out |= BIT(dp->index);
60+
out |= dsa_xmit_port_mask(skb, dev);
6161

6262
p = (__be16 *)(tag + 2);
6363
*p = htons(out);

0 commit comments

Comments
 (0)