[openwrt/openwrt] realtek: correct egress frame port verification

LEDE Commits lede-commits at lists.infradead.org
Thu Jul 21 12:30:25 PDT 2022


svanheule pushed a commit to openwrt/openwrt.git, branch openwrt-22.03:
https://git.openwrt.org/396dc89ee74c833ba3f687b586a1718c13f17900

commit 396dc89ee74c833ba3f687b586a1718c13f17900
Author: Sander Vanheule <sander at svanheule.net>
AuthorDate: Sun Jun 19 10:29:35 2022 +0200

    realtek: correct egress frame port verification
    
    Destination switch ports for outgoing frame can range from 0 to
    CPU_PORT-1.
    
    Refactor the code to only generate egress frame CPU headers when a valid
    destination port number is available, and make the code a bit more
    consistent between different switch generations. Change the dest_port
    argument's type to 'unsigned int', since only positive values are valid.
    
    This fixes the issue where egress frames on switch port 0 did not
    receive a VLAN tag, because they are sent out without a CPU header.
    Also fixes a potential issue with invalid (negative) egress port numbers
    on RTL93xx switches.
    
    Reported-by: Arınç ÜNAL <arinc.unal at xeront.com>
    Suggested-by: Birger Koblitz <mail at birger-koblitz.de>
    Tested-by: Luiz Angelo Daros de Luca <luizluca at gmail.com>
    Signed-off-by: Sander Vanheule <sander at svanheule.net>
    (cherry picked from commit 1773264a0c6da099af7f36046f95f0126d6de1eb)
---
 .../files-5.10/drivers/net/ethernet/rtl838x_eth.c  | 73 +++++++++++-----------
 .../files-5.10/drivers/net/ethernet/rtl838x_eth.h  |  2 +-
 2 files changed, 36 insertions(+), 39 deletions(-)

diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c
index 1de420dea1..0eee06d803 100644
--- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c
+++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c
@@ -92,47 +92,42 @@ struct notify_b {
 	u32			reserved2[8];
 };
 
-static void rtl838x_create_tx_header(struct p_hdr *h, int dest_port, int prio)
+static void rtl838x_create_tx_header(struct p_hdr *h, unsigned int dest_port, int prio)
 {
-	if (dest_port > 0) {
-		// cpu_tag[0] is reserved on the RTL83XX SoCs
-		h->cpu_tag[1] = 0x0401;  // BIT 10: RTL8380_CPU_TAG, BIT0: L2LEARNING on
-		h->cpu_tag[2] = 0x0200;  // Set only AS_DPM, to enable DPM settings below
-		h->cpu_tag[3] = 0x0000;
-		h->cpu_tag[4] = BIT(dest_port) >> 16;
-		h->cpu_tag[5] = BIT(dest_port) & 0xffff;
+	// cpu_tag[0] is reserved on the RTL83XX SoCs
+	h->cpu_tag[1] = 0x0401;  // BIT 10: RTL8380_CPU_TAG, BIT0: L2LEARNING on
+	h->cpu_tag[2] = 0x0200;  // Set only AS_DPM, to enable DPM settings below
+	h->cpu_tag[3] = 0x0000;
+	h->cpu_tag[4] = BIT(dest_port) >> 16;
+	h->cpu_tag[5] = BIT(dest_port) & 0xffff;
 
-		/* Set internal priority (PRI) and enable (AS_PRI) */
-		if (prio >= 0)
-			h->cpu_tag[2] |= ((prio & 0x7) | BIT(3)) << 12;
-	}
+	/* Set internal priority (PRI) and enable (AS_PRI) */
+	if (prio >= 0)
+		h->cpu_tag[2] |= ((prio & 0x7) | BIT(3)) << 12;
 }
 
-static void rtl839x_create_tx_header(struct p_hdr *h, int dest_port, int prio)
+static void rtl839x_create_tx_header(struct p_hdr *h, unsigned int dest_port, int prio)
 {
-	if (dest_port > 0) {
-		// cpu_tag[0] is reserved on the RTL83XX SoCs
-		h->cpu_tag[1] = 0x0100; // RTL8390_CPU_TAG marker
-		h->cpu_tag[2] = h->cpu_tag[3] = h->cpu_tag[4] = h->cpu_tag[5] = 0;
-		// h->cpu_tag[1] |= BIT(1) | BIT(0); // Bypass filter 1/2
-		if (dest_port >= 32) {
-			dest_port -= 32;
-			h->cpu_tag[2] = BIT(dest_port) >> 16;
-			h->cpu_tag[3] = BIT(dest_port) & 0xffff;
-		} else {
-			h->cpu_tag[4] = BIT(dest_port) >> 16;
-			h->cpu_tag[5] = BIT(dest_port) & 0xffff;
-		}
-		h->cpu_tag[2] |= BIT(4); // Enable destination port mask use
-		h->cpu_tag[2] |= BIT(7); // Enable L2 Learning
-
-		/* Set internal priority (PRI) and enable (AS_PRI) */
-		if (prio >= 0)
-			h->cpu_tag[2] |= ((prio & 0x7) | BIT(3)) << 8;
+	// cpu_tag[0] is reserved on the RTL83XX SoCs
+	h->cpu_tag[1] = 0x0100; // RTL8390_CPU_TAG marker
+	h->cpu_tag[2] = BIT(4) | BIT(7); /* AS_DPM (4) and L2LEARNING (7) flags */
+	h->cpu_tag[3] = h->cpu_tag[4] = h->cpu_tag[5] = 0;
+	// h->cpu_tag[1] |= BIT(1) | BIT(0); // Bypass filter 1/2
+	if (dest_port >= 32) {
+		dest_port -= 32;
+		h->cpu_tag[2] = BIT(dest_port) >> 16;
+		h->cpu_tag[3] = BIT(dest_port) & 0xffff;
+	} else {
+		h->cpu_tag[4] = BIT(dest_port) >> 16;
+		h->cpu_tag[5] = BIT(dest_port) & 0xffff;
 	}
+
+	/* Set internal priority (PRI) and enable (AS_PRI) */
+	if (prio >= 0)
+		h->cpu_tag[2] |= ((prio & 0x7) | BIT(3)) << 8;
 }
 
-static void rtl930x_create_tx_header(struct p_hdr *h, int dest_port, int prio)
+static void rtl930x_create_tx_header(struct p_hdr *h, unsigned int dest_port, int prio)
 {
 	h->cpu_tag[0] = 0x8000;  // CPU tag marker
 	h->cpu_tag[1] = h->cpu_tag[2] = 0;
@@ -147,7 +142,7 @@ static void rtl930x_create_tx_header(struct p_hdr *h, int dest_port, int prio)
 		h->cpu_tag[2] = (BIT(5) | (prio & 0x1f)) << 8;
 }
 
-static void rtl931x_create_tx_header(struct p_hdr *h, int dest_port, int prio)
+static void rtl931x_create_tx_header(struct p_hdr *h, unsigned int dest_port, int prio)
 {
 	h->cpu_tag[0] = 0x8000;  // CPU tag marker
 	h->cpu_tag[1] = h->cpu_tag[2] = 0;
@@ -1144,9 +1139,10 @@ static int rtl838x_eth_tx(struct sk_buff *skb, struct net_device *dev)
 	len = skb->len;
 
 	/* Check for DSA tagging at the end of the buffer */
-	if (netdev_uses_dsa(dev) && skb->data[len-4] == 0x80 && skb->data[len-3] > 0
-			&& skb->data[len-3] < priv->cpu_port &&  skb->data[len-2] == 0x10
-			&&  skb->data[len-1] == 0x00) {
+	if (netdev_uses_dsa(dev) && skb->data[len-4] == 0x80
+			&& skb->data[len-3] < priv->cpu_port
+			&& skb->data[len-2] == 0x10
+			&& skb->data[len-1] == 0x00) {
 		/* Reuse tag space for CRC if possible */
 		dest_port = skb->data[len-3];
 		skb->data[len-4] = skb->data[len-3] = skb->data[len-2] = skb->data[len-1] = 0x00;
@@ -1173,7 +1169,8 @@ static int rtl838x_eth_tx(struct sk_buff *skb, struct net_device *dev)
 				h->len -= 4;
 		}
 
-		priv->r->create_tx_header(h, dest_port, skb->priority >> 1);
+		if (dest_port >= 0)
+			priv->r->create_tx_header(h, dest_port, skb->priority >> 1);
 
 		/* Copy packet data to tx buffer */
 		memcpy((void *)KSEG1ADDR(h->buf), skb->data, len);
diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.h
index 2d1f80dc9d..5db5f545b9 100644
--- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.h
+++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.h
@@ -436,7 +436,7 @@ struct rtl838x_eth_reg {
 	int mac;
 	int l2_tbl_flush_ctrl;
 	void (*update_cntr)(int r, int work_done);
-	void (*create_tx_header)(struct p_hdr *h, int dest_port, int prio);
+	void (*create_tx_header)(struct p_hdr *h, unsigned int dest_port, int prio);
 	bool (*decode_tag)(struct p_hdr *h, struct dsa_tag *tag);
 };
 




More information about the lede-commits mailing list