realtek: dsa: rtl83xx: check L4 port and VLAN template fields

*_pie_verify_template() rejected a template that lacked the SIP, DIP,
SMAC or DMAC field a rule needs, but silently accepted one missing the
L4 source/destination port or inner-VLAN fields. When such a template
was picked the corresponding match was simply dropped: a
"flower ip_proto udp dst_port 5353" offload installed against an L2-only
template matched every UDP frame instead of just mDNS.

The same gap exists identically in all four PIE-based SoCs (rtl838x,
rtl839x, rtl930x, rtl931x): each verify_template() stops at the SMAC/DMAC
check and never looks at the L4 port or VLAN fields.

Reject a template that does not carry the port/VLAN field the rule masks,
so the block search falls through to one that does.

The failure was observed on an RTL9302C (Zyxel XGS1210-12, rtl930x): a
dst_port 5353 drop rule also counted UDP sent to other ports. rtl838x/
839x/931x share the same verify_template() structure and template
layout, so the fix is applied there too, though only rtl930x hardware
was available to reproduce and verify it.

Assisted-by: Claude Code (Anthropic Claude Sonnet 5)
Signed-off-by: Mark Abe <github@mab.wien>
Link: https://github.com/openwrt/openwrt/pull/25024
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
This commit is contained in:
Mark Abe authored and Markus Stockhausen committed 2026-09-05 23:11:32 +02:00
1 parent d51cfa41a6
commit d6933d6aed
4 files changed
+36

No files matched your search

@@ -1487,6 +1487,15 @@ static int rtl838x_pie_verify_template(struct rtl838x_switch_priv *priv,
if (ether_addr_to_u64(pr->dmac) && !rtl838x_pie_templ_has(t, TEMPLATE_FIELD_DMAC0))
return -1;
if (pr->itag_m && !rtl838x_pie_templ_has(t, TEMPLATE_FIELD_ITAG))
return -1;
if (pr->sport_m && !rtl838x_pie_templ_has(t, TEMPLATE_FIELD_L4_SPORT))
return -1;
if (pr->dport_m && !rtl838x_pie_templ_has(t, TEMPLATE_FIELD_L4_DPORT))
return -1;
/* TODO: Check more */
i = find_first_zero_bit(&priv->pie_use_bm[block * 4], PIE_BLOCK_SIZE);
@@ -1383,6 +1383,15 @@ static int rtl839x_pie_verify_template(struct rtl838x_switch_priv *priv,
if (ether_addr_to_u64(pr->dmac) && !rtl839x_pie_templ_has(t, TEMPLATE_FIELD_DMAC0))
return -1;
if (pr->itag_m && !rtl839x_pie_templ_has(t, TEMPLATE_FIELD_ITAG))
return -1;
if (pr->sport_m && !rtl839x_pie_templ_has(t, TEMPLATE_FIELD_L4_SPORT))
return -1;
if (pr->dport_m && !rtl839x_pie_templ_has(t, TEMPLATE_FIELD_L4_DPORT))
return -1;
/* TODO: Check more */
i = find_first_zero_bit(&priv->pie_use_bm[block * 4], PIE_BLOCK_SIZE);
@@ -1749,6 +1749,15 @@ static int rtl930x_pie_verify_template(struct rtl838x_switch_priv *priv,
if (ether_addr_to_u64(pr->dmac) && !rtl930x_pie_templ_has(t, TEMPLATE_FIELD_DMAC0))
return -1;
if (pr->itag_m && !rtl930x_pie_templ_has(t, TEMPLATE_FIELD_VLAN))
return -1;
if (pr->sport_m && !rtl930x_pie_templ_has(t, TEMPLATE_FIELD_L4_SPORT))
return -1;
if (pr->dport_m && !rtl930x_pie_templ_has(t, TEMPLATE_FIELD_L4_DPORT))
return -1;
/* TODO: Check more */
i = find_first_zero_bit(&priv->pie_use_bm[block * 4], PIE_BLOCK_SIZE);
@@ -1411,6 +1411,15 @@ static int rtl931x_pie_verify_template(struct rtl838x_switch_priv *priv,
if (ether_addr_to_u64(pr->dmac) && !rtl931x_pie_templ_has(t, TEMPLATE_FIELD_DMAC0))
return -1;
if (pr->itag_m && !rtl931x_pie_templ_has(t, TEMPLATE_FIELD_VLAN))
return -1;
if (pr->sport_m && !rtl931x_pie_templ_has(t, TEMPLATE_FIELD_L4_SPORT))
return -1;
if (pr->dport_m && !rtl931x_pie_templ_has(t, TEMPLATE_FIELD_L4_DPORT))
return -1;
/* TODO: Check more */
i = find_first_zero_bit(&priv->pie_use_bm[block * 4], PIE_BLOCK_SIZE);