From: Sander Vanheule Date: Sun, 19 Jun 2022 08:29:35 +0000 (+0200) Subject: realtek: correct egress frame port verification X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fstaging%2Fstintel.git;a=commitdiff_plain;h=1773264a0c6da099af7f36046f95f0126d6de1eb 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 Suggested-by: Birger Koblitz Tested-by: Luiz Angelo Daros de Luca Signed-off-by: Sander Vanheule --- 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); };