summaryrefslogtreecommitdiffstats
path: root/net/dsa
diff options
context:
space:
mode:
authorVladimir Oltean <olteanv@gmail.com>2019-06-08 15:04:32 +0300
committerDavid S. Miller <davem@davemloft.net>2019-06-08 15:20:40 -0700
commit42824463d38d273194376051d7883724aea1b0ac (patch)
treeed29c4d66c66a42c0cfe7a825a0ab5bea6b2829f /net/dsa
parentf9a1a7646c0d8351a2529b221c4f5fa46b384ee6 (diff)
downloadlinux-42824463d38d273194376051d7883724aea1b0ac.tar.bz2
net: dsa: sja1105: Limit use of incl_srcpt to bridge+vlan mode
The incl_srcpt setting makes the switch mangle the destination MACs of multicast frames trapped to the CPU - a primitive tagging mechanism that works even when we cannot use the 802.1Q software features. The downside is that the two multicast MAC addresses that the switch traps for L2 PTP (01-80-C2-00-00-0E and 01-1B-19-00-00-00) quickly turn into a lot more, as the switch encodes the source port and switch id into bytes 3 and 4 of the MAC. The resulting range of MAC addresses would need to be installed manually into the DSA master port's multicast MAC filter, and even then, most devices might not have a large enough MAC filtering table. As a result, only limit use of incl_srcpt to when it's strictly necessary: when under a VLAN filtering bridge. This fixes PTP in non-bridged mode (standalone ports). Otherwise, PTP frames, as well as metadata follow-up frames holding RX timestamps won't be received because they will be blocked by the master port's MAC filter. Linuxptp doesn't help, because it only requests the addition of the unmodified PTP MACs to the multicast filter. This issue is not seen in bridged mode because the master port is put in promiscuous mode when the slave ports are enslaved to a bridge. Therefore, there is no downside to having the incl_srcpt mechanism active there. Signed-off-by: Vladimir Oltean <olteanv@gmail.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa')
-rw-r--r--net/dsa/tag_sja1105.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c
index 77eeea004e92..cd8e0bfb5e75 100644
--- a/net/dsa/tag_sja1105.c
+++ b/net/dsa/tag_sja1105.c
@@ -69,15 +69,24 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
int source_port, switch_id;
struct vlan_ethhdr *hdr;
u16 tpid, vid, tci;
+ bool is_link_local;
bool is_tagged;
hdr = vlan_eth_hdr(skb);
tpid = ntohs(hdr->h_vlan_proto);
is_tagged = (tpid == ETH_P_SJA1105);
+ is_link_local = sja1105_is_link_local(skb);
skb->offload_fwd_mark = 1;
- if (sja1105_is_link_local(skb)) {
+ if (is_tagged) {
+ /* Normal traffic path. */
+ tci = ntohs(hdr->h_vlan_TCI);
+ vid = tci & VLAN_VID_MASK;
+ source_port = dsa_8021q_rx_source_port(vid);
+ switch_id = dsa_8021q_rx_switch_id(vid);
+ skb->priority = (tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+ } else if (is_link_local) {
/* Management traffic path. Switch embeds the switch ID and
* port ID into bytes of the destination MAC, courtesy of
* the incl_srcpt options.
@@ -88,12 +97,7 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
hdr->h_dest[3] = 0;
hdr->h_dest[4] = 0;
} else {
- /* Normal traffic path. */
- tci = ntohs(hdr->h_vlan_TCI);
- vid = tci & VLAN_VID_MASK;
- source_port = dsa_8021q_rx_source_port(vid);
- switch_id = dsa_8021q_rx_switch_id(vid);
- skb->priority = (tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+ return NULL;
}
skb->dev = dsa_master_find_slave(netdev, switch_id, source_port);