Commit 8aa1053f authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

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: default avatarJakub Kicinski <kuba@kernel.org>
parents e48766e6 64b0d2ed
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -319,6 +319,24 @@ static inline void *dsa_etype_header_pos_tx(struct sk_buff *skb)
	return skb->data + 2 * ETH_ALEN;
}

static inline unsigned long dsa_xmit_port_mask(const struct sk_buff *skb,
					       const struct net_device *dev)
{
	struct dsa_port *dp = dsa_user_to_port(dev);
	unsigned long mask = BIT(dp->index);

	if (IS_ENABLED(CONFIG_HSR) &&
	    unlikely(dev->features & NETIF_F_HW_HSR_DUP)) {
		struct net_device *hsr_dev = dp->hsr_dev;
		struct dsa_port *other_dp;

		dsa_hsr_foreach_port(other_dp, dp->ds, hsr_dev)
			mask |= BIT(other_dp->index);
	}

	return mask;
}

/* Create 2 modaliases per tagging protocol, one to auto-load the module
 * given the ID reported by get_tag_protocol(), and the other by name.
 */
+4 −4
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ static struct sk_buff *brcm_tag_xmit_ll(struct sk_buff *skb,
{
	struct dsa_port *dp = dsa_user_to_port(dev);
	u16 queue = skb_get_queue_mapping(skb);
	u16 port_mask;
	u8 *brcm_tag;

	/* 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,
	brcm_tag[0] = (1 << BRCM_OPCODE_SHIFT) |
		       ((queue & BRCM_IG_TC_MASK) << BRCM_IG_TC_SHIFT);
	brcm_tag[1] = 0;
	brcm_tag[2] = 0;
	if (dp->index == 8)
		brcm_tag[2] = BRCM_IG_DSTMAP2_MASK;
	brcm_tag[3] = (1 << dp->index) & BRCM_IG_DSTMAP1_MASK;
	port_mask = dsa_xmit_port_mask(skb, dev);
	brcm_tag[2] = (port_mask >> 8) & BRCM_IG_DSTMAP2_MASK;
	brcm_tag[3] = port_mask & BRCM_IG_DSTMAP1_MASK;

	/* Now tell the conduit network device about the desired output queue
	 * as well
+2 −4
Original line number Diff line number Diff line
@@ -48,8 +48,7 @@

/* Byte 3 */
#define GSWIP_TX_DPID_EN		BIT(0)
#define GSWIP_TX_PORT_MAP_SHIFT		1
#define GSWIP_TX_PORT_MAP_MASK		GENMASK(6, 1)
#define GSWIP_TX_PORT_MAP		GENMASK(6, 1)

#define GSWIP_RX_HEADER_LEN	8

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

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

	return skb;
+1 −2
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@
static struct sk_buff *hellcreek_xmit(struct sk_buff *skb,
				      struct net_device *dev)
{
	struct dsa_port *dp = dsa_user_to_port(dev);
	u8 *tag;

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

	/* Tag encoding */
	tag  = skb_put(skb, HELLCREEK_TAG_LEN);
	*tag = BIT(dp->index);
	*tag = dsa_xmit_port_mask(skb, dev);

	return skb;
}
+4 −16
Original line number Diff line number Diff line
@@ -120,7 +120,6 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,

static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct dsa_port *dp = dsa_user_to_port(dev);
	struct ethhdr *hdr;
	u8 *tag;

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

	*tag = 1 << dp->index;
	*tag = dsa_xmit_port_mask(skb, dev);
	if (is_link_local_ether_addr(hdr->h_dest))
		*tag |= KSZ8795_TAIL_TAG_OVERRIDE;

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

	val = BIT(dp->index);

	val = dsa_xmit_port_mask(skb, dev);
	val |= FIELD_PREP(KSZ9477_TAIL_TAG_PRIO, prio);

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

	if (dev->features & NETIF_F_HW_HSR_DUP) {
		struct net_device *hsr_dev = dp->hsr_dev;
		struct dsa_port *other_dp;

		dsa_hsr_foreach_port(other_dp, dp->ds, hsr_dev)
			val |= BIT(other_dp->index);
	}

	*tag = cpu_to_be16(val);

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

	*tag = BIT(dp->index);

	*tag = dsa_xmit_port_mask(skb, dev);
	*tag |= FIELD_PREP(KSZ9893_TAIL_TAG_PRIO, prio);

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

	tag = skb_put(skb, LAN937X_EGRESS_TAG_LEN);

	val = BIT(dp->index);

	val = dsa_xmit_port_mask(skb, dev);
	val |= FIELD_PREP(LAN937X_TAIL_TAG_PRIO, prio);

	if (is_link_local_ether_addr(hdr->h_dest))
Loading