Added initial monitoring service for external interface
[platform/core/connectivity/wifi-mesh-manager.git] / src / mesh-peer-monitor.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2017 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 #include <glib.h>
20
21 #include "mesh.h"
22 #include "mesh-log.h"
23 #include "mesh-util.h"
24 #include "mesh-request.h"
25 #include "mesh-netlink.h"
26 #include "mesh-interface.h"
27 #include "mesh-peer-monitor.h"
28 #include "mesh-device-monitor.h"
29
30 #define MESH_MONITORING_TIME 5
31 #define MESH_MAXIMUM_BEACON_LOST_COUNT 10
32
33 static void _on_station_list_destroy(gpointer data)
34 {
35         mesh_station_info_s *info = (mesh_station_info_s*)data;
36
37         if (info) {
38                 g_free(info->bssid);
39                 g_free(info);
40         }
41 }
42 #if 0
43 static void _on_mpath_list_destroy(gpointer data)
44 {
45         mesh_mpath_info_s *info = (mesh_mpath_info_s*)data;
46
47         if (info) {
48                 g_free(info->dest_addr);
49                 g_free(info->next_hop);
50                 g_free(info->interface);
51                 g_free(info);
52         }
53 }
54 #endif
55
56 static int _get_station_info(void *pdata)
57 {
58         int is_new;
59         int ret = MESHD_ERROR_NONE;
60
61         GList *iter = NULL;
62         GList *sta_list = NULL;
63         GList *cmp_iter = NULL;
64
65         mesh_service *service = (mesh_service *)pdata;
66         mesh_interface_s *info = service->interface_info;
67
68         ret = mesh_request_get_station_info(info->mesh_interface, &sta_list);
69         if (MESHD_ERROR_NONE != ret) {
70                 MESH_LOGE("Failed to mesh_request_get_station_info");
71                 return ret;
72         }
73
74         iter = service->station_list;
75         while (iter) {
76                 mesh_station_info_s *item = (mesh_station_info_s*)iter->data;
77                 MESH_LOGD("[%s]", item->bssid);
78                 iter = g_list_next(iter);
79         }
80
81         iter = sta_list;
82         while (iter) {
83                 mesh_station_info_s *item = (mesh_station_info_s*)iter->data;
84
85                 /* Found this in th existing station infomation list. */
86                 if (item->inactive_time > item->beacon_interval * MESH_MAXIMUM_BEACON_LOST_COUNT) {
87                         /* Remove this node from station list in kernel */
88                         mesh_netlink_del_station_info(info->mesh_interface, item->bssid);
89                         /* Remove current linked list */
90                         iter = g_list_remove(iter, item);
91                         /* Send existing node disjoined */
92                         MESH_LOGE("[%s] disjoined", item->bssid);
93
94                 }
95
96                 is_new = TRUE;
97                 cmp_iter = service->station_list;
98                 while (cmp_iter) {
99                         mesh_station_info_s *cmp_item = (mesh_station_info_s*)cmp_iter->data;
100                         if (0 == strncmp(item->bssid, cmp_item->bssid, sizeof("11:22:33:44:55:66"))) {
101                                 is_new = FALSE;
102                                 break;
103                         }
104                         cmp_iter = g_list_next(cmp_iter);
105                 }
106
107                 if (is_new) {
108                         /* Send new station joined event */
109                         MESH_LOGE("[%s] joined", item->bssid);
110                 }
111
112                 iter = g_list_next(iter);
113         }
114
115         /* Clear mesh station list */
116         g_list_free_full(service->station_list, _on_station_list_destroy);
117         /* Copy new mesh station list */
118         service->station_list = sta_list;
119
120         iter = service->station_list;
121         while (iter) {
122                 mesh_station_info_s *item2 = (mesh_station_info_s*)iter->data;
123                 MESH_LOGE("[%s]", item2->bssid);
124                 iter = g_list_next(iter);
125         }
126
127         return ret;
128 }
129 #if 0
130 static gboolean _get_mpath_info(void *pdata)
131 {
132         int ret = MESHD_ERROR_NONE;
133         GVariantBuilder builder;
134         GVariant* mpath_data;
135         GList *iter = NULL;
136
137         mesh_service *service = (mesh_service *)pdata;
138         mesh_interface_s *info = service->interface_info;
139
140         /* Clear mesh path list */
141         g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
142         service->mpath_list = NULL;
143
144         ret = mesh_request_get_mpath_info(info->mesh_interface, &service->mpath_list);
145         if (MESHD_ERROR_NONE == ret) {
146         /*
147          * Example) sh-3.2# iw mesh0 mpath dump
148          * DEST ADDR         NEXT HOP          IFACE    SN      METRIC  QLEN    EXPTIME         DTIM    DRET    FLAGS
149          * 7c:dd:90:62:37:cf 7c:dd:90:62:37:cf mesh0    221     152             0               10                      100             0               0x5
150          */
151                 /* Get mesh path information and make variant data */
152                 g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
153
154                 iter = service->mpath_list;
155                 while (iter != NULL) {
156                         mesh_mpath_info_s *item = (mesh_mpath_info_s*)iter->data;
157
158                         g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
159                         g_variant_builder_add(&builder, "{sv}", "DEST_ADDR",
160                                                 g_variant_new_string(item->dest_addr));
161                         g_variant_builder_add(&builder, "{sv}", "NEXT_HOP",
162                                                 g_variant_new_string(item->next_hop));
163                         g_variant_builder_add(&builder, "{sv}", "IFACE",
164                                                 g_variant_new_string(item->interface));
165                         g_variant_builder_add(&builder, "{sv}", "SN",
166                                                 g_variant_new_uint32(item->sn));
167                         g_variant_builder_add(&builder, "{sv}", "METRIC",
168                                                 g_variant_new_uint32(item->metric));
169                         g_variant_builder_add(&builder, "{sv}", "QLEN",
170                                                 g_variant_new_uint32(item->qlen));
171                         g_variant_builder_add(&builder, "{sv}", "EXPTIME",
172                                                 g_variant_new_uint32(item->exptime));
173                         g_variant_builder_add(&builder, "{sv}", "DTIM",
174                                                 g_variant_new_uint32(item->discovery_timeout));
175                         g_variant_builder_add(&builder, "{sv}", "DRET",
176                                                 g_variant_new_byte(item->discovery_retries));
177                         g_variant_builder_add(&builder, "{sv}", "FLAGS",
178                                                 g_variant_new_byte(item->flags));
179                         g_variant_builder_close(&builder);
180
181                         iter = g_list_next(iter);
182                 }
183
184                 mpath_data = g_variant_builder_end(&builder);
185                 g_object_unref(mpath_data);
186         } else
187                 MESH_LOGE("Failed to mesh_request_get_mpath_info");
188
189         return ret;
190 }
191 #endif
192 static gboolean _on_mesh_monitor_cb(gpointer pdata)
193 {
194         int ret;
195 #ifdef USE_IOCTL_MONITOR
196         int state;
197 #else
198         bool state;
199 #endif /* USE_IOCTL_MONITOR */
200         mesh_service *service = (mesh_service *)pdata;
201         if (service) {
202                 mesh_interface_s *info = service->interface_info;
203                 if (info) {
204                         /* Exceptionally, checking external interface processes here. */
205 #ifdef USE_IOCTL_MONITOR
206                         ret = mesh_get_ethernet_cable_state(&state);
207 #else
208                         ret = mesh_interface_check_external_exists(info->external_interface, &state);
209 #endif /* USE_IOCTL_MONITOR */
210                         MESH_LOGE("Status : %d %d %d", ret, info->can_be_gate, state);
211                         if (MESHD_ERROR_NONE == ret) {
212                                 if (info->can_be_gate != state) {
213                                         /* Detect external network state (i.e. Ethernet)
214                                                 and decide to make gate enabled */
215                                         if (state)
216                                                 mesh_request_set_mesh_gate(info->bridge_interface,
217                                                                 info->mesh_interface, info->external_interface);
218                                         else
219                                                 mesh_request_unset_mesh_gate(info->bridge_interface,
220                                                                 info->mesh_interface, info->external_interface);
221
222                                         MESH_LOGD("External interface state has been changed : [%d]", state);
223                                         info->can_be_gate = state;
224                                 }
225                         }
226 #if 0
227                         _get_mpath_info(service);
228 #endif
229                         _get_station_info(service);
230                 }
231         }
232
233         return G_SOURCE_CONTINUE;
234 }
235
236 int mesh_start_monitor_service(void *pdata)
237 {
238         int ret = MESHD_ERROR_NONE;
239         mesh_service *service = (mesh_service *)pdata;
240         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
241
242         if (service->monitor_timer)
243                 mesh_stop_monitor_service(pdata);
244
245         service->monitor_timer = g_timeout_add_seconds(MESH_MONITORING_TIME, _on_mesh_monitor_cb, service);
246
247         MESH_LOGD("Peer Monitoring Service Started");
248
249         return ret;
250 }
251
252 int mesh_stop_monitor_service(void *pdata)
253 {
254         int ret = MESHD_ERROR_NONE;
255         mesh_service *service = (mesh_service *)pdata;
256         meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
257
258         if (service->monitor_timer) {
259                 g_source_remove(service->monitor_timer);
260                 service->monitor_timer = 0;
261         }
262
263         MESH_LOGD("Peer Monitoring Service Stopped");
264         return ret;
265 }