mirror of
https://github.com/openwrt/openwrt.git
synced 2026-10-22 15:18:44 +04:00
realtek: dsa: drop untagged frames of ports without PVID
Every port is a member of VID 0, so that the frames the CPU sends with its PVID 0 reach the ports with untagged VLANs. A port without PVID keeps PVID 0 too, so in a VLAN-filtering bridge its untagged and priority tagged frames land in VID 0 and are flooded to the other ports of the bridge, tagged VID 0, where the bridge would drop them. The acceptable frame type of a port tells the two apart (one bit each for inner and outer, tagged and untagged frames; vendor SDK). While a port without PVID is in a VLAN-filtering bridge, it accepts only tagged frames, outer tagged ones as an 802.1ad port; standalone ports, which can have VLAN filtering on, and every other state accept all. The driver tracks the bridge membership itself, since DSA rolls back a failed join through port_bridge_leave() before it clears dp->bridge. VID 0 and the CPU path stay as they are. The register has this layout on all four families; only RTL839x sets its address here, the others keep their behaviour until tested. HPE 1920-48G (RTL8393), lan48 a UCI trunk with VLAN 3 and 7 tagged, lan47 an access port in VLAN 1: untagged and priority tagged ARP from the host behind lan48 left lan47 tagged VID 0, 3 of 3 each; now none does. STP, LLDP, LACP and EAPOL frames on lan48 still reach the CPU, 5 of 5 each, and VLAN 3 tagged frames pass. With a PVID on lan48 again, and in a bridge without VLAN filtering, the ARP leaves lan47 untagged; as standalone ports both accept all frames again. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Gennaro Cimmino <gcimmino@rayonra.net> Link: https://github.com/openwrt/openwrt/pull/25992 Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
This commit is contained in:
1 parent
14423144a5
commit
e4c5f850ee
5 files changed
+41
No files matched your search
@@ -840,6 +840,9 @@ static int rtldsa_port_bridge_join(struct dsa_switch *ds, int port, struct dsa_b
|
||||
priv->ports[port].qinq = true;
|
||||
}
|
||||
|
||||
priv->ports[port].bridged = true;
|
||||
otto_vlan_port_untagged_set(priv, port);
|
||||
|
||||
rtldsa_update_port_member(priv, port, bridge.dev, true);
|
||||
|
||||
if (priv->r->set_static_move_action)
|
||||
@@ -868,6 +871,9 @@ static void rtldsa_port_bridge_leave(struct dsa_switch *ds, int port, struct dsa
|
||||
priv->ports[port].qinq = false;
|
||||
}
|
||||
|
||||
priv->ports[port].bridged = false;
|
||||
otto_vlan_port_untagged_set(priv, port);
|
||||
|
||||
if (priv->r->set_static_move_action)
|
||||
priv->r->set_static_move_action(port, true);
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ struct rtldsa_port {
|
||||
bool phy:1;
|
||||
bool isolated:1;
|
||||
bool qinq:1;
|
||||
bool bridged:1;
|
||||
bool vlan_filtering:1;
|
||||
unsigned long rate_police_egress;
|
||||
unsigned long rate_police_ingress;
|
||||
unsigned long cached_flags;
|
||||
@@ -464,6 +466,7 @@ struct rtldsa_config {
|
||||
u32 (*l2_hash_key)(struct otto_dsa_priv *priv, u64 seed);
|
||||
u64 (*read_mcast_pmask)(int idx);
|
||||
void (*write_mcast_pmask)(int idx, u64 portmask);
|
||||
u32 vlan_port_aft;
|
||||
void (*vlan_fwd_on_inner)(struct otto_dsa_priv *priv, int port, bool is_set);
|
||||
void (*vlan_qinq_setup)(struct otto_dsa_priv *priv);
|
||||
void (*vlan_port_qinq_set)(struct otto_dsa_priv *priv, int port, bool enable);
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
|
||||
#define RTL839X_SPCL_TRAP_EAPOL_CTRL (0x105C)
|
||||
#define RTL839X_SPCL_TRAP_SWITCH_MAC_CTRL (0x1068)
|
||||
#define RTL839X_VLAN_PORT_AFT (0x2600)
|
||||
|
||||
#define RTL839X_IMR_GLB (0x0064)
|
||||
#define RTL839X_IMR_PORT_LINK_STS_CHG (0x0068)
|
||||
@@ -239,6 +240,7 @@ const struct rtldsa_config rtldsa_839x_cfg = {
|
||||
.vlan_profile_get = otto_vlan_839x_profile_get,
|
||||
.vlan_profile_dump = otto_vlan_839x_profile_dump,
|
||||
.vlan_profile_setup = otto_vlan_839x_profile_setup,
|
||||
.vlan_port_aft = RTL839X_VLAN_PORT_AFT,
|
||||
.vlan_fwd_on_inner = otto_vlan_839x_port_forward_on_inner,
|
||||
.vlan_port_keep_tag_set = otto_vlan_839x_port_keep_tag_set,
|
||||
.vlan_port_pvidmode_set = otto_vlan_839x_port_pvid_mode_set,
|
||||
|
||||
@@ -133,6 +133,31 @@
|
||||
#define RTL931X_VLAN_PORT_TAG_ITPID_IDX_MASK GENMASK(2, 1)
|
||||
#define RTL931X_VLAN_PORT_TAG_ITPID_KEEP_MASK GENMASK(0, 0)
|
||||
|
||||
#define RTLDSA_VLAN_PORT_AFT_ITAG_UNTAG BIT(1)
|
||||
#define RTLDSA_VLAN_PORT_AFT_OTAG_UNTAG BIT(3)
|
||||
#define RTLDSA_VLAN_PORT_AFT_ALL GENMASK(3, 0)
|
||||
|
||||
/*
|
||||
* Every port is a member of VID 0 for the frames the CPU sends, see
|
||||
* otto_vlan_setup(). A port without PVID in a VLAN-filtering bridge must not
|
||||
* flood its untagged frames there, so it accepts only tagged ones, outer tagged
|
||||
* ones as an 802.1ad port. Standalone ports can have VLAN filtering on.
|
||||
*/
|
||||
void otto_vlan_port_untagged_set(struct otto_dsa_priv *priv, int port)
|
||||
{
|
||||
struct rtldsa_port *p = &priv->ports[port];
|
||||
u32 aft = RTLDSA_VLAN_PORT_AFT_ALL;
|
||||
|
||||
if (!priv->r->vlan_port_aft || port == priv->r->cpu_port)
|
||||
return;
|
||||
|
||||
if (p->bridged && p->vlan_filtering && !p->pvid)
|
||||
aft &= ~(p->qinq ? RTLDSA_VLAN_PORT_AFT_OTAG_UNTAG :
|
||||
RTLDSA_VLAN_PORT_AFT_ITAG_UNTAG);
|
||||
|
||||
regmap_write(priv->map, priv->r->vlan_port_aft + (port << 2), aft);
|
||||
}
|
||||
|
||||
static void otto_vlan_port_pvid_set(struct otto_dsa_priv *priv,
|
||||
int port, int pvid)
|
||||
{
|
||||
@@ -145,6 +170,7 @@ static void otto_vlan_port_pvid_set(struct otto_dsa_priv *priv,
|
||||
PBVLAN_MODE_UNTAG_AND_PRITAG);
|
||||
|
||||
priv->ports[port].pvid = pvid;
|
||||
otto_vlan_port_untagged_set(priv, port);
|
||||
}
|
||||
|
||||
/* Initialize all VLANS */
|
||||
@@ -905,6 +931,9 @@ int otto_vlan_port_filtering(struct dsa_switch *ds, int port,
|
||||
priv->r->set_vlan_egr_filter(port, EGR_DISABLE);
|
||||
}
|
||||
|
||||
priv->ports[port].vlan_filtering = vlan_filtering;
|
||||
otto_vlan_port_untagged_set(priv, port);
|
||||
|
||||
/* Do we need to do something to the CPU-Port, too? */
|
||||
mutex_unlock(&priv->reg_mutex);
|
||||
|
||||
|
||||
@@ -152,6 +152,7 @@ void otto_vlan_931x_port_pvid_set(struct otto_dsa_priv *priv, int port, enum pbv
|
||||
int pvid);
|
||||
|
||||
void otto_vlan_setup(struct otto_dsa_priv *priv);
|
||||
void otto_vlan_port_untagged_set(struct otto_dsa_priv *priv, int port);
|
||||
int otto_vlan_port_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
|
||||
struct netlink_ext_ack *extack);
|
||||
int otto_vlan_port_add(struct dsa_switch *ds, int port, const struct switchdev_obj_port_vlan *vlan,
|
||||
|
||||
Reference in new issue
Block a user