Modify send_arp
[platform/core/connectivity/net-config.git] / src / network-statistics.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <vconf.h>
22 #include <vconf-keys.h>
23
24 #include "log.h"
25 #include "util.h"
26 #include "netsupplicant.h"
27 #include "network-statistics.h"
28
29 #include "generated-code.h"
30
31 #define NETCONFIG_PROCDEV                                       "/proc/net/dev"
32
33 static Network_statistics *netconfigstatistics = NULL;
34
35 gboolean netconfig_wifi_get_bytes_statistics(guint64 *tx, guint64 *rx)
36 {
37         gboolean ret = FALSE;
38         FILE *fp;
39         gchar buf[1024];
40         gchar *p_ifname = NULL, *p_entry = NULL;
41
42         *tx = 0;
43         *rx = 0;
44
45         fp = fopen(NETCONFIG_PROCDEV, "r");
46         if (fp == NULL) {
47                 ERR("Failed to open %s", NETCONFIG_PROCDEV);
48                 return FALSE;
49         }
50
51         /* skip the first and second line */
52         if (fgets(buf, sizeof(buf), fp) == NULL ||
53                         fgets(buf, sizeof(buf), fp) == NULL)
54                 goto endline;
55
56         while (fgets(buf, sizeof(buf), fp)) {
57                 long long unsigned int llval;
58                 gulong lval;
59
60                 p_ifname = buf;
61                 while (*p_ifname == ' ') p_ifname++;
62                 p_entry = strchr(p_ifname, ':');
63                 if (p_entry != NULL) {
64                         *p_entry++ = '\0';
65
66                 if (g_strcmp0(p_ifname, WIFI_IFNAME) != 0)
67                         continue;
68
69                 /* read interface statistics */
70                 sscanf(p_entry,
71                                 "%llu %llu %lu %lu %lu %lu %lu %lu "
72                                 "%llu %llu %lu %lu %lu %lu %lu %lu",
73                                 (long long unsigned int *)rx, /* rx bytes */
74                                 &llval,         /* rx packet */
75                                 &lval,          /* rx errors */
76                                 &lval,          /* rx dropped */
77                                 &lval,          /* rx fifo errors */
78                                 &lval,          /* rx frame errors */
79                                 &lval,          /* rx compressed */
80                                 &lval,          /* rx multicast */
81
82                                 (long long unsigned int *)tx, /* tx bytes */
83                                 &llval,         /* tx packet */
84                                 &lval,          /* tx errors */
85                                 &lval,          /* tx dropped */
86                                 &lval,          /* tx fifo errors */
87                                 &lval,          /* collisions */
88                                 &lval,          /* tx carrier errors */
89                                 &lval           /* tx compressed */
90                                 );
91                 } else {
92                         ERR("No matched Iface name in proc file");
93                 }
94                 ret = TRUE;
95                 break;
96         }
97
98 endline:
99         fclose(fp);
100         return ret;
101 }
102
103 static gboolean handle_get_wifi_total_tx_bytes(
104                 Network_statistics *object,
105                 GDBusMethodInvocation *context)
106 {
107         guint64 tx = 0, rx = 0;
108         guint64 tx_bytes = 0;
109         guint64 total_bytes = 0;
110         int val = 0;
111
112         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, &val);
113         tx_bytes = (guint64)val;
114
115         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
116                 total_bytes = tx + tx_bytes;
117         else
118                 total_bytes = tx_bytes;
119
120         network_statistics_complete_get_wifi_total_tx_bytes(object, context, total_bytes);
121         return TRUE;
122 }
123
124 static gboolean handle_get_wifi_total_rx_bytes(
125                 Network_statistics *object,
126                 GDBusMethodInvocation *context)
127 {
128         guint64 tx = 0, rx = 0;
129         guint64 rx_bytes = 0;
130         guint64 total_bytes = 0;
131         int val = 0;
132
133         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, &val);
134         rx_bytes = (guint64)val;
135
136         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
137                 total_bytes = rx + rx_bytes;
138         else
139                 total_bytes = rx_bytes;
140
141         network_statistics_complete_get_wifi_total_rx_bytes(object, context, total_bytes);
142         return TRUE;
143 }
144
145 static gboolean handle_get_wifi_last_tx_bytes(
146                 Network_statistics *object,
147                 GDBusMethodInvocation *context)
148 {
149         guint64 tx = 0, rx = 0;
150         guint64 tx_bytes = 0;
151         guint64 last_bytes = 0;
152         int val = 0;
153
154         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, &val);
155         tx_bytes = (guint64)val;
156
157         if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
158                 last_bytes = tx_bytes;
159                 network_statistics_complete_get_wifi_last_tx_bytes(object, context, last_bytes);
160                 return TRUE;
161         }
162
163         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
164                 last_bytes = tx < tx_bytes ? 0 : tx - tx_bytes;
165         else
166                 last_bytes = tx_bytes;
167
168         network_statistics_complete_get_wifi_last_tx_bytes(object, context, last_bytes);
169         return TRUE;
170 }
171
172 static gboolean handle_get_wifi_last_rx_bytes(
173                 Network_statistics *object,
174                 GDBusMethodInvocation *context)
175 {
176         guint64 tx = 0, rx = 0;
177         guint64 rx_bytes = 0;
178         guint64 last_bytes = 0;
179         int val = 0;
180
181         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, &val);
182         rx_bytes = (guint64)val;
183
184         if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
185                 last_bytes = rx_bytes;
186                 network_statistics_complete_get_wifi_last_rx_bytes(object, context, last_bytes);
187                 return TRUE;
188         }
189
190         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
191                 last_bytes = rx < rx_bytes ? 0 : rx - rx_bytes;
192         else
193                 last_bytes = rx_bytes;
194
195         network_statistics_complete_get_wifi_last_rx_bytes(object, context, last_bytes);
196         return TRUE;
197 }
198
199 static gboolean handle_reset_cellular_total_tx_bytes(
200                 Network_statistics *object,
201                 GDBusMethodInvocation *context)
202 {
203         netconfig_set_vconf_int(VCONFKEY_NETWORK_CELLULAR_PKT_TOTAL_SNT, 0);
204         network_statistics_complete_reset_cellular_total_tx_bytes(object, context);
205         return TRUE;
206 }
207
208 static gboolean handle_reset_cellular_total_rx_bytes(
209                 Network_statistics *object,
210                 GDBusMethodInvocation *context)
211 {
212         netconfig_set_vconf_int(VCONFKEY_NETWORK_CELLULAR_PKT_TOTAL_RCV, 0);
213         network_statistics_complete_reset_cellular_total_rx_bytes(object, context);
214         return TRUE;
215 }
216
217 static gboolean handle_reset_cellular_last_tx_bytes(
218                 Network_statistics *object,
219                 GDBusMethodInvocation *context)
220 {
221         netconfig_set_vconf_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_SNT, 0);
222         network_statistics_complete_reset_cellular_last_tx_bytes(object, context);
223         return TRUE;
224 }
225
226 static gboolean handle_reset_cellular_last_rx_bytes(
227                 Network_statistics *object,
228                 GDBusMethodInvocation *context)
229 {
230         netconfig_set_vconf_int(VCONFKEY_NETWORK_CELLULAR_PKT_LAST_RCV, 0);
231         network_statistics_complete_reset_cellular_last_rx_bytes(object, context);
232         return TRUE;
233 }
234
235 static gboolean handle_reset_wifi_total_tx_bytes(
236                 Network_statistics *object,
237                 GDBusMethodInvocation *context)
238 {
239         guint64 tx = 0, rx = 0;
240
241         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
242                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, -(int)tx);
243         else
244                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, 0);
245
246         network_statistics_complete_reset_wifi_total_tx_bytes(object, context);
247
248         return TRUE;
249 }
250
251 static gboolean handle_reset_wifi_total_rx_bytes(
252                 Network_statistics *object,
253                 GDBusMethodInvocation *context)
254 {
255         guint64 tx = 0, rx = 0;
256
257         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
258                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, -(int)rx);
259         else
260                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, 0);
261
262         network_statistics_complete_reset_wifi_total_rx_bytes(object, context);
263         return TRUE;
264 }
265
266 static gboolean handle_reset_wifi_last_tx_bytes(
267                 Network_statistics *object,
268                 GDBusMethodInvocation *context)
269 {
270         guint64 tx = 0, rx = 0;
271
272         if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
273                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, 0);
274                 network_statistics_complete_reset_wifi_last_tx_bytes(object, context);
275                 return TRUE;
276         }
277
278         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
279                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, (int)tx);
280         else
281                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, 0);
282
283         network_statistics_complete_reset_wifi_last_tx_bytes(object, context);
284
285         return TRUE;
286 }
287
288 static gboolean handle_reset_wifi_last_rx_bytes(
289                 Network_statistics *object,
290                 GDBusMethodInvocation *context)
291 {
292         guint64 tx = 0, rx = 0;
293
294         if (wifi_state_get_service_state() != NETCONFIG_WIFI_CONNECTED) {
295                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, 0);
296                 network_statistics_complete_reset_wifi_last_rx_bytes(object, context);
297                 return TRUE;
298         }
299
300         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) == TRUE)
301                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, (int)rx);
302         else
303                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, 0);
304
305         network_statistics_complete_reset_wifi_last_rx_bytes(object, context);
306
307         return TRUE;
308 }
309
310 void netconfig_wifi_statistics_update_powered_off(void)
311 {
312         guint64 cur_tx = 0, cur_rx = 0;
313         guint64 prev_tx = 0, prev_rx = 0;
314         guint64 total_tx = 0, total_rx = 0;
315         int val = 0;
316
317         if (netconfig_wifi_get_bytes_statistics(&cur_tx, &cur_rx) != TRUE)
318                 return;
319
320         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, &val);
321         prev_tx = (guint64)val;
322
323         netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, &val);
324         prev_rx = (guint64)val;
325
326         total_tx = prev_tx + cur_tx;
327         total_rx = prev_rx + cur_rx;
328
329         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_SNT, (int)total_tx);
330         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_TOTAL_RCV, (int)total_rx);
331 }
332
333 static void wifi_statistics_update_state(wifi_service_state_e state, void *user_data)
334 {
335         guint64 tx = 0, rx = 0;
336         guint64 last_tx = 0, last_rx = 0;
337         int val = 0;
338         static wifi_service_state_e prev_state = NETCONFIG_WIFI_UNKNOWN;
339
340         if (prev_state == NETCONFIG_WIFI_UNKNOWN) {
341                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, 0);
342                 netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, 0);
343
344                 prev_state = NETCONFIG_WIFI_IDLE;
345                 return;
346         }
347
348         if (netconfig_wifi_get_bytes_statistics(&tx, &rx) != TRUE)
349                 return;
350
351         if (state == NETCONFIG_WIFI_CONNECTED) {
352                 last_tx = tx;
353                 last_rx = rx;
354         } else {
355                 if (prev_state != NETCONFIG_WIFI_CONNECTED)
356                         return;
357
358                 netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, &val);
359                 last_tx = (guint64)val;
360
361                 netconfig_vconf_get_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, &val);
362                 last_rx = (guint64)val;
363
364                 last_tx = tx < last_tx ? 0 : tx - last_tx;
365                 last_rx = rx < last_rx ? 0 : rx - last_rx;
366         }
367
368         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_SNT, (int)last_tx);
369         netconfig_set_vconf_int(VCONFKEY_NETWORK_WIFI_PKT_LAST_RCV, (int)last_rx);
370
371         prev_state = state;
372 }
373
374 static wifi_state_notifier state_notifier = {
375                 .wifi_state_changed = wifi_statistics_update_state,
376                 .user_data = NULL,
377 };
378
379 void statistics_object_create_and_init(void)
380 {
381         DBG("Creating statistics object");
382         GDBusInterfaceSkeleton *interface_statistics = NULL;
383         GDBusConnection *connection = NULL;
384         GDBusObjectManagerServer *server = netdbus_get_statistics_manager();
385         if (server == NULL)
386                 return;
387
388         connection = netdbus_get_connection();
389         g_dbus_object_manager_server_set_connection(server, connection);
390
391         /*Interface netconfig.network_statistics*/
392         netconfigstatistics = network_statistics_skeleton_new();
393
394         interface_statistics = G_DBUS_INTERFACE_SKELETON(netconfigstatistics);
395         g_signal_connect(netconfigstatistics, "handle-get-wifi-last-rx-bytes",
396                                 G_CALLBACK(handle_get_wifi_last_rx_bytes), NULL);
397         g_signal_connect(netconfigstatistics, "handle-get-wifi-last-tx-bytes",
398                                 G_CALLBACK(handle_get_wifi_last_tx_bytes), NULL);
399         g_signal_connect(netconfigstatistics, "handle-get-wifi-total-rx-bytes",
400                                 G_CALLBACK(handle_get_wifi_total_rx_bytes), NULL);
401         g_signal_connect(netconfigstatistics, "handle-get-wifi-total-tx-bytes",
402                                 G_CALLBACK(handle_get_wifi_total_tx_bytes), NULL);
403         g_signal_connect(netconfigstatistics, "handle-reset-cellular-last-rx-bytes",
404                                 G_CALLBACK(handle_reset_cellular_last_rx_bytes), NULL);
405         g_signal_connect(netconfigstatistics, "handle-reset-cellular-last-tx-bytes",
406                                 G_CALLBACK(handle_reset_cellular_last_tx_bytes), NULL);
407         g_signal_connect(netconfigstatistics, "handle-reset-cellular-total-rx-bytes",
408                                 G_CALLBACK(handle_reset_cellular_total_rx_bytes), NULL);
409         g_signal_connect(netconfigstatistics, "handle-reset-cellular-total-tx-bytes",
410                                 G_CALLBACK(handle_reset_cellular_total_tx_bytes), NULL);
411         g_signal_connect(netconfigstatistics, "handle-reset-wifi-last-rx-bytes",
412                                 G_CALLBACK(handle_reset_wifi_last_rx_bytes), NULL);
413         g_signal_connect(netconfigstatistics, "handle-reset-wifi-last-tx-bytes",
414                                 G_CALLBACK(handle_reset_wifi_last_tx_bytes), NULL);
415         g_signal_connect(netconfigstatistics, "handle-reset-wifi-total-rx-bytes",
416                                 G_CALLBACK(handle_reset_wifi_total_rx_bytes), NULL);
417         g_signal_connect(netconfigstatistics, "handle-reset-wifi-total-tx-bytes",
418                                 G_CALLBACK(handle_reset_wifi_total_tx_bytes), NULL);
419
420         if (!g_dbus_interface_skeleton_export(interface_statistics, connection,
421                         NETCONFIG_NETWORK_STATISTICS_PATH, NULL)) {
422                 ERR("Export with path failed");
423         }
424
425         wifi_statistics_update_state(NETCONFIG_WIFI_IDLE, NULL);
426         wifi_state_notifier_register(&state_notifier);
427
428         return;
429 }
430
431 void statistics_object_deinit(void)
432 {
433         g_object_unref(netconfigstatistics);
434 }