From 1ee96a2f233b75dd5d41c61a90657fdb6520ec51 Mon Sep 17 00:00:00 2001 From: Gennaro Cimmino Date: Mon, 12 Oct 2026 20:26:00 +0200 Subject: [PATCH] realtek: l3: add a capability for per-route source MACs The common L3 code tells the RTL839x source MAC model apart by whether the family sets set_switch_mac: there a route takes the source MAC entry of the device it goes out of, its DMAC entry names that entry, and the entries are also the MACs whose frames are routed. Once both families reach their source MACs through the same operations, that test no longer tells them apart. Name the model with smac_per_route, set for RTL839x, and test that wherever the code chose it by set_switch_mac. No functional change: RTL839x sets both, RTL838x, RTL930x and RTL931x neither. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Gennaro Cimmino Link: https://github.com/openwrt/openwrt/pull/25852 Signed-off-by: Markus Stockhausen --- .../files-6.18/drivers/net/dsa/rtl83xx/l3.c | 15 ++++++++------- .../files-6.18/drivers/net/dsa/rtl83xx/l3.h | 6 ++++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c index bf5808293e9..990b0cd2f5e 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.c @@ -1900,7 +1900,7 @@ static void otto_l3_route_update_hw(struct otto_l3_ctrl *ctrl, struct otto_l3_ro * and gives the old one up only with the ROUTING row that names it. * With none free it keeps to the CPU, its next hop untouched. */ - if (ctrl->cfg->set_switch_mac && + if (ctrl->cfg->smac_per_route && (r->switch_mac_id < 0 || ctrl->switch_macs[r->switch_mac_id] != r->switch_mac)) { sa = otto_l3_switch_mac_get(ctrl, r->switch_mac); if (sa < 0) { @@ -1924,7 +1924,7 @@ static void otto_l3_route_update_hw(struct otto_l3_ctrl *ctrl, struct otto_l3_ro } } - if (ctrl->cfg->set_switch_mac && otto_l3_l2_entry_taken(ctrl, r, &key)) { + if (ctrl->cfg->smac_per_route && otto_l3_l2_entry_taken(ctrl, r, &key)) { if (!r->l2_taken) { if (r->attr.type == ROUTE_TYPE_IP4UC) dev_info(ctrl->dev, "gateway %pI4 also reached from another MAC on VLAN %d, routing %s in software\n", @@ -2362,7 +2362,7 @@ static void otto_l3_egress_sync(struct work_struct *work) mac = ether_addr_to_u64(dev->dev_addr); - if (ctrl->cfg->set_switch_mac) { + if (ctrl->cfg->smac_per_route) { otto_l3_switch_mac_sync(ctrl, dev, mac); goto out; } @@ -2805,7 +2805,7 @@ static int otto_l3_fib_add_v4(struct otto_l3_ctrl *ctrl, struct fib_entry_notifi route->nh.rvid = vlan; route->gw_ifindex = ndev->ifindex; - if (ctrl->cfg->set_switch_mac) { + if (ctrl->cfg->smac_per_route) { route->switch_mac = ether_addr_to_u64(ndev->dev_addr); route->switch_mac_id = otto_l3_switch_mac_get(ctrl, route->switch_mac); if (route->switch_mac_id < 0) @@ -3025,7 +3025,7 @@ static int otto_l3_fib_trap_v6(struct otto_l3_ctrl *ctrl, struct fib6_info *rt, * a MAC of its own may have no other route to take one, and frames to * that MAC would miss the trap rules, which match on the switch's MACs. */ - if (ctrl->cfg->set_switch_mac && ndev && !rt->fib6_nh->fib_nh_gw_family && + if (ctrl->cfg->smac_per_route && ndev && !rt->fib6_nh->fib_nh_gw_family && otto_l3_port_dev_lower_find(ndev, ctrl) >= 0) { route->gw_ifindex = ndev->ifindex; route->switch_mac = ether_addr_to_u64(ndev->dev_addr); @@ -3290,7 +3290,7 @@ static int otto_l3_fib_add_v6(struct otto_l3_ctrl *ctrl, struct fib6_entry_notif route->nh.rvid = vlan; route->gw_ifindex = ndev->ifindex; - if (ctrl->cfg->set_switch_mac) { + if (ctrl->cfg->smac_per_route) { route->switch_mac = ether_addr_to_u64(ndev->dev_addr); route->switch_mac_id = otto_l3_switch_mac_get(ctrl, route->switch_mac); if (route->switch_mac_id < 0) @@ -4467,6 +4467,7 @@ const struct otto_l3_config otto_l3_838x_cfg = { }; const struct otto_l3_config otto_l3_839x_cfg = { + .smac_per_route = true, .set_dmac = otto_l3_839x_set_dmac, .set_switch_mac = otto_l3_839x_set_switch_mac, .route_rows_move = otto_l3_839x_route_rows_move, @@ -4682,7 +4683,7 @@ int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv) return dev_err_probe(dev, err, "Failed to register netevent notifier\n"); } - if (ctrl->cfg->set_router_mac || ctrl->cfg->set_switch_mac) { + if (ctrl->cfg->set_router_mac || ctrl->cfg->smac_per_route) { ctrl->nd_nb.notifier_call = otto_l3_netdev_notifier; err = register_netdevice_notifier(&ctrl->nd_nb); if (err) { diff --git a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h index 07a660217aa..b522acb54d9 100644 --- a/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h +++ b/target/linux/realtek/files-6.18/drivers/net/dsa/rtl83xx/l3.h @@ -123,6 +123,12 @@ struct otto_l3_config { * need a PIE rule to match the destination and point at the next hop. */ bool use_l3_tables; + /* RTL839x: a route holds the source MAC entry of the device it goes + * out of, which its DMAC entry names, and the source MAC entries are + * also the MACs whose frames are routed. RTL930x reaches its source MAC + * through the egress interface of a next hop instead. + */ + bool smac_per_route; int (*find_slot)(struct otto_l3_ctrl *ctrl, struct otto_l3_route *rt, bool must_exist); void (*get_egress_intf)(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_intf *intf); void (*set_egress_intf)(struct otto_l3_ctrl *ctrl, int idx, struct otto_l3_intf *intf);