The ethernet driver uses a port map override via special tag to control
the ports on which multicast packets are sent. This was added to work
around an issue in the switch that was occasionally leaking packets onto
the wrong vlan.
Unfortunately the change had some leftover lines that were overwrting
the port map with a list of all ports, thus always leaking packets onto
the wront vlan.
Fix this by only enabling the override with the VLAN port map and only
if a matching VLAN port map was actually found
Signed-off-by: Felix Fietkau <nbd@nbd.name>
+};
--- /dev/null
+++ b/drivers/net/ethernet/lantiq_xrx200.c
+};
--- /dev/null
+++ b/drivers/net/ethernet/lantiq_xrx200.c
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ struct xrx200_chan *ch;
+ struct ltq_dma_desc *desc;
+ u32 byte_offset;
+ struct xrx200_chan *ch;
+ struct ltq_dma_desc *desc;
+ u32 byte_offset;
+ int ret = NETDEV_TX_OK;
+ int len;
+#ifdef SW_ROUTING
+ int ret = NETDEV_TX_OK;
+ int len;
+#ifdef SW_ROUTING
+
+#ifdef SW_ROUTING
+ if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
+
+#ifdef SW_ROUTING
+ if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
-+ u16 port_map = priv->port_map;
-+ special_tag |= PORT_MAP_SEL | PORT_MAP_EN;
+ if (skb->protocol == htons(ETH_P_8021Q)) {
+ u16 vid;
+ int i;
+ if (skb->protocol == htons(ETH_P_8021Q)) {
+ u16 vid;
+ int i;
-+ special_tag |= port_map << PORT_MAP_SHIFT;
-+ special_tag |= priv->port_map << PORT_MAP_SHIFT;
++ if (port_map) {
++ special_tag |= (port_map << PORT_MAP_SHIFT) |
++ PORT_MAP_SEL | PORT_MAP_EN;
++ }
+ if(priv->wan)
+ special_tag |= (1 << DPID_SHIFT);
+ if(skb_headroom(skb) < 4) {
+ if(priv->wan)
+ special_tag |= (1 << DPID_SHIFT);
+ if(skb_headroom(skb) < 4) {
+};
--- /dev/null
+++ b/drivers/net/ethernet/lantiq_xrx200.c
+};
--- /dev/null
+++ b/drivers/net/ethernet/lantiq_xrx200.c
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ struct xrx200_chan *ch;
+ struct ltq_dma_desc *desc;
+ u32 byte_offset;
+ struct xrx200_chan *ch;
+ struct ltq_dma_desc *desc;
+ u32 byte_offset;
+ int ret = NETDEV_TX_OK;
+ int len;
+#ifdef SW_ROUTING
+ int ret = NETDEV_TX_OK;
+ int len;
+#ifdef SW_ROUTING
+
+#ifdef SW_ROUTING
+ if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
+
+#ifdef SW_ROUTING
+ if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
-+ u16 port_map = priv->port_map;
-+ special_tag |= PORT_MAP_SEL | PORT_MAP_EN;
+ if (skb->protocol == htons(ETH_P_8021Q)) {
+ u16 vid;
+ int i;
+ if (skb->protocol == htons(ETH_P_8021Q)) {
+ u16 vid;
+ int i;
-+ special_tag |= port_map << PORT_MAP_SHIFT;
-+ special_tag |= priv->port_map << PORT_MAP_SHIFT;
++ if (port_map) {
++ special_tag |= (port_map << PORT_MAP_SHIFT) |
++ PORT_MAP_SEL | PORT_MAP_EN;
++ }
+ if(priv->wan)
+ special_tag |= (1 << DPID_SHIFT);
+ if(skb_headroom(skb) < 4) {
+ if(priv->wan)
+ special_tag |= (1 << DPID_SHIFT);
+ if(skb_headroom(skb) < 4) {