diff options
Diffstat (limited to 'src/platform')
| -rw-r--r-- | src/platform/nm-linux-platform.c | 9 | ||||
| -rw-r--r-- | src/platform/nm-netlink.h | 3 | ||||
| -rw-r--r-- | src/platform/nm-platform-utils.c | 62 | ||||
| -rw-r--r-- | src/platform/nm-platform.c | 17 | ||||
| -rw-r--r-- | src/platform/nm-platform.h | 4 | ||||
| -rw-r--r-- | src/platform/wifi/wifi-utils-nl80211.c | 42 | ||||
| -rw-r--r-- | src/platform/wifi/wifi-utils-private.h | 3 | ||||
| -rw-r--r-- | src/platform/wifi/wifi-utils.c | 9 | ||||
| -rw-r--r-- | src/platform/wifi/wifi-utils.h | 3 |
9 files changed, 151 insertions, 1 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 3a671acf..9bd662a1 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -6092,6 +6092,14 @@ wifi_indicate_addressing_running (NMPlatform *platform, int ifindex, gboolean ru wifi_utils_indicate_addressing_running (wifi_data, running); } +static gboolean +wifi_set_wake_on_wlan (NMPlatform *platform, int ifindex, + NMSettingWirelessWakeOnWLan wowl) +{ + WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE); + return wifi_utils_set_wake_on_wlan (wifi_data, wowl); +} + /*****************************************************************************/ static gboolean @@ -7230,6 +7238,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->wifi_set_powersave = wifi_set_powersave; platform_class->wifi_find_frequency = wifi_find_frequency; platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running; + platform_class->wifi_set_wake_on_wlan = wifi_set_wake_on_wlan; platform_class->mesh_get_channel = mesh_get_channel; platform_class->mesh_set_channel = mesh_set_channel; diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h index c0dc09c4..b938fa4a 100644 --- a/src/platform/nm-netlink.h +++ b/src/platform/nm-netlink.h @@ -244,6 +244,9 @@ nla_put_string (struct nl_msg *msg, int attrtype, const char *str) #define NLA_PUT_STRING(msg, attrtype, value) \ NLA_PUT(msg, attrtype, (int) strlen(value) + 1, value) +#define NLA_PUT_FLAG(msg, attrtype) \ + NLA_PUT(msg, attrtype, 0, NULL) + struct nlattr *nla_find (const struct nlattr *head, int len, int attrtype); static inline int diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c index 114bf4b3..0d224443 100644 --- a/src/platform/nm-platform-utils.c +++ b/src/platform/nm-platform-utils.c @@ -384,6 +384,40 @@ nmp_utils_ethtool_get_link_settings (int ifindex, return TRUE; } + +#define ADVERTISED_INVALID 0 +#define BASET_ALL_MODES ( ADVERTISED_10baseT_Half \ + | ADVERTISED_10baseT_Full \ + | ADVERTISED_100baseT_Half \ + | ADVERTISED_100baseT_Full \ + | ADVERTISED_1000baseT_Half \ + | ADVERTISED_1000baseT_Full \ + | ADVERTISED_10000baseT_Full ) + +static inline guint32 +get_baset_mode (guint32 speed, NMPlatformLinkDuplexType duplex) +{ + if (duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN) + return ADVERTISED_INVALID; + + if (duplex == NM_PLATFORM_LINK_DUPLEX_HALF) { + switch (speed) { + case 10: return ADVERTISED_10baseT_Half; + case 100: return ADVERTISED_100baseT_Half; + case 1000: return ADVERTISED_1000baseT_Half; + default: return ADVERTISED_INVALID; + } + } else { + switch (speed) { + case 10: return ADVERTISED_10baseT_Full; + case 100: return ADVERTISED_100baseT_Full; + case 1000: return ADVERTISED_1000baseT_Full; + case 10000: return ADVERTISED_10000baseT_Full; + default: return ADVERTISED_INVALID; + } + } +} + gboolean nmp_utils_ethtool_set_link_settings (int ifindex, gboolean autoneg, @@ -395,6 +429,8 @@ nmp_utils_ethtool_set_link_settings (int ifindex, }; g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail ( (speed && duplex != NM_PLATFORM_LINK_DUPLEX_UNKNOWN) + || (!speed && duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN), FALSE); /* retrieve first current settings */ if (!ethtool_get (ifindex, &edata)) @@ -404,7 +440,31 @@ nmp_utils_ethtool_set_link_settings (int ifindex, edata.cmd = ETHTOOL_SSET; if (autoneg) { edata.autoneg = AUTONEG_ENABLE; - edata.advertising = edata.supported; + if (!speed) + edata.advertising = edata.supported; + else { + guint32 mode; + + mode = get_baset_mode (speed, duplex); + + if (!mode) { + nm_log_trace (LOGD_PLATFORM, + "ethtool[%d]: %uBASE-T %s duplex mode cannot be advertised", + ifindex, + speed, + nm_platform_link_duplex_type_to_string (duplex)); + return FALSE; + } + if (!(edata.supported & mode)) { + nm_log_trace (LOGD_PLATFORM, + "ethtool[%d]: device does not support %uBASE-T %s duplex mode", + ifindex, + speed, + nm_platform_link_duplex_type_to_string (duplex)); + return FALSE; + } + edata.advertising = (edata.supported & ~BASET_ALL_MODES) | mode; + } } else { edata.autoneg = AUTONEG_DISABLE; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 1a94ce28..f75019e8 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -2888,6 +2888,16 @@ nm_platform_wifi_indicate_addressing_running (NMPlatform *self, int ifindex, gbo klass->wifi_indicate_addressing_running (self, ifindex, running); } +gboolean +nm_platform_wifi_set_wake_on_wlan (NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl) +{ + _CHECK_SELF (self, klass, FALSE); + + g_return_val_if_fail (ifindex > 0, FALSE); + + return klass->wifi_set_wake_on_wlan (self, ifindex, wowl); +} + guint32 nm_platform_mesh_get_channel (NMPlatform *self, int ifindex) { @@ -2995,6 +3005,13 @@ nm_platform_ethtool_get_link_settings (NMPlatform *self, int ifindex, gboolean * return nmp_utils_ethtool_get_link_settings (ifindex, out_autoneg, out_speed, out_duplex); } +NM_UTILS_LOOKUP_STR_DEFINE (nm_platform_link_duplex_type_to_string, NMPlatformLinkDuplexType, + NM_UTILS_LOOKUP_DEFAULT_WARN (NULL), + NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_LINK_DUPLEX_UNKNOWN, "unknown"), + NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_LINK_DUPLEX_FULL, "full"), + NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_LINK_DUPLEX_HALF, "half"), +); + /*****************************************************************************/ const NMDedupMultiHeadEntry * diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 2d2bfaab..866df736 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -33,6 +33,7 @@ #include "nm-core-utils.h" #include "nm-setting-vlan.h" #include "nm-setting-wired.h" +#include "nm-setting-wireless.h" #include "nm-setting-ip-tunnel.h" #define NM_TYPE_PLATFORM (nm_platform_get_type ()) @@ -867,6 +868,7 @@ typedef struct { void (*wifi_set_powersave) (NMPlatform *, int ifindex, guint32 powersave); guint32 (*wifi_find_frequency) (NMPlatform *, int ifindex, const guint32 *freqs); void (*wifi_indicate_addressing_running) (NMPlatform *, int ifindex, gboolean running); + gboolean (*wifi_set_wake_on_wlan) (NMPlatform *, int ifindex, NMSettingWirelessWakeOnWLan wowl); guint32 (*mesh_get_channel) (NMPlatform *, int ifindex); gboolean (*mesh_set_channel) (NMPlatform *, int ifindex, guint32 channel); @@ -1245,6 +1247,7 @@ void nm_platform_wifi_set_mode (NMPlatform *self, int ifindex, NM void nm_platform_wifi_set_powersave (NMPlatform *self, int ifindex, guint32 powersave); guint32 nm_platform_wifi_find_frequency (NMPlatform *self, int ifindex, const guint32 *freqs); void nm_platform_wifi_indicate_addressing_running (NMPlatform *self, int ifindex, gboolean running); +gboolean nm_platform_wifi_set_wake_on_wlan (NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl); guint32 nm_platform_mesh_get_channel (NMPlatform *self, int ifindex); gboolean nm_platform_mesh_set_channel (NMPlatform *self, int ifindex, guint32 channel); @@ -1449,6 +1452,7 @@ int nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPla gboolean nm_platform_ethtool_set_wake_on_lan (NMPlatform *self, int ifindex, NMSettingWiredWakeOnLan wol, const char *wol_password); gboolean nm_platform_ethtool_set_link_settings (NMPlatform *self, int ifindex, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex); gboolean nm_platform_ethtool_get_link_settings (NMPlatform *self, int ifindex, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex); +const char * nm_platform_link_duplex_type_to_string (NMPlatformLinkDuplexType duplex); void nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self, int ifindex, diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c index 767e23a9..6c2ff3f5 100644 --- a/src/platform/wifi/wifi-utils-nl80211.c +++ b/src/platform/wifi/wifi-utils-nl80211.c @@ -271,6 +271,47 @@ nla_put_failure: return FALSE; } +static gboolean +wifi_nl80211_set_wake_on_wlan (WifiData *data, NMSettingWirelessWakeOnWLan wowl) +{ + WifiDataNl80211 *nl80211 = (WifiDataNl80211 *) data; + nm_auto_nlmsg struct nl_msg *msg = NULL; + struct nlattr *triggers; + int err; + + if (wowl == NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE) + return TRUE; + + msg = nl80211_alloc_msg(nl80211, NL80211_CMD_SET_WOWLAN, 0); + if (!msg) + return FALSE; + + triggers = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); + + if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY)) + NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_ANY); + if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT)) + NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_DISCONNECT); + if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC)) + NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); + if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE)) + NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE); + if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST)) + NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST); + if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE)) + NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE); + if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE)) + NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE); + + nla_nest_end(msg, triggers); + + err = nl80211_send_and_recv (nl80211, msg, NULL, NULL); + return err ? FALSE : TRUE; + +nla_put_failure: + return FALSE; +} + /* @divisor: pass what value @xbm should be divided by to get dBm */ static guint32 nl80211_xbm_to_percent (gint32 xbm, guint32 divisor) @@ -846,6 +887,7 @@ wifi_nl80211_init (int ifindex) .get_mode = wifi_nl80211_get_mode, .set_mode = wifi_nl80211_set_mode, .set_powersave = wifi_nl80211_set_powersave, + .set_wake_on_wlan = wifi_nl80211_set_wake_on_wlan, .get_freq = wifi_nl80211_get_freq, .find_freq = wifi_nl80211_find_freq, .get_bssid = wifi_nl80211_get_bssid, diff --git a/src/platform/wifi/wifi-utils-private.h b/src/platform/wifi/wifi-utils-private.h index 59386514..627108cb 100644 --- a/src/platform/wifi/wifi-utils-private.h +++ b/src/platform/wifi/wifi-utils-private.h @@ -34,6 +34,9 @@ typedef struct { /* Set power saving mode on an interface */ gboolean (*set_powersave) (WifiData *data, guint32 powersave); + /* Set WakeOnWLAN mode on an interface */ + gboolean (*set_wake_on_wlan) (WifiData *data, NMSettingWirelessWakeOnWLan wowl); + /* Return current frequency in MHz (really associated BSS frequency) */ guint32 (*get_freq) (WifiData *data); diff --git a/src/platform/wifi/wifi-utils.c b/src/platform/wifi/wifi-utils.c index 8818dc9d..b3dd92ba 100644 --- a/src/platform/wifi/wifi-utils.c +++ b/src/platform/wifi/wifi-utils.c @@ -112,6 +112,15 @@ wifi_utils_set_powersave (WifiData *data, guint32 powersave) return data->klass->set_powersave ? data->klass->set_powersave (data, powersave) : TRUE; } +gboolean +wifi_utils_set_wake_on_wlan (WifiData *data, NMSettingWirelessWakeOnWLan wowl) +{ + g_return_val_if_fail (data != NULL, FALSE); + + return data->klass->set_wake_on_wlan ? + data->klass->set_wake_on_wlan (data, wowl) : FALSE; +} + guint32 wifi_utils_get_freq (WifiData *data) { diff --git a/src/platform/wifi/wifi-utils.h b/src/platform/wifi/wifi-utils.h index 8acc35fc..c69561de 100644 --- a/src/platform/wifi/wifi-utils.h +++ b/src/platform/wifi/wifi-utils.h @@ -25,6 +25,7 @@ #include <net/ethernet.h> #include "nm-dbus-interface.h" +#include "nm-setting-wireless.h" typedef struct WifiData WifiData; @@ -66,6 +67,8 @@ gboolean wifi_utils_get_wowlan (WifiData *data); gboolean wifi_utils_set_powersave (WifiData *data, guint32 powersave); +gboolean wifi_utils_set_wake_on_wlan (WifiData *data, NMSettingWirelessWakeOnWLan wowl); + /* OLPC Mesh-only functions */ guint32 wifi_utils_get_mesh_channel (WifiData *data); |