2 * Network Configuration Module
4 * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
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"
30 #define MESH_MONITORING_TIME 5
31 #define MESH_MAXIMUM_BEACON_LOST_COUNT 10
34 static void _on_station_list_destroy(gpointer data)
36 wmesh_station_info_s *info = (wmesh_station_info_s*)data;
44 static void _on_mpath_list_destroy(gpointer data)
46 wmesh_mpath_info_s *info = (wmesh_mpath_info_s*)data;
49 g_free(info->dest_addr);
50 g_free(info->next_hop);
51 g_free(info->interface);
57 static int _get_station_info(void *pdata)
60 int ret = WMESHD_ERROR_NONE;
63 GList *sta_list = NULL;
64 GList *cmp_iter = NULL;
66 wmesh_service *service = (wmesh_service *)pdata;
67 wmesh_interface_s *info = service->interface_info;
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");
75 iter = service->station_list;
77 wmesh_station_info_s *item = (wmesh_station_info_s*)iter->data;
78 WMESH_LOGD("[%s]", item->bssid);
79 iter = g_list_next(iter);
84 wmesh_station_info_s *item = (wmesh_station_info_s*)iter->data;
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);
98 cmp_iter = service->station_list;
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"))) {
105 cmp_iter = g_list_next(cmp_iter);
109 /* Send new station joined event */
110 WMESH_LOGE("[%s] joined", item->bssid);
113 iter = g_list_next(iter);
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));
122 iter = service->station_list;
124 wmesh_station_info_s *item2 = (wmesh_station_info_s*)iter->data;
125 WMESH_LOGE("[%s]", item2->bssid);
126 iter = g_list_next(iter);
133 static gboolean _get_mpath_info(void *pdata)
135 int ret = WMESHD_ERROR_NONE;
136 GVariantBuilder builder;
137 GVariant* mpath_data;
140 wmesh_service *service = (wmesh_service *)pdata;
141 wmesh_interface_s *info = service->interface_info;
143 /* Clear mesh path list */
144 g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
145 service->mpath_list = NULL;
147 ret = wmesh_request_get_mpath_info(info->mesh_interface, &service->mpath_list);
148 if (WMESHD_ERROR_NONE == ret) {
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
154 /* Get mesh path information and make variant data */
155 g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
157 iter = service->mpath_list;
158 while (iter != NULL) {
159 wmesh_mpath_info_s *item = (wmesh_mpath_info_s*)iter->data;
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);
184 iter = g_list_next(iter);
187 mpath_data = g_variant_builder_end(&builder);
188 g_object_unref(mpath_data);
190 WMESH_LOGE("Failed to wmesh_request_get_mpath_info");
195 static gboolean _on_mesh_monitor_cb(gpointer pdata)
199 wmesh_service *service = (wmesh_service *)pdata;
201 wmesh_interface_s *info = service->interface_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);
210 /* Detect external network state (i.e. Ethernet)
211 and decide to make gate enabled */
213 wmesh_request_set_mesh_gate(info->bridge_interface,
214 info->mesh_interface, info->external_interface);
216 wmesh_request_unset_mesh_gate(info->bridge_interface,
217 info->mesh_interface, info->external_interface);
219 WMESH_LOGD("External interface state has been changed : [%d]", state);
220 info->can_be_gate = state;
223 /* In error case, we call enable etheret again for OdroidU3 */
224 wmesh_gdbus_enable_ethernet_interface(service, true);
227 _get_mpath_info(service);
229 ret = _get_station_info(service);
230 if (WMESHD_ERROR_NONE != ret) {
231 WMESH_LOGW("Erro in get station info (%d)", ret);
236 return G_SOURCE_CONTINUE;
240 int wmesh_start_monitor_service(void *pdata)
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);
246 if (service->monitor_timer)
247 wmesh_stop_monitor_service(pdata); /* LCOV_EXCL_LINE */
249 service->monitor_timer = g_timeout_add_seconds(MESH_MONITORING_TIME,
250 _on_mesh_monitor_cb, service);
252 WMESH_LOGD("Peer Monitoring Service Started");
257 int wmesh_stop_monitor_service(void *pdata)
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);
263 if (service->monitor_timer) {
264 g_source_remove(service->monitor_timer);
265 service->monitor_timer = 0;
268 WMESH_LOGD("Peer Monitoring Service Stopped");