Thread (9 messages) flat view 9 messages, 3 authors, 4d ago

Re: [PATCH net-next v13 2/4] net: dsa: tag_ks8995: Add the KS8995 tag handling

From: netdev-bot+sashiko@kernel.org
Date: 2026-09-14 20:46:59
Also in: linux-devicetree

Thank you for your contribution! Sashiko AI review found 2 potential
issue(s) to consider:

Critical: 0 · High: 0 · Medium: 1 · Low: 1

- [Medium] net/dsa/tag_ks8995.c declares KS8995_NEEDED_HEADROOM =
  KS8995_TAG_LEN + VLAN_HLEN = 8 (needed for TX, where…
- [Low] net/dsa/tag_ks8995.c:ks8995_rcv() lines 120-134 use the special
  tag's TCI as the only discriminator between a hardware-inserted…

--

net: dsa: tag_ks8995: Add the KS8995 tag handling

This adds a new DSA tagger for the Micrel KS8995 / Microchip KSZ8995XA
switches, which carry the switch tag in a modified 0x8100 ethertype
where the low nibble is a port mask. Egress inserts the special tag at
offset 12 after pushing any hardware-accelerated VLAN tag inside, and
ingress moves the in-band tag into VLAN metadata before resolving the
source port.

A couple of questions below.
quoted hunk ↗ jump to hunk
diff --git a/net/dsa/tag_ks8995.c b/net/dsa/tag_ks8995.c
new file mode 100644
index 0000000000000..435665013a864
--- /dev/null
+++ b/net/dsa/tag_ks8995.c
@@ -0,0 +1,153 @@
[ ... ]
+#define KS8995_NAME "ks8995"
+
+#define KS8995_TAG_LEN		VLAN_HLEN
+/* Reserve room for the switch tag and a hardware-accelerated VLAN tag. */
+#define KS8995_NEEDED_HEADROOM	(KS8995_TAG_LEN + VLAN_HLEN)
[Severity: Medium]
The transmit side can add two 4-byte tags, so reserving 8 bytes of
headroom makes sense there, but the in-band tag seen on receive is only
VLAN_HLEN.  Since ks8995_netdev_ops does not provide a .flow_dissect
callback, __skb_flow_dissect() falls back to the generic helper, which
takes needed_headroom as the tag length:

include/net/dsa.h:dsa_tag_generic_flow_dissect() {
	const struct dsa_device_ops *ops = skb->dev->dsa_ptr->tag_ops;
	int tag_len = ops->needed_headroom;

	*offset = tag_len;
	*proto = ((__be16 *)skb->data)[(tag_len / 2) - 1];
}

With tag_len == 8 that reads *proto from skb->data + 6 and advances
nhoff by 8, while the real EtherType of a single-tagged frame sits at
skb->data + 2.  For IPv4 the bogus proto is taken from the IP total
length field, which varies per packet, so skb_get_hash() and any tc
classifier on the conduit would see a different pseudo-protocol per
frame and RPS/RFS could steer one flow across CPUs.

Would it make sense to follow the pattern already used in
tag_sja1105.c:sja1110_flow_dissect() and tag_netc.c:netc_flow_dissect(),
which keep the larger needed_headroom but override the dissector with
*offset = VLAN_HLEN and *proto = ((__be16 *)skb->data)[(VLAN_HLEN / 2) - 1]?

[ ... ]
+	/* The special tag's TCI is now in the hardware-accelerated VLAN
+	 * metadata. The switch preserves the TCI of tagged
+	 * frames, but inserts the ingress port's default tag for untagged frames.
+	 * Since the driver programs the default tag to 0, a zero TCI identifies
+	 * an originally untagged frame. Preserve every non-zero TCI as an
+	 * 802.1Q tag, including VID 0 frames with PCP or DEI set.
+	 */
+	if (!skb->vlan_tci) {
+		netdev_dbg(dev, "%s: clear VLAN tag from frame\n", __func__);
+		__vlan_hwaccel_clear_tag(skb);
+	} else {
+		skb->vlan_proto = htons(ETH_P_8021Q);
+		netdev_dbg(dev, "%s: vlan_tci = 0x%04x VLAN frame\n",
+			   __func__, skb->vlan_tci);
+	}
[Severity: Low]
Does this drop a legal 802.1Q tag whose TCI happens to be all zero?

A station sending a priority tag with VID 0, PCP 0 and DEI 0 produces
TCI == 0x0000 on the wire, and after skb_vlan_untag() moved the special
tag into the metadata that is identical to the switch-inserted default
tag, so ks8995_rcv() takes the __vlan_hwaccel_clear_tag() branch and the
frame reaches the stack untagged.  That would be visible to a VLAN 0
upper interface and to a capture on the user port.

To be clear about what was checked: the default-tag == 0 assumption in
the comment does hold at the end of the series.  The later commit
"net: dsa: microchip: Support Microchip KSZ8995XA / KS8995XA" writes
REG_PORT_CTRL_VID = 0 for every port in ksz8_port_setup():

	/* Use VID 0 to identify untagged frames in the special tag */
	ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, 0);

ksz8995xa_switch_ops exposes no .port_vlan_filtering or .port_vlan_add,
so a bridge PVID cannot end up in that register, and the default port
priority lives in Port Control 0 (KSZ8995XA_PORT_BASED_PRIO in
ksz_dcb.c) rather than in the inserted TCI.  So the only remaining case
is the all-zero wire tag above.  Is that ambiguity worth a note in the
comment, given it is inherent to the tag format?
+static const struct dsa_device_ops ks8995_netdev_ops = {
+	.name = KS8995_NAME,
+	.proto	= DSA_TAG_PROTO_KS8995,
+	.xmit = ks8995_xmit,
+	.rcv = ks8995_rcv,
+	.needed_headroom = KS8995_NEEDED_HEADROOM,
+};
[ ... ]

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260913-ks8995-to-ksz8-v13-0-327b16d309eb%40kernel.org
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help