Added support to get Mesh Configuration using netlink 27/145427/1
authorsaerome kim <saerome.kim@samsung.com>
Tue, 22 Aug 2017 08:40:31 +0000 (17:40 +0900)
committersaerome kim <saerome.kim@samsung.com>
Tue, 22 Aug 2017 08:40:31 +0000 (17:40 +0900)
Change-Id: I4544070667cceb6dd5e21f5078dc82bfdb2912e3
Signed-off-by: Saurav Babu <saurav.babu@samsung.com>
Signed-off-by: saerome kim <saerome.kim@samsung.com>
include/wmesh-netlink.h
include/wmesh-request.h
include/wmesh.h
introspection/wmesh.xml
src/wmesh-netlink.c
src/wmesh-request.c
src/wmesh-service-interface.c

index 0f756b0..4207663 100644 (file)
@@ -25,6 +25,7 @@ int wmesh_netlink_set_mesh_parameter(const char* mesh_if_name,
 int wmesh_netlink_get_station_info(const char* mesh_if_name, GList **station_list);
 int wmesh_netlink_del_station_info(const char* mesh_if_name, char *peer);
 int wmesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list);
+int wmesh_netlink_get_meshconf_info(wmesh_service *service);
 
 int wmesh_netlink_register_event_handler();
 int wmesh_netlink_unregister_event_handler();
