From: Christian Marangi Date: Sat, 11 Nov 2023 22:27:11 +0000 (+0100) Subject: system-linux: refresh MAC address on DSA port conduit change X-Git-Url: http://git.openwrt.org/?p=project%2Fnetifd.git;a=commitdiff_plain;h=c739dee0a37bc593aaed7ae3f0a61e3d7c1fb1ac system-linux: refresh MAC address on DSA port conduit change On changing the conduit for a DSA port, the conduit may have different a MAC address. In the scenario where a port is part of a bridge and is the primary port, some inconsistency may arise where the bridge have the MAC address of the previous conduit and is never updated. This inconsistency cause problem with packet forwarding with FDB and other related problems. To fix this, refresh the original MAC address after the conduit for the DSA port is changed by polling the new MAC address for the device using ioctl API. Fixes: 2dc7f450f3a2 ("system-linux: add option to configure DSA conduit device") Signed-off-by: Christian Marangi --- diff --git a/system-linux.c b/system-linux.c index 21110c5..cc1b5e9 100644 --- a/system-linux.c +++ b/system-linux.c @@ -1842,6 +1842,17 @@ out: return ret; } +static void system_refresh_orig_macaddr(struct device *dev, struct device_settings *s) +{ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1); + + if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) + memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr)); +} + static void system_set_master(struct device *dev, int master_ifindex) { struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, }; @@ -2322,12 +2333,14 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, uint64_t system_set_drop_unsolicited_na(dev, s->drop_unsolicited_na ? "1" : "0"); if (apply_mask & DEV_OPT_ARP_ACCEPT) system_set_arp_accept(dev, s->arp_accept ? "1" : "0"); - if (apply_mask & DEV_OPT_MASTER) + if (apply_mask & DEV_OPT_MASTER) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0) system_set_master(dev, s->master_ifindex); + system_refresh_orig_macaddr(dev, &dev->orig_settings); #else netifd_log_message(L_WARNING, "%s Your kernel is older than linux 6.1.0, changing DSA port conduit is not supported!", dev->ifname); #endif + } system_set_ethtool_settings(dev, s); }