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
33 static void _on_station_list_destroy(gpointer data)
35 wmesh_station_info_s *info = (wmesh_station_info_s*)data;
43 static void _on_mpath_list_destroy(gpointer data)
45 wmesh_mpath_info_s *info = (wmesh_mpath_info_s*)data;
48 g_free(info->dest_addr);
49 g_free(info->next_hop);
50 g_free(info->interface);
56 static int _get_station_info(void *pdata)
59 int ret = WMESHD_ERROR_NONE;
62 GList *sta_list = NULL;
63 GList *cmp_iter = NULL;
65 wmesh_service *service = (wmesh_service *)pdata;
66 wmesh_interface_s *info = service->interface_info;
68 ret = wmesh_request_get_station_info(info->mesh_interface, &sta_list);
69 if (WMESHD_ERROR_NONE != ret) {
70 WMESH_LOGE("Failed to wmesh_request_get_station_info");
74 iter = service->station_list;
76 wmesh_station_info_s *item = (wmesh_station_info_s*)iter->data;
77 WMESH_LOGD("[%s]", item->bssid);
78 iter = g_list_next(iter);
83 wmesh_station_info_s *item = (wmesh_station_info_s*)iter->data;
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 wmesh_gdbus_mesh_remove_peer(service, item->bssid);
89 /* Remove current linked list */
90 sta_list = g_list_remove(iter, item);
91 /* Send existing node disjoined */
92 WMESH_LOGE("[%s] disjoined", item->bssid);
97 cmp_iter = service->station_list;
99 wmesh_station_info_s *cmp_item = (wmesh_station_info_s*)cmp_iter->data;
100 if (0 == strncmp(item->bssid, cmp_item->bssid, sizeof("11:22:33:44:55:66"))) {
104 cmp_iter = g_list_next(cmp_iter);
108 /* Send new station joined event */
109 WMESH_LOGE("[%s] joined", item->bssid);
112 iter = g_list_next(iter);
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 WMESH_LOGD("station_list length %d", g_list_length(service->station_list));
121 iter = service->station_list;
123 wmesh_station_info_s *item2 = (wmesh_station_info_s*)iter->data;
124 WMESH_LOGE("[%s]", item2->bssid);
125 iter = g_list_next(iter);
131 static gboolean _get_mpath_info(void *pdata)
133 int ret = WMESHD_ERROR_NONE;
134 GVariantBuilder builder;
135 GVariant* mpath_data;
138 wmesh_service *service = (wmesh_service *)pdata;
139 wmesh_interface_s *info = service->interface_info;
141 /* Clear mesh path list */
142 g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
143 service->mpath_list = NULL;
145 ret = wmesh_request_get_mpath_info(info->mesh_interface, &service->mpath_list);
146 if (WMESHD_ERROR_NONE == ret) {
148 * Example) sh-3.2# iw mesh0 mpath dump
149 * DEST ADDR NEXT HOP IFACE SN METRIC QLEN EXPTIME DTIM DRET FLAGS
150 * 7c:dd:90:62:37:cf 7c:dd:90:62:37:cf mesh0 221 152 0 10 100 0 0x5
152 /* Get mesh path information and make variant data */
153 g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
155 iter = service->mpath_list;
156 while (iter != NULL) {
157 wmesh_mpath_info_s *item = (wmesh_mpath_info_s*)iter->data;
159 g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
160 g_variant_builder_add(&builder, "{sv}", "DEST_ADDR",
161 g_variant_new_string(item->dest_addr));
162 g_variant_builder_add(&builder, "{sv}", "NEXT_HOP",
163 g_variant_new_string(item->next_hop));
164 g_variant_builder_add(&builder, "{sv}", "IFACE",
165 g_variant_new_string(item->interface));
166 g_variant_builder_add(&builder, "{sv}", "SN",
167 g_variant_new_uint32(item->sn));
168 g_variant_builder_add(&builder, "{sv}", "METRIC",
169 g_variant_new_uint32(item->metric));
170 g_variant_builder_add(&builder, "{sv}", "QLEN",
171 g_variant_new_uint32(item->qlen));
172 g_variant_builder_add(&builder, "{sv}", "EXPTIME",
173 g_variant_new_uint32(item->exptime));
174 g_variant_builder_add(&builder, "{sv}", "DTIM",
175 g_variant_new_uint32(item->discovery_timeout));
176 g_variant_builder_add(&builder, "{sv}", "DRET",
177 g_variant_new_byte(item->discovery_retries));
178 g_variant_builder_add(&builder, "{sv}", "FLAGS",
179 g_variant_new_byte(item->flags));
180 g_variant_builder_close(&builder);
182 iter = g_list_next(iter);
185 mpath_data = g_variant_builder_end(&builder);
186 g_object_unref(mpath_data);
188 WMESH_LOGE("Failed to wmesh_request_get_mpath_info");
193 static gboolean _on_mesh_monitor_cb(gpointer pdata)
197 wmesh_service *service = (wmesh_service *)pdata;
199 wmesh_interface_s *info = service->interface_info;
201 /* Exceptionally, checking external interface processes here. */
202 ret = wmesh_interface_check_external_exists(info->external_interface, &state);
203 WMESH_LOGD("Status : %d %d %d", ret, info->can_be_gate, state);
204 if (WMESHD_ERROR_NONE == ret) {
205 if (info->can_be_gate != state) {
206 wmesh_gdbus_enable_ethernet_interface(service, state);
208 /* Detect external network state (i.e. Ethernet)
209 and decide to make gate enabled */
211 wmesh_request_set_mesh_gate(info->bridge_interface,
212 info->mesh_interface, info->external_interface);
214 wmesh_request_unset_mesh_gate(info->bridge_interface,
215 info->mesh_interface, info->external_interface);
217 WMESH_LOGD("External interface state has been changed : [%d]", state);
218 info->can_be_gate = state;
221 /* In error case, we call enable etheret again for OdroidU3 */
222 wmesh_gdbus_enable_ethernet_interface(service, true);
225 _get_mpath_info(service);
227 _get_station_info(service);
231 return G_SOURCE_CONTINUE;
234 int wmesh_start_monitor_service(void *pdata)
236 int ret = WMESHD_ERROR_NONE;
237 wmesh_service *service = (wmesh_service *)pdata;
238 wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
240 if (service->monitor_timer)
241 wmesh_stop_monitor_service(pdata);
243 service->monitor_timer = g_timeout_add_seconds(MESH_MONITORING_TIME, _on_mesh_monitor_cb, service);
245 WMESH_LOGD("Peer Monitoring Service Started");
250 int wmesh_stop_monitor_service(void *pdata)
252 int ret = WMESHD_ERROR_NONE;
253 wmesh_service *service = (wmesh_service *)pdata;
254 wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
256 if (service->monitor_timer) {
257 g_source_remove(service->monitor_timer);
258 service->monitor_timer = 0;
261 WMESH_LOGD("Peer Monitoring Service Stopped");
263 /* After mesh interface is removed then ethernet is disabled when ethernet
264 * interface is bridged, so try to enable ethernet again */
265 WMESH_LOGD("Enable ethernet interface");
266 wmesh_gdbus_enable_ethernet_interface(service, true);