index 7375a8c..158ee5a 100644 (file)
@@ -68,6 +68,9 @@ int wmesh_request_disable_softap(
 int wmesh_request_get_station_info(const char* mesh_interface, GList **station_list);
 int wmesh_request_get_mpath_info(const char* mesh_interface, GList **mpath_list);
 
+/* Mesh Conf */
+int wmesh_request_get_meshconf_info(wmesh_service *service);
+
 int wmesh_request_register_event_handler();
 int wmesh_request_unregister_event_handler();
 
index e79c9ac..18b0a70 100644 (file)
@@ -147,6 +147,21 @@ typedef struct {
        guchar flags; /**< Flags */
 } wmesh_mpath_info_s;
 
+/**< Mesh Conf information structure */
+typedef struct {
+       gushort retry_timeout; /**< Retry Timeout */
+       guchar hwmp_max_preq_retries; /**< HWMP Max Preq Retries */
+       gushort confirm_timeout; /**< Confirm Timeout */
+       guint path_refresh_time; /**< Path Refresh Time */
+       gushort holding_timeout; /**< Holding Timeout */
+       gushort min_disc_timeout; /**< Min Discovery Timeout */
+       gushort max_peer_links; /**< Max Peer Links */
+       gushort hwmp_preq_min_interval; /**< HWMP PREQ Min Interval */
+       guchar ttl; /**< TTL */
+       guint hwmp_active_path_timeout; /**< HWMP Active Path Timeout */
+       guchar element_ttl; /**< Element TTL */
+       gushort hwmp_rann_interval; /**< HWMP RANN Interval */
+} wmesh_meshconf_info_s;
 
 /**< mesh service structure */
 typedef struct _wmesh_service {
@@ -166,6 +181,7 @@ typedef struct _wmesh_service {
 
        GList *station_list; /**< Mesh station list */
        GList *mpath_list; /**< MPath list */
+       wmesh_meshconf_info_s *meshconf; /**< Mesh Conf */
        int netlink_fd; /**< Netlink event socket file descriptor */
        int monitor_timer; /**< Timer ID for peer monitoring service */
 } wmesh_service;
index 7bd424f..fac4da1 100644 (file)
                        <arg type="aa{sv}" name="mpath" direction="out"/>\r
                        <arg type="i" name="result" direction="out"/>\r
                </method>\r
+               <method name="get_meshconf_info">\r
+                       <arg type="a{sv}" name="meshconf" direction="out"/>\r
+                       <arg type="i" name="result" direction="out"/>\r
+               </method>\r
 \r
                <!-- Signal (D-Bus) definitions -->\r
                <signal name="mesh_enabled">\r
index 24c3cfb..e442017 100644 (file)
@@ -68,6 +68,7 @@ typedef struct {
        bool error_occured;
        GList **station_list;
        GList **mpath_list;
+       wmesh_meshconf_info_s **meshconf;
 } mesh_nl_state;
 
 typedef struct {
@@ -1147,6 +1148,140 @@ static int _on_receive_mpath_info(struct nl_msg *msg, void *arg)
        return NL_SKIP;
 }
 
+static int _on_receive_meshconf_info(struct nl_msg *msg, void *arg)
+{
+       struct nlattr *tb[NL80211_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       struct nlattr *pinfo[NL80211_MESHCONF_ATTR_MAX + 1];
+       static struct nla_policy meshconf_policy[NL80211_MESHCONF_ATTR_MAX+1] = {
+               [NL80211_MESHCONF_RETRY_TIMEOUT] = { .type = NLA_U16 },
+               [NL80211_MESHCONF_CONFIRM_TIMEOUT] = { .type = NLA_U16 },
+               [NL80211_MESHCONF_HOLDING_TIMEOUT] = { .type = NLA_U16 },
+               [NL80211_MESHCONF_MAX_PEER_LINKS] = { .type = NLA_U16 },
+               [NL80211_MESHCONF_MAX_RETRIES] = { .type = NLA_U8 },
+               [NL80211_MESHCONF_TTL] = { .type = NLA_U8 },
+               [NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 },
+               [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 },
+               [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] = { .type = NLA_U32 },
+               [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 },
+               [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 },
+               [NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT] = { .type = NLA_U16 },
+               [NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },
+               [NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },
+               [NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL] = { .type = NLA_U16 },
+               [NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
+               [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 },
+               [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 },
+               [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
+               [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },
+               [NL80211_MESHCONF_RSSI_THRESHOLD] = { .type = NLA_U32 },
+               [NL80211_MESHCONF_HT_OPMODE] = { .type = NLA_U16 },
+               [NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT] = { .type = NLA_U32 },
+               [NL80211_MESHCONF_HWMP_ROOT_INTERVAL] = { .type = NLA_U16 },
+               [NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL] = { .type = NLA_U16 },
+               [NL80211_MESHCONF_POWER_MODE] = { .type = NLA_U32 },
+               [NL80211_MESHCONF_AWAKE_WINDOW] = { .type = NLA_U16 },
+       };
+
+       mesh_nl_state *state = (mesh_nl_state *)arg;
+       wmesh_meshconf_info_s *meshconf_info = NULL;
+
+       nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+               genlmsg_attrlen(gnlh, 0), NULL);
+
+       /*
+        * TODO: validate the interface and mac address!
+        * Otherwise, there's a race condition as soon as
+        * the kernel starts sending mpath notifications.
+        */
+
+       if (!tb[NL80211_ATTR_MESH_CONFIG]) {
+               WMESH_LOGE("missing mesh path info!");
+               return NL_SKIP;
+       }
+       if (nla_parse_nested(pinfo, NL80211_MESHCONF_ATTR_MAX,
+                                               tb[NL80211_ATTR_MESH_CONFIG], meshconf_policy)) {
+               WMESH_LOGE("failed to parse nested attributes!");
+               return NL_SKIP;
+       }
+
+       meshconf_info = g_try_new0(wmesh_meshconf_info_s, 1);
+       if (NULL == meshconf_info) {
+               WMESH_LOGE("Failed to allocate mesh path info !");
+               return NL_SKIP;
+       }
+
+       if (pinfo[NL80211_MESHCONF_RETRY_TIMEOUT]) {
+               meshconf_info->retry_timeout =
+                       nla_get_u16(pinfo[NL80211_MESHCONF_RETRY_TIMEOUT]);
+               WMESH_LOGD("Retry Timeout : %u", meshconf_info->retry_timeout);
+       }
+       if (pinfo[NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES]) {
+               meshconf_info->hwmp_max_preq_retries =
+                       nla_get_u8(pinfo[NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES]);
+               WMESH_LOGD("HWMP Max PREQ Retries : %u",
+                                  meshconf_info->hwmp_max_preq_retries);
+       }
+       if (pinfo[NL80211_MESHCONF_CONFIRM_TIMEOUT]) {
+               meshconf_info->confirm_timeout =
+                       nla_get_u16(pinfo[NL80211_MESHCONF_CONFIRM_TIMEOUT]);
+               WMESH_LOGD("Confirm Timeout : %u", meshconf_info->confirm_timeout);
+       }
+       if (pinfo[NL80211_MESHCONF_PATH_REFRESH_TIME]) {
+               meshconf_info->path_refresh_time =
+                       nla_get_u32(pinfo[NL80211_MESHCONF_PATH_REFRESH_TIME]);
+               WMESH_LOGD("Path Refresh Time : %u", meshconf_info->path_refresh_time);
+       }
+       if (pinfo[NL80211_MESHCONF_HOLDING_TIMEOUT]) {
+               meshconf_info->holding_timeout =
+                       nla_get_u16(pinfo[NL80211_MESHCONF_HOLDING_TIMEOUT]);
+               WMESH_LOGD("Holding Timeout : %u", meshconf_info->holding_timeout);
+       }
+       if (pinfo[NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT]) {
+               meshconf_info->min_disc_timeout =
+                       nla_get_u16(pinfo[NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT]);
+               WMESH_LOGD("Min Disc Timeout : %u", meshconf_info->min_disc_timeout);
+       }
+       if (pinfo[NL80211_MESHCONF_MAX_PEER_LINKS]) {
+               meshconf_info->max_peer_links =
+                       nla_get_u16(pinfo[NL80211_MESHCONF_MAX_PEER_LINKS]);
+               WMESH_LOGD("MAX Peer Links : %u", meshconf_info->max_peer_links);
+       }
+       if (pinfo[NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL]) {
+               meshconf_info->hwmp_preq_min_interval =
+                       nla_get_u16(pinfo[NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL]);
+               WMESH_LOGD("HWMP PREQ Min Interval : %u",
+                                  meshconf_info->hwmp_preq_min_interval);
+       }
+       if (pinfo[NL80211_MESHCONF_TTL]) {
+               meshconf_info->ttl =
+                       nla_get_u8(pinfo[NL80211_MESHCONF_TTL]);
+               WMESH_LOGD("TTL : %u", meshconf_info->ttl);
+       }
+       if (pinfo[NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT]) {
+               meshconf_info->hwmp_active_path_timeout =
+                       nla_get_u32(pinfo[NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT]);
+               WMESH_LOGD("HWMP Active Path Timeout : %u",
+                                  meshconf_info->hwmp_active_path_timeout);
+       }
+       if (pinfo[NL80211_MESHCONF_ELEMENT_TTL]) {
+               meshconf_info->element_ttl =
+                       nla_get_u8(pinfo[NL80211_MESHCONF_ELEMENT_TTL]);
+               WMESH_LOGD("Element TTL : %u", meshconf_info->element_ttl);
+       }
+       if (pinfo[NL80211_MESHCONF_HWMP_RANN_INTERVAL]) {
+               meshconf_info->hwmp_rann_interval =
+                       nla_get_u16(pinfo[NL80211_MESHCONF_HWMP_RANN_INTERVAL]);
+               WMESH_LOGD("HWMP RANN Interval : %u",
+                                  meshconf_info->hwmp_rann_interval);
+       }
+
+       WMESH_LOGD("");
+       *(state->meshconf) = meshconf_info;
+
+       return NL_SKIP;
+}
+
 static int _on_receive_mesh_event(struct nl_msg *msg, void *arg)
 {
        struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
@@ -1511,6 +1646,86 @@ nla_put_failure:
        return WMESHD_ERROR_OPERATION_FAILED;
 }
 
+static int _send_nl_get_meshconf_info(wmesh_service *service)
+{
+       mesh_nl_state state = {
+               .nl80211_id = -1,
+               .callback_state = MESH_NL_CALLBACK_TRYING,
+               .event_source = 0,
+               .nl_socket = NULL,
+               .msg = NULL,
+               .cb = NULL,
+               .s_cb = NULL,
+               .meshconf = &service->meshconf,
+       };
+       int err = WMESHD_ERROR_NONE;
+       int device_index = 0;
+       int ret;
+       int test = 0;
+
+       ret = __initialize_nl80211(&state);
+       if (WMESHD_ERROR_NONE != ret) {
+               WMESH_LOGE("Failed to initialize nl80211");
+               return ret;
+       }
+
+       ret = __initialize_netlink_message(&state);
+       if (WMESHD_ERROR_NONE != ret) {
+               WMESH_LOGE("Failed to initialize netlink message");
+               goto DESTROY;
+       }
+
+       /* Set command into message */
+       genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
+                   0, NL80211_CMD_GET_MESH_CONFIG, 0);
+
+       /* Add attributes into message */
+       WMESH_LOGD("Dump Mesh Config with interface [%s]",
+                          service->interface_info->mesh_interface);
+       ret = __get_device_index_from_string(
+                                       service->interface_info->mesh_interface, &device_index);
+       if (WMESHD_ERROR_NONE != ret) {
+               WMESH_LOGE("Failed to get mesh interface device index");
+               err = ret;
+               goto DESTROY;
+       }
+       NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
+
+       /* Register valid callback to dump result */
+       nl_cb_set(state.cb, NL_CB_VALID, NL_CB_CUSTOM,
+                       _on_receive_meshconf_info, &state);
+
+       /* Send message into kernel */
+       ret = nl_send_auto(state.nl_socket, state.msg);
+       if (ret < 0) {
+               WMESH_LOGE("Failed to nl_send_auto() [%s](%d)",
+                               nl_geterror(ret), ret);
+               err = WMESHD_ERROR_OPERATION_FAILED;
+               goto DESTROY;
+       }
+
+       /* sync response */
+       state.callback_state = MESH_NL_CALLBACK_TRYING;
+       while (state.callback_state == MESH_NL_CALLBACK_TRYING) {
+               WMESH_LOGD("  count [%02d]", ++test);
+               nl_recvmsgs(state.nl_socket, state.cb);
+       }
+       WMESH_LOGD("Finished");
+
+DESTROY:
+       __clean_netlink_message(&state);
+       __clean_nl80211(&state);
+
+       return err;
+
+nla_put_failure:
+       WMESH_LOGE("Failed to message build");
+       __clean_netlink_message(&state);
+       __clean_nl80211(&state);
+
+       return WMESHD_ERROR_OPERATION_FAILED;
+}
+
 static int _send_nl_register_event_handler()
 {
        int err = WMESHD_ERROR_NONE;
@@ -1655,6 +1870,21 @@ int wmesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list)
        return ret;
 }
 
+int wmesh_netlink_get_meshconf_info(wmesh_service *service)
+{
+       int ret = WMESHD_ERROR_NONE;
+
+       if (NULL == service) {
+               WMESH_LOGE("Invalid parameter [%p]", service);
+               return WMESHD_ERROR_INVALID_PARAMETER;
+       }
+
+       WMESH_LOGD("Get current Mesh Config info");
+       ret = _send_nl_get_meshconf_info(service);
+
+       return ret;
+}
+
 int wmesh_netlink_register_event_handler()
 {
        int ret = WMESHD_ERROR_NONE;
index 1b774c7..9c3cffe 100644 (file)
@@ -245,6 +245,20 @@ int wmesh_request_get_mpath_info(const char* mesh_interface, GList **mpath_list)
        return WMESHD_ERROR_NONE;
 }
 
+int wmesh_request_get_meshconf_info(wmesh_service *service)
+{
+       int ret = WMESHD_ERROR_NONE;
+
+       WMESH_LOGD("Request to get meshconf info");
+
+       /* Get MPath info */
+       ret = wmesh_netlink_get_meshconf_info(service);
+       if (WMESHD_ERROR_NONE != ret)
+               return ret;
+
+       return WMESHD_ERROR_NONE;
+}
+
 int wmesh_request_register_event_handler()
 {
        int ret = WMESHD_ERROR_NONE;
index 2252949..3ff949f 100644 (file)
@@ -970,6 +970,67 @@ static gboolean _wmeshd_dbus_handle_get_mpath_info(NetWmesh *object,
        return TRUE;
 }
 
+static gboolean _wmeshd_dbus_handle_get_meshconf_info(NetWmesh *object,
+               GDBusMethodInvocation *invocation,
+               gpointer user_data)
+{
+       int ret = WMESHD_ERROR_NONE;
+       GVariantBuilder builder;
+       GVariant* meshconf_data;
+       wmesh_meshconf_info_s *item;
+
+       wmesh_service *service = (wmesh_service *)user_data;
+
+       ret = wmesh_request_get_meshconf_info(service);
+       if (WMESHD_ERROR_NONE != ret) {
+               WMESH_LOGE("Failed to wmesh_request_get_mpath_info");
+
+               g_dbus_method_invocation_return_error(invocation,
+                               G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
+       } else {
+               /* Get mesh path information and make variant data */
+               g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
+
+               item = service->meshconf;
+
+               g_variant_builder_add(&builder, "{sv}", "RETRY_TIMEOUT",
+                                                         g_variant_new_uint16(item->retry_timeout));
+               g_variant_builder_add(&builder, "{sv}", "HWMP_MAX_PREQ_RETRIES",
+                                                       g_variant_new_byte(item->hwmp_max_preq_retries));
+               g_variant_builder_add(&builder, "{sv}", "CONFIRM_TIMEOUT",
+                                                         g_variant_new_uint16(item->confirm_timeout));
+               g_variant_builder_add(&builder, "{sv}", "PATH_REFRESH_TIME",
+                                                         g_variant_new_uint32(item->path_refresh_time));
+               g_variant_builder_add(&builder, "{sv}", "HOLDING_TIMEOUT",
+                                                         g_variant_new_uint16(item->holding_timeout));
+               g_variant_builder_add(&builder, "{sv}", "MIN_DISC_TIMEOUT",
+                                                         g_variant_new_uint16(item->min_disc_timeout));
+               g_variant_builder_add(&builder, "{sv}", "MAX_PEER_LINKS",
+                                                         g_variant_new_uint16(item->max_peer_links));
+               g_variant_builder_add(&builder, "{sv}", "HWMP_PREQ_MIN_INTERVAL",
+                                                       g_variant_new_uint16(item->hwmp_preq_min_interval));
+               g_variant_builder_add(&builder, "{sv}", "TTL",
+                                                         g_variant_new_byte(item->ttl));
+               g_variant_builder_add(&builder, "{sv}", "HWMP_ACTIVE_PATH_TIMEOUT",
+                                               g_variant_new_uint32(item->hwmp_active_path_timeout));
+               g_variant_builder_add(&builder, "{sv}", "ELEMENT_TTL",
+                                                         g_variant_new_byte(item->element_ttl));
+               g_variant_builder_add(&builder, "{sv}", "HWMP_RANN_INTERVAL",
+                                                         g_variant_new_uint16(item->hwmp_rann_interval));
+
+
+               meshconf_data = g_variant_builder_end(&builder);
+               net_wmesh_complete_get_meshconf_info(object, invocation, meshconf_data,
+                                                                       ret);
+
+               g_object_unref(meshconf_data);
+       }
+
+       g_free(service->meshconf);
+
+       return TRUE;
+}
+
 static void _wmeshd_dbus_on_activator_bus_acquired(GDBusConnection *conn,
                const gchar *name, gpointer user_data)
 {
@@ -1056,6 +1117,8 @@ static void _wmeshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *nam
                        G_CALLBACK(_wmeshd_dbus_handle_get_station_info), service);
        g_signal_connect(meshd_dbus_object, "handle-get-mpath-info",
                        G_CALLBACK(_wmeshd_dbus_handle_get_mpath_info), service);
+       g_signal_connect(meshd_dbus_object, "handle-get-meshconf-info",
+                       G_CALLBACK(_wmeshd_dbus_handle_get_meshconf_info), service);
 
        ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(meshd_dbus_object),
                        conn, WMESH_DBUS_OBJPATH, &error);