Merge lp:~cyphermox/powerd/wifi-powersave into lp:powerd

Proposed by Mathieu Trudel-Lapierre
Status: Rejected
Rejected by: Mathieu Trudel-Lapierre
Proposed branch: lp:~cyphermox/powerd/wifi-powersave
Merge into: lp:powerd
Diff against target: 445 lines (+372/-0)
4 files modified
CMakeLists.txt (+5/-0)
src/powerd-netlink.c (+281/-0)
src/powerd-netlink.h (+77/-0)
src/powerd.cpp (+9/-0)
To merge this branch: bzr merge lp:~cyphermox/powerd/wifi-powersave
Reviewer Review Type Date Requested Status
Mathieu Trudel-Lapierre Disapprove
PS Jenkins bot continuous-integration Needs Fixing
Review via email: mp+239403@code.launchpad.net

Commit message

Use netlink to set up powersave for wireless devices on startup.

Description of the change

Investigating the use of netlink to set up powersave for wireless devices.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Mathieu Trudel-Lapierre (cyphermox) wrote :

Abandoning; this code would not support the module removal and readding that happens when flight mode is toggled.

review: Disapprove

Unmerged revisions

145. By Mathieu Trudel-Lapierre

Implement setting powersave via netlink on startup

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-09-30 20:52:33 +0000
3+++ CMakeLists.txt 2014-10-23 16:07:31 +0000
4@@ -26,6 +26,7 @@
5 pkg_check_modules(GIO-UNIX gio-unix-2.0)
6 pkg_check_modules(UPOWER_GLIB upower-glib)
7 pkg_check_modules(UUID uuid)
8+pkg_check_modules(LIBNL3 libnl-3.0 libnl-genl-3.0)
9
10 set(POWERD_GENERATED_SOURCES
11 ${GDBUS_NAME}.c
12@@ -50,6 +51,7 @@
13 src/log.c
14 src/power-request.c
15 src/power-source.c
16+ src/powerd-netlink.c
17 src/powerd-client.c
18 src/powerd-object.c
19 src/powerd-sensors.cpp
20@@ -67,6 +69,7 @@
21 ${GIO-UNIX_LIBRARY_DIRS}
22 ${UPOWER_GLIB_LIBRARY_DIRS}
23 ${UUID_LIBRARY_DIRS}
24+ ${LIBNL3_LIBRARY_DIRS}
25 )
26
27 include_directories(
28@@ -76,6 +79,7 @@
29 ${GIO-UNIX_INCLUDE_DIRS}
30 ${UPOWER_GLIB_INCLUDE_DIRS}
31 ${UUID_INCLUDE_DIRS}
32+ ${LIBNL3_INCLUDE_DIRS}
33 ${PROJECT_SOURCE_DIR}/libsuspend
34 ${CMAKE_CURRENT_BINARY_DIR}/src
35 )
36@@ -111,6 +115,7 @@
37 "-lhardware"
38 ${UPOWER_GLIB_LIBRARIES}
39 ${UUID_LIBRARIES}
40+ ${LIBNL3_LIBRARIES}
41 )
42
43 install(
44
45=== added file 'src/powerd-netlink.c'
46--- src/powerd-netlink.c 1970-01-01 00:00:00 +0000
47+++ src/powerd-netlink.c 2014-10-23 16:07:31 +0000
48@@ -0,0 +1,281 @@
49+/*
50+ * Copyright 2013 Canonical Ltd.
51+ *
52+ * This file is part of powerd.
53+ *
54+ * powerd is free software; you can redistribute it and/or modify
55+ * it under the terms of the GNU General Public License as published by
56+ * the Free Software Foundation; version 3.
57+ *
58+ * powerd is distributed in the hope that it will be useful,
59+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
60+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61+ * GNU General Public License for more details.
62+ *
63+ * You should have received a copy of the GNU General Public License
64+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
65+ */
66+
67+#include <glib.h>
68+#include <glib-object.h>
69+#include <gio/gio.h>
70+#include <inttypes.h>
71+#include <string.h>
72+#include <stdio.h>
73+#include <errno.h>
74+#include <sys/types.h>
75+#include <sys/ioctl.h>
76+
77+#include <ifaddrs.h>
78+#include <net/if.h>
79+#include <linux/nl80211.h>
80+#include <wireless.h>
81+
82+#include <netlink/netlink.h>
83+#include <netlink/genl/genl.h>
84+#include <netlink/genl/family.h>
85+#include <netlink/genl/ctrl.h>
86+#include <netlink/msg.h>
87+#include <netlink/attr.h>
88+
89+#include "powerd-netlink.h"
90+
91+struct _PowerdNetlinkPrivate {
92+ struct nl_sock *socket;
93+ struct nl_cb *cb;
94+ gboolean is_generic;
95+ char *type;
96+ int type_id;
97+ gboolean valid;
98+};
99+
100+static void powerd_netlink_class_init (PowerdNetlinkClass * klass);
101+static void powerd_netlink_init (PowerdNetlink * self);
102+static void powerd_netlink_dispose (GObject * object);
103+static void powerd_netlink_finalize (GObject * object);
104+
105+G_DEFINE_TYPE (PowerdNetlink, powerd_netlink, G_TYPE_OBJECT);
106+
107+#define POWERD_NETLINK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), POWERD_TYPE_NETLINK, PowerdNetlinkPrivate))
108+
109+static struct nl_cb *
110+set_socket_cb (struct nl_sock *sock, int cb_level)
111+{
112+ struct nl_cb *cb;
113+
114+ cb = nl_cb_alloc(cb_level);
115+ nl_socket_set_cb(sock, cb);
116+
117+ return cb;
118+}
119+
120+static struct nl_sock *
121+allocate_netlink_socket()
122+{
123+ struct nl_sock *sock;
124+
125+ sock = nl_socket_alloc();
126+ if (!sock) {
127+ g_warning ("Failed to allocate netlink socket");
128+ return NULL;
129+ }
130+
131+ nl_socket_set_buffer_size(sock, 8192, 8192);
132+
133+ return sock;
134+}
135+
136+static gboolean
137+get_generic_netlink(PowerdNetlink *self)
138+{
139+ PowerdNetlinkPrivate *priv = POWERD_NETLINK_GET_PRIVATE(self);
140+
141+ g_return_val_if_fail (priv->socket != NULL, FALSE);
142+
143+ if (genl_connect(priv->socket) < 0) {
144+ g_warning ("Could not make netlink socket generic");
145+ return FALSE;
146+ }
147+
148+ return TRUE;
149+}
150+
151+/* Instance */
152+static void
153+powerd_netlink_init (PowerdNetlink *self)
154+{
155+ self->priv = POWERD_NETLINK_GET_PRIVATE(self);
156+ self->priv->socket = allocate_netlink_socket();
157+ self->priv->is_generic = FALSE;
158+ self->priv->type = NULL;
159+ self->priv->valid = self->priv->socket != NULL;
160+
161+ return;
162+}
163+
164+/* Class Init */
165+static void
166+powerd_netlink_class_init (PowerdNetlinkClass *self)
167+{
168+ GObjectClass *object_class = G_OBJECT_CLASS (self);
169+
170+ g_type_class_add_private (self, sizeof (PowerdNetlinkPrivate));
171+ object_class->dispose = powerd_netlink_dispose;
172+ object_class->finalize = powerd_netlink_finalize;
173+
174+ return;
175+}
176+
177+/* Clean up references */
178+static void
179+powerd_netlink_dispose (GObject *object)
180+{
181+ PowerdNetlink * self = POWERD_NETLINK(object);
182+ PowerdNetlinkPrivate *priv = POWERD_NETLINK_GET_PRIVATE (self);
183+
184+ if (priv->type) {
185+ g_free (priv->type);
186+ priv->type = NULL;
187+ }
188+
189+ nl_cb_put(priv->cb);
190+ nl_socket_free(priv->socket);
191+
192+ priv->valid = FALSE;
193+
194+ return;
195+}
196+
197+static void
198+powerd_netlink_finalize (GObject *object)
199+{
200+ return;
201+}
202+
203+static int
204+get_powersave_val (gboolean powersave)
205+{
206+ if (powersave)
207+ return NL80211_PS_ENABLED;
208+ else
209+ return NL80211_PS_DISABLED;
210+}
211+
212+void
213+powerd_netlink_set_cb (PowerdNetlink *self, int cb)
214+{
215+ PowerdNetlinkPrivate *priv = POWERD_NETLINK_GET_PRIVATE (self);
216+
217+ g_return_val_if_fail (priv->valid, FALSE);
218+
219+ set_socket_cb (priv->socket, cb);
220+}
221+
222+void
223+powerd_netlink_make_generic (PowerdNetlink *self)
224+{
225+ PowerdNetlinkPrivate *priv = POWERD_NETLINK_GET_PRIVATE (self);
226+
227+ g_return_val_if_fail (!priv->is_generic, TRUE);
228+ g_return_val_if_fail (priv->valid, FALSE);
229+
230+ priv->valid = get_generic_netlink (self);
231+ if (priv->valid)
232+ priv->is_generic = TRUE;
233+}
234+
235+gboolean
236+powerd_netlink_set_type (PowerdNetlink *self, char *type)
237+{
238+ PowerdNetlinkPrivate *priv = POWERD_NETLINK_GET_PRIVATE (self);
239+
240+ g_return_val_if_fail (priv->is_generic, FALSE);
241+ g_return_val_if_fail (priv->valid, FALSE);
242+
243+ priv->type = g_strdup (type);
244+ priv->type_id = genl_ctrl_resolve(priv->socket, type);
245+
246+ return priv->type_id >= 0;
247+}
248+
249+gboolean
250+powerd_netlink_set_device_powersave(PowerdNetlink *self, char *devname, gboolean powersave)
251+{
252+ PowerdNetlinkPrivate *priv = POWERD_NETLINK_GET_PRIVATE (self);
253+ struct nl_msg *msg;
254+ int devidx;
255+ gboolean result = FALSE;
256+ int iferr = 0;
257+
258+ /* Fail now if we're not dealing with a valid nl80211 netlink */
259+ g_return_val_if_fail (priv->valid, FALSE);
260+ g_return_val_if_fail (!g_strcmp0 (priv->type, "nl80211"), FALSE);
261+
262+ devidx = if_nametoindex(devname);
263+
264+ msg = nlmsg_alloc();
265+ genlmsg_put(msg, 0, 0, priv->type_id, 0, 0, NL80211_CMD_SET_POWER_SAVE, 0);
266+
267+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx);
268+ NLA_PUT_U32(msg, NL80211_ATTR_PS_STATE, get_powersave_val(powersave));
269+
270+ iferr = nl_send_auto_complete(priv->socket, msg);
271+ if (iferr >= 0)
272+ result = TRUE;
273+
274+ nlmsg_free(msg);
275+
276+nla_put_failure:
277+ return result;
278+}
279+
280+gboolean
281+powerd_netlink_set_wifi_powersave(PowerdNetlink *self, gboolean powersave)
282+{
283+ PowerdNetlinkPrivate *priv = POWERD_NETLINK_GET_PRIVATE (self);
284+ struct ifaddrs *ifa, *ifaddr;
285+ gboolean result = FALSE;
286+ int skfd;
287+ int n, errcnt = 0;
288+
289+ /* Fail now if we're not dealing with a valid nl80211 netlink */
290+ g_return_val_if_fail (priv->valid, FALSE);
291+ g_return_val_if_fail (!g_strcmp0 (priv->type, "nl80211"), FALSE);
292+
293+ skfd = socket(AF_INET, SOCK_DGRAM, 0);
294+ if (getifaddrs(&ifaddr) < 0) {
295+ g_warning ("Could not get network interfaces");
296+ goto out;
297+ }
298+
299+ for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
300+ struct ifreq pwrq;
301+
302+ if (ifa->ifa_addr == NULL)
303+ continue;
304+
305+ if (ifa->ifa_addr->sa_family != AF_INET)
306+ continue;
307+
308+ strncpy(pwrq.ifr_name, ifa->ifa_name, IFNAMSIZ);
309+ if (ioctl(skfd, SIOCGIWNAME, &pwrq) < 0) {
310+ /* We can't set wifi powersave if the device isn't
311+ * wifi...
312+ */
313+ continue;
314+ }
315+
316+ if (!powerd_netlink_set_device_powersave (self,
317+ ifa->ifa_name,
318+ powersave))
319+ errcnt++;
320+ }
321+
322+ if (errcnt == 0)
323+ result = TRUE;
324+
325+out:
326+ freeifaddrs(ifaddr);
327+ return result;
328+}
329+
330
331=== added file 'src/powerd-netlink.h'
332--- src/powerd-netlink.h 1970-01-01 00:00:00 +0000
333+++ src/powerd-netlink.h 2014-10-23 16:07:31 +0000
334@@ -0,0 +1,77 @@
335+/*
336+ * Copyright 2013 Canonical Ltd.
337+ *
338+ * This file is part of powerd.
339+ *
340+ * powerd is free software; you can redistribute it and/or modify
341+ * it under the terms of the GNU General Public License as published by
342+ * the Free Software Foundation; version 3.
343+ *
344+ * powerd is distributed in the hope that it will be useful,
345+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
346+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
347+ * GNU General Public License for more details.
348+ *
349+ * You should have received a copy of the GNU General Public License
350+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
351+ */
352+
353+#ifndef __POWERD_NETLINK_H__
354+#define __POWERD_NETLINK_H__
355+
356+#include <netlink/netlink.h>
357+
358+#include <glib.h>
359+#include <glib-object.h>
360+#include <gio/gio.h>
361+
362+#ifdef __cplusplus
363+extern "C" {
364+#endif
365+
366+G_BEGIN_DECLS
367+
368+#define POWERD_TYPE_NETLINK (powerd_netlink_get_type ())
369+#define POWERD_NETLINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), POWERD_TYPE_NETLINK, PowerdNetlink))
370+#define POWERD_IS_NETLINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POWERD_TYPE_NETLINK))
371+#define POWERD_NETLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), POWERD_TYPE_NETLINK, PowerdNetlinkClass))
372+#define POWERD_IS_NETLINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), POWERD_TYPE_NETLINK))
373+#define POWERD_NETLINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), POWERD_TYPE_NETLINK, PowerdNetlinkClass))
374+
375+struct _PowerdNetlinkPrivate;
376+
377+typedef struct _PowerdNetlink PowerdNetlink;
378+typedef struct _PowerdNetlinkClass PowerdNetlinkClass;
379+typedef struct _PowerdNetlinkPrivate PowerdNetlinkPrivate;
380+
381+struct _PowerdNetlinkClass {
382+ GObjectClass parent_class;
383+};
384+
385+struct _PowerdNetlink {
386+ GObject parent;
387+ PowerdNetlinkPrivate * priv;
388+};
389+
390+GType powerd_netlink_get_type (void);
391+
392+void powerd_netlink_set_cb (PowerdNetlink *self, int cb);
393+
394+void powerd_netlink_make_generic (PowerdNetlink *self);
395+
396+gboolean powerd_netlink_set_type (PowerdNetlink *self, char *type);
397+
398+gboolean powerd_netlink_set_device_powersave (PowerdNetlink *self,
399+ char *devname,
400+ gboolean powersave);
401+
402+gboolean powerd_netlink_set_wifi_powersave (PowerdNetlink *self,
403+ gboolean powersave);
404+
405+G_END_DECLS
406+
407+#ifdef __cplusplus
408+}
409+#endif
410+
411+#endif
412
413=== modified file 'src/powerd.cpp'
414--- src/powerd.cpp 2014-09-30 14:50:08 +0000
415+++ src/powerd.cpp 2014-10-23 16:07:31 +0000
416@@ -38,6 +38,7 @@
417 #include <gio/gio.h>
418 #include "powerd-internal.h"
419 #include "powerd-object.h"
420+#include "powerd-netlink.h"
421 #include "powerd-dbus.h"
422 #include "powerd-sensors.h"
423 #include "device-config.h"
424@@ -95,6 +96,8 @@
425 static GDBusProxy *g_ofono_proxy;
426 static GDBusProxy *g_unity_proxy;
427
428+static PowerdNetlink *powerd_netlink;
429+
430 static struct power_module* _power_module;
431
432 static void
433@@ -402,6 +405,12 @@
434 /* Init this first, data is used by other inits */
435 device_config_init();
436
437+ powerd_netlink = POWERD_NETLINK (g_object_new (POWERD_TYPE_NETLINK, NULL));
438+ powerd_netlink_set_cb (powerd_netlink, 0);
439+ powerd_netlink_make_generic (powerd_netlink);
440+ powerd_netlink_set_type (powerd_netlink, "nl80211");
441+ powerd_netlink_set_wifi_powersave (powerd_netlink, TRUE);
442+
443 libsuspend_init(0);
444 powerd_info("libsuspend: detect module: %s.", libsuspend_getname());
445 powerd_stats_init();

Subscribers

People subscribed via source and target branches