device: add support to configure eee
authorRahul Thakur <rahul.thakur@iopsys.eu>
Sat, 19 Aug 2023 03:33:46 +0000 (09:03 +0530)
committerRahul Thakur <rahul.thakur@iopsys.eu>
Fri, 10 Nov 2023 12:14:27 +0000 (17:44 +0530)
Add support for configurable EEE option i.e. energy efficient ethernet.

The option can be configured by adding the config for the device in the
network uci config. Example:

config device
option name 'eth0'
option eee '1'

Signed-off-by: Rahul Thakur <rahul.thakur@iopsys.eu>
device.c
device.h
system-linux.c

index 3ad1563b79a2d734b88c5952cfc90e2d43ffc3d8..e26edbbc2d223030b14d0f10a711558ffbc182c9 100644 (file)
--- a/device.c
+++ b/device.c
@@ -74,6 +74,7 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
        [DEV_ATTR_AUTONEG] = { .name = "autoneg", .type = BLOBMSG_TYPE_BOOL },
        [DEV_ATTR_GRO] = { .name = "gro", .type = BLOBMSG_TYPE_BOOL },
        [DEV_ATTR_MASTER] = { .name = "conduit", .type = BLOBMSG_TYPE_STRING },
+       [DEV_ATTR_EEE] = { .name = "eee", .type = BLOBMSG_TYPE_BOOL },
 };
 
 const struct uci_blob_param_list device_attr_list = {
@@ -299,6 +300,7 @@ device_merge_settings(struct device *dev, struct device_settings *n)
        n->txpause = s->flags & DEV_OPT_TXPAUSE ? s->txpause : os->txpause;
        n->autoneg = s->flags & DEV_OPT_AUTONEG ? s->autoneg : os->autoneg;
        n->gro = s->flags & DEV_OPT_GRO ? s->gro : os->gro;
+       n->eee = s->flags & DEV_OPT_EEE ? s->eee : os->eee;
        n->master_ifindex = s->flags & DEV_OPT_MASTER ? s->master_ifindex : os->master_ifindex;
        n->flags = s->flags | os->flags | os->valid_flags;
 }
@@ -561,6 +563,11 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
                s->flags |= DEV_OPT_MASTER;
        }
 
+       if ((cur = tb[DEV_ATTR_EEE])) {
+               s->eee = blobmsg_get_bool(cur);
+               s->flags |= DEV_OPT_EEE;
+       }
+
        cur = tb[DEV_ATTR_AUTH_VLAN];
        free(dev->config_auth_vlans);
        dev->config_auth_vlans = cur ? blob_memdup(cur) : NULL;
@@ -1388,6 +1395,8 @@ device_dump_status(struct blob_buf *b, struct device *dev)
                        blobmsg_add_u8(b, "auth", st.auth);
                if (st.flags & DEV_OPT_GRO)
                        blobmsg_add_u8(b, "gro", st.gro);
+               if (st.flags & DEV_OPT_EEE)
+                       blobmsg_add_u8(b, "eee", st.eee);
        }
 
        s = blobmsg_open_table(b, "statistics");
index 8bad7fb2d2dd2010fadf4c6069e7a5b40183dc6a..b2ea0fa67afe56b243ec13c288ab239b07fb5984 100644 (file)
--- a/device.h
+++ b/device.h
@@ -71,6 +71,7 @@ enum {
        DEV_ATTR_AUTONEG,
        DEV_ATTR_GRO,
        DEV_ATTR_MASTER,
+       DEV_ATTR_EEE,
        __DEV_ATTR_MAX,
 };
 
@@ -142,6 +143,7 @@ enum {
        DEV_OPT_AUTONEG                 = (1ULL << 36),
        DEV_OPT_GRO                     = (1ULL << 37),
        DEV_OPT_MASTER                  = (1ULL << 38),
+       DEV_OPT_EEE                     = (1ULL << 39),
 };
 
 /* events broadcasted to all users of a device */
@@ -226,6 +228,7 @@ struct device_settings {
        bool autoneg;
        bool gro;
        int master_ifindex;
+       bool eee;
 };
 
 struct device_vlan_range {
index 147569df3c2297b287eb33312b5ce4dc876bd238..8efb020e78d22ef4054961b00766915f20a2821e 100644 (file)
@@ -1984,6 +1984,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)
 {
@@ -2000,6 +2017,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);