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