Commit 42824463 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

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: default avatarVladimir Oltean <olteanv@gmail.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f9a1a764
...@@ -392,11 +392,11 @@ static int sja1105_init_general_params(struct sja1105_private *priv) ...@@ -392,11 +392,11 @@ static int sja1105_init_general_params(struct sja1105_private *priv)
.hostprio = 0, .hostprio = 0,
.mac_fltres1 = SJA1105_LINKLOCAL_FILTER_A, .mac_fltres1 = SJA1105_LINKLOCAL_FILTER_A,
.mac_flt1 = SJA1105_LINKLOCAL_FILTER_A_MASK, .mac_flt1 = SJA1105_LINKLOCAL_FILTER_A_MASK,
.incl_srcpt1 = true, .incl_srcpt1 = false,
.send_meta1 = false, .send_meta1 = false,
.mac_fltres0 = SJA1105_LINKLOCAL_FILTER_B, .mac_fltres0 = SJA1105_LINKLOCAL_FILTER_B,
.mac_flt0 = SJA1105_LINKLOCAL_FILTER_B_MASK, .mac_flt0 = SJA1105_LINKLOCAL_FILTER_B_MASK,
.incl_srcpt0 = true, .incl_srcpt0 = false,
.send_meta0 = false, .send_meta0 = false,
/* The destination for traffic matching mac_fltres1 and /* The destination for traffic matching mac_fltres1 and
* mac_fltres0 on all ports except host_port. Such traffic * mac_fltres0 on all ports except host_port. Such traffic
...@@ -1435,6 +1435,11 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled) ...@@ -1435,6 +1435,11 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
general_params->tpid = tpid; general_params->tpid = tpid;
/* EtherType used to identify inner tagged (C-tag) VLAN traffic */ /* EtherType used to identify inner tagged (C-tag) VLAN traffic */
general_params->tpid2 = tpid2; general_params->tpid2 = tpid2;
/* When VLAN filtering is on, we need to at least be able to
* decode management traffic through the "backup plan".
*/
general_params->incl_srcpt1 = enabled;
general_params->incl_srcpt0 = enabled;
rc = sja1105_static_config_reload(priv); rc = sja1105_static_config_reload(priv);
if (rc) if (rc)
......
...@@ -69,15 +69,24 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, ...@@ -69,15 +69,24 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
int source_port, switch_id; int source_port, switch_id;
struct vlan_ethhdr *hdr; struct vlan_ethhdr *hdr;
u16 tpid, vid, tci; u16 tpid, vid, tci;
bool is_link_local;
bool is_tagged; bool is_tagged;
hdr = vlan_eth_hdr(skb); hdr = vlan_eth_hdr(skb);
tpid = ntohs(hdr->h_vlan_proto); tpid = ntohs(hdr->h_vlan_proto);
is_tagged = (tpid == ETH_P_SJA1105); is_tagged = (tpid == ETH_P_SJA1105);
is_link_local = sja1105_is_link_local(skb);
skb->offload_fwd_mark = 1; 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 /* Management traffic path. Switch embeds the switch ID and
* port ID into bytes of the destination MAC, courtesy of * port ID into bytes of the destination MAC, courtesy of
* the incl_srcpt options. * the incl_srcpt options.
...@@ -88,12 +97,7 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb, ...@@ -88,12 +97,7 @@ static struct sk_buff *sja1105_rcv(struct sk_buff *skb,
hdr->h_dest[3] = 0; hdr->h_dest[3] = 0;
hdr->h_dest[4] = 0; hdr->h_dest[4] = 0;
} else { } else {
/* Normal traffic path. */ return NULL;
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;
} }
skb->dev = dsa_master_find_slave(netdev, switch_id, source_port); skb->dev = dsa_master_find_slave(netdev, switch_id, source_port);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment