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@xeront.com> Suggested-by: Birger Koblitz <mail@birger-koblitz.de> Tested-by: Luiz Angelo Daros de Luca <luizluca@gmail.com> Signed-off-by: Sander Vanheule <sander@svanheule.net>
This commit is contained in:
		| @@ -92,9 +92,8 @@ struct notify_b { | |||||||
| 	u32			reserved2[8]; | 	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 | 	// 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[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[2] = 0x0200;  // Set only AS_DPM, to enable DPM settings below | ||||||
| @@ -105,15 +104,14 @@ static void rtl838x_create_tx_header(struct p_hdr *h, int dest_port, int prio) | |||||||
| 	/* Set internal priority (PRI) and enable (AS_PRI) */ | 	/* Set internal priority (PRI) and enable (AS_PRI) */ | ||||||
| 	if (prio >= 0) | 	if (prio >= 0) | ||||||
| 		h->cpu_tag[2] |= ((prio & 0x7) | BIT(3)) << 12; | 		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 | 	// cpu_tag[0] is reserved on the RTL83XX SoCs | ||||||
| 	h->cpu_tag[1] = 0x0100; // RTL8390_CPU_TAG marker | 	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[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 | 	// h->cpu_tag[1] |= BIT(1) | BIT(0); // Bypass filter 1/2 | ||||||
| 	if (dest_port >= 32) { | 	if (dest_port >= 32) { | ||||||
| 		dest_port -= 32; | 		dest_port -= 32; | ||||||
| @@ -123,16 +121,13 @@ static void rtl839x_create_tx_header(struct p_hdr *h, int dest_port, int prio) | |||||||
| 		h->cpu_tag[4] = BIT(dest_port) >> 16; | 		h->cpu_tag[4] = BIT(dest_port) >> 16; | ||||||
| 		h->cpu_tag[5] = BIT(dest_port) & 0xffff; | 		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) */ | 	/* Set internal priority (PRI) and enable (AS_PRI) */ | ||||||
| 	if (prio >= 0) | 	if (prio >= 0) | ||||||
| 		h->cpu_tag[2] |= ((prio & 0x7) | BIT(3)) << 8; | 		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[0] = 0x8000;  // CPU tag marker | ||||||
| 	h->cpu_tag[1] = h->cpu_tag[2] = 0; | 	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; | 		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[0] = 0x8000;  // CPU tag marker | ||||||
| 	h->cpu_tag[1] = h->cpu_tag[2] = 0; | 	h->cpu_tag[1] = h->cpu_tag[2] = 0; | ||||||
| @@ -1144,8 +1139,9 @@ static int rtl838x_eth_tx(struct sk_buff *skb, struct net_device *dev) | |||||||
| 	len = skb->len; | 	len = skb->len; | ||||||
|  |  | ||||||
| 	/* Check for DSA tagging at the end of the buffer */ | 	/* 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 | 	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-3] < priv->cpu_port | ||||||
|  | 			&& skb->data[len-2] == 0x10 | ||||||
| 			&& skb->data[len-1] == 0x00) { | 			&& skb->data[len-1] == 0x00) { | ||||||
| 		/* Reuse tag space for CRC if possible */ | 		/* Reuse tag space for CRC if possible */ | ||||||
| 		dest_port = skb->data[len-3]; | 		dest_port = skb->data[len-3]; | ||||||
| @@ -1173,6 +1169,7 @@ static int rtl838x_eth_tx(struct sk_buff *skb, struct net_device *dev) | |||||||
| 				h->len -= 4; | 				h->len -= 4; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		if (dest_port >= 0) | ||||||
| 			priv->r->create_tx_header(h, dest_port, skb->priority >> 1); | 			priv->r->create_tx_header(h, dest_port, skb->priority >> 1); | ||||||
|  |  | ||||||
| 		/* Copy packet data to tx buffer */ | 		/* Copy packet data to tx buffer */ | ||||||
|   | |||||||
| @@ -436,7 +436,7 @@ struct rtl838x_eth_reg { | |||||||
| 	int mac; | 	int mac; | ||||||
| 	int l2_tbl_flush_ctrl; | 	int l2_tbl_flush_ctrl; | ||||||
| 	void (*update_cntr)(int r, int work_done); | 	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); | 	bool (*decode_tag)(struct p_hdr *h, struct dsa_tag *tag); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Sander Vanheule
					Sander Vanheule