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 <ansuelsmth@gmail.com>
+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, };
static void system_set_master(struct device *dev, int master_ifindex)
{
struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC, };
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");
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);
#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
#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);
}
system_set_ethtool_settings(dev, s);
}