interface-ip: fix IPv4 route target masking
[project/netifd.git] / system-linux.c
index 00530f2dc4e9313986b26a9e41aaa954e579a007..cc1b5e969132c41ceaa38744faa07b9d94125436 100644 (file)
@@ -700,12 +700,10 @@ static void
 system_device_update_state(struct device *dev, unsigned int flags, unsigned int ifindex)
 {
        if (dev->type == &simple_device_type) {
-               bool present = ifindex > 0;
-
                if (dev->external)
-                       present = present && (flags & IFF_UP);
+                       device_set_disabled(dev, !(flags & IFF_UP));
 
-               device_set_present(dev, present);
+               device_set_present(dev, ifindex > 0);
        }
        device_set_link(dev, flags & IFF_LOWER_UP ? true : false);
 }
@@ -1714,6 +1712,7 @@ int system_vlandev_del(struct device *vlandev)
        return system_link_del(vlandev->ifname);
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)
 struct if_get_master_data {
        int ifindex;
        int master_ifindex;
@@ -1843,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, };
@@ -1876,6 +1886,7 @@ static void system_set_master(struct device *dev, int master_ifindex)
 failure:
        nlmsg_free(nlm);
 }
+#endif
 
 static void ethtool_link_mode_clear_bit(__s8 nwords, int nr, __u32 *mask)
 {
@@ -1982,6 +1993,23 @@ system_set_ethtool_pause(struct device *dev, struct device_settings *s)
        ioctl(sock_ioctl, SIOCETHTOOL, &ifr);
 }
 
+static void
+system_set_ethtool_eee_settings(struct device *dev, struct device_settings *s)
+{
+       struct ethtool_eee eeecmd;
+       struct ifreq ifr = {
+               .ifr_data = (caddr_t)&eeecmd,
+       };
+
+       memset(&eeecmd, 0, sizeof(eeecmd));
+       eeecmd.cmd = ETHTOOL_SEEE;
+       eeecmd.eee_enabled = s->eee;
+       strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
+
+       if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) != 0)
+               netifd_log_message(L_WARNING, "cannot set eee %d for device %s", s->eee, dev->ifname);
+}
+
 static void
 system_set_ethtool_settings(struct device *dev, struct device_settings *s)
 {
@@ -1998,6 +2026,9 @@ system_set_ethtool_settings(struct device *dev, struct device_settings *s)
 
        system_set_ethtool_pause(dev, s);
 
+       if (s->flags & DEV_OPT_EEE)
+               system_set_ethtool_eee_settings(dev, s);
+
        memset(&ecmd, 0, sizeof(ecmd));
        ecmd.req.cmd = ETHTOOL_GLINKSETTINGS;
        strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
@@ -2197,11 +2228,13 @@ system_if_get_settings(struct device *dev, struct device_settings *s)
                s->flags |= DEV_OPT_GRO;
        }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,1,0)
        ret = system_if_get_master_ifindex(dev);
        if (ret >= 0) {
                s->master_ifindex = ret;
                s->flags |= DEV_OPT_MASTER;
        }
+#endif
 }
 
 void
@@ -2300,8 +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);
 }