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.
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"
30 #define MESH_MONITORING_TIME 5
31 #define MESH_MAXIMUM_BEACON_LOST_COUNT 10
33 static void _on_station_list_destroy(gpointer data)
35 mesh_station_info_s *info = (mesh_station_info_s*)data;
43 static void _on_mpath_list_destroy(gpointer data)
45 mesh_mpath_info_s *info = (mesh_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 = MESHD_ERROR_NONE;
62 GList *sta_list = NULL;
63 GList *cmp_iter = NULL;
65 mesh_service *service = (mesh_service *)pdata;
66 mesh_interface_s *info = service->interface_info;
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");
74 iter = service->station_list;
76 mesh_station_info_s *item = (mesh_station_info_s*)iter->data;
77 MESH_LOGD("[%s]", item->bssid);
78 iter = g_list_next(iter);
83 mesh_station_info_s *item = (mesh_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 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);
97 cmp_iter = service->station_list;
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"))) {
104 cmp_iter = g_list_next(cmp_iter);
108 /* Send new station joined event */
109 MESH_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;
120 iter = service->station_list;
122 mesh_station_info_s *item2 = (mesh_station_info_s*)iter->data;
123 MESH_LOGE("[%s]", item2->bssid);
124 iter = g_list_next(iter);
130 static gboolean _get_mpath_info(void *pdata)
132 int ret = MESHD_ERROR_NONE;
133 GVariantBuilder builder;
134 GVariant* mpath_data;
137 mesh_service *service = (mesh_service *)pdata;
138 mesh_interface_s *info = service->interface_info;
140 /* Clear mesh path list */
141 g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
142 service->mpath_list = NULL;
144 ret = mesh_request_get_mpath_info(info->mesh_interface, &service->mpath_list);
145 if (MESHD_ERROR_NONE == ret) {
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
151 /* Get mesh path information and make variant data */
152 g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
154 iter = service->mpath_list;
155 while (iter != NULL) {
156 mesh_mpath_info_s *item = (mesh_mpath_info_s*)iter->data;
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);
181 iter = g_list_next(iter);
184 mpath_data = g_variant_builder_end(&builder);
185 g_object_unref(mpath_data);
187 MESH_LOGE("Failed to mesh_request_get_mpath_info");
192 static gboolean _on_mesh_monitor_cb(gpointer pdata)
195 #ifdef USE_IOCTL_MONITOR
199 #endif /* USE_IOCTL_MONITOR */
200 mesh_service *service = (mesh_service *)pdata;
202 mesh_interface_s *info = service->interface_info;
204 /* Exceptionally, checking external interface processes here. */
205 #ifdef USE_IOCTL_MONITOR
206 ret = mesh_get_ethernet_cable_state(&state);
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 */
216 mesh_request_set_mesh_gate(info->bridge_interface,
217 info->mesh_interface, info->external_interface);
219 mesh_request_unset_mesh_gate(info->bridge_interface,
220 info->mesh_interface, info->external_interface);
222 MESH_LOGD("External interface state has been changed : [%d]", state);
223 info->can_be_gate = state;
227 _get_mpath_info(service);
229 _get_station_info(service);
233 return G_SOURCE_CONTINUE;
236 int mesh_start_monitor_service(void *pdata)
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);
242 if (service->monitor_timer)
243 mesh_stop_monitor_service(pdata);
245 service->monitor_timer = g_timeout_add_seconds(MESH_MONITORING_TIME, _on_mesh_monitor_cb, service);
247 MESH_LOGD("Peer Monitoring Service Started");
252 int mesh_stop_monitor_service(void *pdata)
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);
258 if (service->monitor_timer) {
259 g_source_remove(service->monitor_timer);
260 service->monitor_timer = 0;
263 MESH_LOGD("Peer Monitoring Service Stopped");