Added Network Fault Diagnosis feature 55/213555/3 submit/tizen/20190923.065757 submit/tizen/20190925.091926
authorNishant Chaprana <n.chaprana@samsung.com>
Thu, 5 Sep 2019 14:18:38 +0000 (19:48 +0530)
committerNishant Chaprana <n.chaprana@samsung.com>
Wed, 18 Sep 2019 14:39:12 +0000 (20:09 +0530)
Note: To enable feature make _inm_error_analysis variable as "yes" in spec file.

Change-Id: I3dd5add60ab4c0cc552f57ba00f40f75bbb2bc15
Signed-off-by: Nishant Chaprana <n.chaprana@samsung.com>
21 files changed:
include/inm-connman.h
include/inm-error-analysis.h [new file with mode: 0644]
include/inm-error-logger.h [new file with mode: 0644]
include/inm-error-recovery.h [new file with mode: 0644]
include/inm-error.h
include/inm-gdbus.h
include/inm-manager.h
packaging/inm-manager.spec
src/CMakeLists.txt
src/inm-arping.c
src/inm-connman-internal.h
src/inm-connman-service.c
src/inm-connman-tech.c
src/inm-error-analysis.c [new file with mode: 0644]
src/inm-error-logger.c [new file with mode: 0644]
src/inm-error-recovery.c [new file with mode: 0644]
src/inm-gdbus.c
src/inm-ip-conflict.c
src/inm-manager.c
src/inm-supplicant-iface.c
src/inm-util.c

index 9a2a01eb7792695ac02b9e65f2122436dd3867b8..84be63f01294fde143b9670ee528688a47d222db 100644 (file)
@@ -85,6 +85,24 @@ typedef enum {
        CONNMAN_SERVICE_ERROR_INVALID_KEY,
 } connman_service_error_e;
 
+typedef enum {
+       CONNMAN_SERVICE_STATE_UNKNOWN,
+       CONNMAN_SERVICE_STATE_IDLE,
+       CONNMAN_SERVICE_STATE_ASSOCIATION,
+       CONNMAN_SERVICE_STATE_CONFIGURATION,
+       CONNMAN_SERVICE_STATE_READY,
+       CONNMAN_SERVICE_STATE_ONLINE,
+       CONNMAN_SERVICE_STATE_DISCONNECT,
+       CONNMAN_SERVICE_STATE_FAILURE,
+} connman_service_state_e;
+
+typedef enum {
+       CONNMAN_SERVICE_CONNECT_REASON_NONE,
+       CONNMAN_SERVICE_CONNECT_REASON_AUTO,
+       CONNMAN_SERVICE_CONNECT_REASON_USER,
+       CONNMAN_SERVICE_CONNECT_REASON_SESSION
+} connman_service_connect_reason_e;
+
 typedef enum {
        CONNMAN_IP_TYPE_V4,
        CONNMAN_IP_TYPE_V6,
diff --git a/include/inm-error-analysis.h b/include/inm-error-analysis.h
new file mode 100644 (file)
index 0000000..e4dd55c
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Network Monitoring Module
+ *
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This file defines macro and declares functions which are used are used to
+ * analyse network error and get the root cause of network error.
+ *
+ * @file        inm-error-analysis.h
+ * @author      Nishant Chaprana (n.chaprana@samsung.com)
+ * @version     0.1
+ */
+
+#ifndef __INM_ERROR_ANALYSIS_H__
+#define __INM_ERROR_ANALYSIS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+       INM_NET_ERR_TYPE_NONE = 0,                   /**< No error code */
+
+       INM_NET_ERR_TYPE_ETHERNET_DETACHED,          /**< Connection medium: Ethernet cable detached */
+       INM_NET_ERR_TYPE_ETHERNET_OFF,               /**< Connection medium: Ethernet technology off */
+       INM_NET_ERR_TYPE_WIFI_DETACHED,              /**< Connection medium: Wi-Fi Module detached */
+       INM_NET_ERR_TYPE_WIFI_OFF,                   /**< Connection medium: Wi-Fi technology off */
+
+       INM_NET_ERR_TYPE_AP_POWERED_OFF,             /**< Disconnection: AP powered/switched off */
+       INM_NET_ERR_TYPE_AP_OUT_OF_RANGE,            /**< Disconnection: AP out of range */
+       INM_NET_ERR_TYPE_AP_PASSWORD_MISMATCH,       /**< Disconnection: AP password mismatched */
+       INM_NET_ERR_TYPE_AP_PASSWORD_CHANGED,        /**< Disconnection: AP password changed */
+       INM_NET_ERR_TYPE_DISCONNECTION_BY_USER,      /**< Disconnection: User initiated */
+
+       INM_NET_ERR_TYPE_IP_CONFLICT,                /**< IP: IP conflict */
+       INM_NET_ERR_TYPE_DHCP_FAILED,                /**< IP: DHCP failed */
+
+       INM_NET_ERR_TYPE_CONGESTED_NETWORK,          /**< Performance: Congested network */
+       INM_NET_ERR_TYPE_CHANNEL_INTERFERENCE_HIGH,  /**< Performance: High channel interference */
+       INM_NET_ERR_TYPE_NO_INTERNET,                /**< Performance: No internet */
+} inm_net_err_type_e;
+
+void inm_error_analysis_diagnose(inm_net_err_type_e err_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INM_ERROR_ANALYSIS_H__ */
diff --git a/include/inm-error-logger.h b/include/inm-error-logger.h
new file mode 100644 (file)
index 0000000..ab5c47a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Network Monitoring Module
+ *
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This file defines macro and declares functions for logging network state
+ * transitions.
+ *
+ * @file        inm-error-logger.h
+ * @author      Nishant Chaprana (n.chaprana@samsung.com)
+ * @version     0.1
+ */
+
+#ifndef __INM_ERROR_LOGGER_H__
+#define __INM_ERROR_LOGGER_H__
+
+#include "inm-connman.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+       connman_tech_state_e state;
+       connman_service_type_e type;
+} inm_tech_data_s;
+
+typedef struct {
+       char *name;
+       connman_service_type_e type;
+       connman_service_error_e error;
+       connman_service_state_e state_v4;
+       connman_service_state_e state_v6;
+       guint8 strength;
+       connman_service_connect_reason_e connect_reason;
+       gboolean disconnection_requested;
+} inm_service_data_s;
+
+void inm_error_logger_connman_service_msg(inm_service_data_s *data);
+void inm_error_logger_connman_tech_msg(inm_tech_data_s *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INM_ERROR_LOGGER_H__ */
diff --git a/include/inm-error-recovery.h b/include/inm-error-recovery.h
new file mode 100644 (file)
index 0000000..f73e1a2
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Network Monitoring Module
+ *
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This file defines macro and declares functions for network error recovery.
+ *
+ * @file        inm-error-recovery.h
+ * @author      Nishant Chaprana (n.chaprana@samsung.com)
+ * @version     0.1
+ */
+
+#ifndef __INM_ERROR_RECOVERY_H__
+#define __INM_ERROR_RECOVERY_H__
+
+#include "inm-error-analysis.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void inm_error_recovery_execute(inm_net_err_type_e error_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INM_ERROR_RECOVERY_H__ */
index f0168bbf6d9c29ec3182ceca844990c1bb3b0510..8a0bc0b921844cebd6c15bb54afb5ba72ef0cfb6 100644 (file)
@@ -33,6 +33,7 @@ extern "C" {
 #endif
 
 #include <tizen.h>
+#include "inm-manager.h"
 
 void inm_error_set_gerror(inm_manager_error_e error_code, GError **error);
 void inm_error_register(void);
index 1394d876695cf13ae04de97f807b460c675def56..b9f1f8f5ba5999febe8dc4fb28ead9fefdb8ff80 100644 (file)
@@ -27,6 +27,7 @@
 #ifndef __INM_GDBUS_H__
 #define __INM_GDBUS_H__
 
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -153,6 +154,7 @@ void inm_gdbus_emit_reacher_result(int error_code,
                const gchar *url);
 void inm_gdbus_emit_default_dns_lookup_result(gboolean found, const gchar *host_name);
 void inm_gdbus_emit_port_scan_result(GVariant *result);
+void inm_gdbus_emit_network_error_occured(int error_type);
 void inm_gdbus_emit_ethernet_cable_state(gboolean state);
 void inm_gdbus_emit_wifi_module_state(gboolean state);
 void inm_gdbus_emit_retry_tx_rate_changed(int retry_tx_rate);
index c6de75816531aa3b31edc9453e71d277ecdf973e..e5599b6c37e2f082aed99d2c001c0cfdb2579bc1 100644 (file)
 
 #ifndef __INM_MANAGER_H__
 #define __INM_MANAGER_H__
-#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#include <glib.h>
+
 #ifndef IFNAMSIZ
 #define IFNAMSIZ 16
 #endif
@@ -125,3 +126,9 @@ void inm_manager_unset_loop();
 
 int inm_manager_init();
 int inm_manager_deinit();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INM_MANAGER_H__ */
index 3067f87279865ff674b9e54a5ada4bccd35f0d88..71a91e47fd290b544ee85710c3398e3018f012a4 100644 (file)
@@ -1,3 +1,5 @@
+%define _inm_error_analysis "yes"
+
 Name:       inm-manager
 Summary:    INM(Intelligent Network Monitoring) daemon
 Version:    0.0.27
@@ -59,6 +61,9 @@ export LDFLAGS="$LDFLAGS -lgcov"
 
 %cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \
        -DBIN_DIR=%{_bindir} \
+%if %{_inm_error_analysis} == "yes"
+       -DBUILD_ERROR_ANALYSIS=%{?_inm_error_analysis:1}%{!?_inm_error_analysis:0} \
+%endif
        -DBUILD_GTESTS=%{?gtests:1}%{!?gtests:0} \
        -DBUILD_GCOV=%{?gcov:1}%{!?gcov:0} \
        -DBUILD_TEST_APP=%{?test_app:1}%{!?test_app:0}
index 3f96a18fdc0ed60691fc2f8ad8cf5277f165fe90..2b571bdf8452bc41f0e1ce24ada28d3d8098b4ec 100644 (file)
@@ -32,11 +32,9 @@ PKG_CHECK_MODULES(inm_pkgs REQUIRED
        libcares
        )
 
-SET(REQUIRED_LIBS "-ldl")
-
 IF(BUILD_GCOV)
        ADD_DEFINITIONS("-DTIZEN_TEST_GCOV")
-       SET(REQUIRED_LIBS "${REQUIRED_LIBS} -lgcov")
+       SET(REQUIRED_LIBS ${REQUIRED_LIBS} -lgcov)
 ENDIF(BUILD_GCOV)
 
 FOREACH(flag ${inm_pkgs_CFLAGS})
@@ -83,10 +81,21 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}")
 
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -pie")
 
+IF(BUILD_ERROR_ANALYSIS)
+       ADD_DEFINITIONS("-DBUILD_ERROR_ANALYSIS")
+       SET(SRCS ${SRCS}
+               ${CMAKE_SOURCE_DIR}/src/inm-error-analysis.c
+               ${CMAKE_SOURCE_DIR}/src/inm-error-logger.c
+               ${CMAKE_SOURCE_DIR}/src/inm-error-recovery.c
+       )
+ENDIF(BUILD_ERROR_ANALYSIS)
+
 ADD_DEFINITIONS("-DUSE_DLOG")
 
 ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
 
+SET(REQUIRED_LIBS ${REQUIRED_LIBS} -ldl)
+
 TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${inm_pkgs_LDFLAGS} ${REQUIRED_LIBS})
 
 INSTALL(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION ${BIN_DIR})
index 42311fb7fbf3134e0ffdcb015912d7478435cfe2..d813ec4721435c6e81213614b6530057a5941b98 100644 (file)
@@ -29,6 +29,7 @@
 #include "inm-util.h"
 #include "inm-manager-log.h"
 #include "inm-arping.h"
+#include "inm-error-analysis.h"
 
 #define MSEC 1000
 #define DEFAULT_INTERVAL 1000
index ce5793ab5588050a0ee58c55dcc61a8d5f5a05b6..afaae39e1117fb49492b633a0131339a63a6f5b0 100644 (file)
@@ -66,18 +66,6 @@ typedef enum {
        CONNMAN_ADDR_IPV6,
 } connman_addr_type_e;
 
-typedef enum {
-       CONNMAN_SERVICE_STATE_UNKNOWN,
-       CONNMAN_SERVICE_STATE_IDLE,
-       CONNMAN_SERVICE_STATE_ASSOCIATION,
-       CONNMAN_SERVICE_STATE_CONFIGURATION,
-       CONNMAN_SERVICE_STATE_READY,
-       CONNMAN_SERVICE_STATE_ONLINE,
-       CONNMAN_SERVICE_STATE_DISCONNECT,
-       CONNMAN_SERVICE_STATE_FAILURE,
-
-} connman_service_state_e;
-
 typedef enum {
        CONNMAN_SERVICE_SECURITY_UNKNOWN,
        CONNMAN_SERVICE_SECURITY_NONE,
index 4e2d3169fff5eed09fbfcfc28a7d1831aa5b11aa..c63af84823c4d7262956b336188de2fad8a60035 100644 (file)
@@ -35,6 +35,8 @@
 #include "inm-gdbus.h"
 #include "inm-util.h"
 #include "inm-manager-log.h"
+#include "inm-error-analysis.h"
+#include "inm-error-logger.h"
 
 #define IP_LEN 4
 #define IPV6_LEN 16
@@ -441,6 +443,12 @@ typedef struct {
        gint reason;
        gint assoc_status;
 
+       /** connect reason (user/auto) */
+       gint connect_reason;
+
+       /** disconnection requested by user */
+       gboolean disconnection_requested;
+
 } connman_wlan_priv_s;
 
 typedef union {
@@ -801,21 +809,24 @@ static inline void __get_error(connman_service_s *service, GVariant *value)
        const gchar *err_str = NULL;
        err_str =  g_variant_get_string(value, NULL);
 
-       if (g_strcmp0(err_str, "invalid-key") == 0)
+       if (g_strcmp0(err_str, "invalid-key") == 0) {
                service->error = CONNMAN_SERVICE_ERROR_INVALID_KEY;
-       else if (g_strcmp0(err_str, "connect-failed") == 0)
+       } else if (g_strcmp0(err_str, "connect-failed") == 0) {
                service->error = CONNMAN_SERVICE_ERROR_CONNECT_FAILED;
-       else if (g_strcmp0(err_str, "auth-failed") == 0)
+       } else if (g_strcmp0(err_str, "auth-failed") == 0) {
                service->error = CONNMAN_SERVICE_ERROR_AUTH_FAILED;
-       else if (g_strcmp0(err_str, "login-failed") == 0)
+       } else if (g_strcmp0(err_str, "login-failed") == 0) {
                service->error = CONNMAN_SERVICE_ERROR_LOGIN_FAILED;
-       else if (g_strcmp0(err_str, "dhcp-failed") == 0)
+       } else if (g_strcmp0(err_str, "dhcp-failed") == 0) {
                service->error = CONNMAN_SERVICE_ERROR_DHCP_FAILED;
-       else if (g_strcmp0(err_str, "out-of-range") == 0)
+#ifdef BUILD_ERROR_ANALYSIS
+               inm_error_analysis_diagnose(INM_NET_ERR_TYPE_DHCP_FAILED);
+#endif
+       } else if (g_strcmp0(err_str, "out-of-range") == 0) {
                service->error = CONNMAN_SERVICE_ERROR_OUT_OF_RANGE;
-       else if (g_strcmp0(err_str, "pin-missing") == 0)
+       } else if (g_strcmp0(err_str, "pin-missing") == 0) {
                service->error = CONNMAN_SERVICE_ERROR_PIN_MISSING;
-       else
+       else
                service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
 
        PRINT_LOG("<Connman service error:%s>", err_str);
@@ -1458,6 +1469,16 @@ static inline void __get_assoc_status(connman_service_s *service, GVariant *valu
        service->priv_info.wlan.assoc_status = g_variant_get_int32(value);
 }
 
+static inline void __get_connect_reason(connman_service_s *service, GVariant *value)
+{
+       service->priv_info.wlan.connect_reason = g_variant_get_int32(value);
+}
+
+static inline void __get_disconnection_requested(connman_service_s *service, GVariant *value)
+{
+       service->priv_info.wlan.disconnection_requested = g_variant_get_boolean(value);
+}
+
 static inline void __get_passphrase(connman_service_s *service, GVariant *value)
 {
        wlan_sec_info_s *security_info = &(service->priv_info.wlan.sec_info);
@@ -1718,6 +1739,10 @@ static void __service_get_property(connman_service_s *service,
                __get_reason(service, value);
        else if (g_strcmp0(key, "AssocStatusCode") == 0)
                __get_assoc_status(service, value);
+       else if (g_strcmp0(key, "ConnectReason") == 0)
+               __get_connect_reason(service, value);
+       else if (g_strcmp0(key, "DisconnectionRequested") == 0)
+               __get_disconnection_requested(service, value);
 }
 
 static void __service_property_changed(const gchar *sender_name,
@@ -1742,8 +1767,32 @@ static void __service_property_changed(const gchar *sender_name,
        if (key)
                __service_get_property(service, key, value);
 
-       PRINT_LOG("<Connman service %s:Property changed>", object_path);
-       inm_connman_service_write(object_path, TRUE);
+
+       if (service->state <= CONNMAN_SERVICE_STATE_IDLE &&
+           service->state_ipv6 <= CONNMAN_SERVICE_STATE_IDLE) {
+               g_variant_unref(value);
+               __INM_FUNC_EXIT__;
+               return;
+       }
+
+#ifdef BUILD_ERROR_ANALYSIS
+       if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
+               inm_service_data_s service_data = {
+                       .name = service->name,
+                       .type = service->type,
+                       .error = service->error,
+                       .state_v4 = service->state,
+                       .state_v6 = service->state_ipv6,
+                       .strength = service->strength,
+                       .connect_reason =
+                               service->priv_info.wlan.connect_reason,
+                       .disconnection_requested =
+                               service->priv_info.wlan.disconnection_requested
+               };
+
+               inm_error_logger_connman_service_msg(&service_data);
+       }
+#endif
 
        g_variant_unref(value);
 }
index a70e1b7f12b0e88c970d3301f30a440708aedf6e..7a3ce5ae85c15e72686775b236b69616c0463605 100644 (file)
@@ -32,6 +32,7 @@
 #include "inm-gdbus.h"
 #include "inm-util.h"
 #include "inm-manager-log.h"
+#include "inm-error-logger.h"
 
 #define CONNMAN_TECH_PATH CONNMAN_PATH "/technology"
 
@@ -239,7 +240,14 @@ static void __tech_property_changed(const gchar *sender_name,
        if (g_tech_changed_cb && (tech_state != prev_tech_state)) {
                tech_type = __connman_service_type2enum(tech->type);
                INM_LOGI("State changed");
-               INM_LOGI("Notify tech type %d state %d", tech_type, tech_state);
+#ifdef BUILD_ERROR_ANALYSIS
+               inm_tech_data_s tech_data = {
+                       .state = tech_state,
+                       .type = tech_type,
+               };
+
+               inm_error_logger_connman_tech_msg(&tech_data);
+#endif
                g_tech_changed_cb(tech_type, tech_state);
        }
 
@@ -325,7 +333,14 @@ void inm_connman_tech_add(gchar *path, GVariantIter *iter)
        if (g_tech_changed_cb) {
                tech_type = __connman_service_type2enum(tech->type);
                tech_state = __connman_tech_get_state(tech->powered, tech->connected);
-               INM_LOGI("Notify tech type %d state %d", tech_type, tech_state);
+#ifdef BUILD_ERROR_ANALYSIS
+               inm_tech_data_s tech_data = {
+                       .state = tech_state,
+                       .type = tech_type,
+               };
+
+               inm_error_logger_connman_tech_msg(&tech_data);
+#endif
                g_tech_changed_cb(tech_type, tech_state);
        }
 
@@ -355,7 +370,14 @@ void inm_connman_tech_remove(GVariant *parameters)
 
        if (g_tech_changed_cb) {
                tech_type = __connman_service_type2enum(tech->type);
-               INM_LOGI("Notify tech type %d state %d", tech_type, CONNMAN_TECH_STATE_UNKNOWN);
+#ifdef BUILD_ERROR_ANALYSIS
+               inm_tech_data_s tech_data = {
+                       .state = CONNMAN_TECH_STATE_UNKNOWN,
+                       .type = tech_type,
+               };
+
+               inm_error_logger_connman_tech_msg(&tech_data);
+#endif
                g_tech_changed_cb(tech_type, CONNMAN_TECH_STATE_UNKNOWN);
        }
 
diff --git a/src/inm-error-analysis.c b/src/inm-error-analysis.c
new file mode 100644 (file)
index 0000000..9b2cbf0
--- /dev/null
@@ -0,0 +1,23 @@
+#include <gio/gio.h>
+
+#include "inm-manager-log.h"
+#include "inm-connman.h"
+#include "inm-gdbus.h"
+#include "inm-error-analysis.h"
+#include "inm-error-recovery.h"
+
+void inm_error_analysis_diagnose(inm_net_err_type_e err_type)
+{
+       __INM_FUNC_ENTER__;
+
+       /* No need to diagnose error, send NetworkError event */
+       if (err_type == INM_NET_ERR_TYPE_NONE) {
+               __INM_FUNC_EXIT__;
+               return;
+       }
+
+       inm_gdbus_emit_network_error_occured(err_type);
+       inm_error_recovery_execute(err_type);
+
+       __INM_FUNC_EXIT__;
+}
diff --git a/src/inm-error-logger.c b/src/inm-error-logger.c
new file mode 100644 (file)
index 0000000..146b31a
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Network Monitoring Module
+ *
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This file implements functions for analysing and identifying occurance of
+ * network error by monitoring network state transitions.
+ *
+ * @file        inm-error-analysis.c
+ * @author      Nishant Chaprana (n.chaprana@samsung.com)
+ * @version     0.1
+ */
+
+#include <gio/gio.h>
+
+#include "inm-manager-log.h"
+#include "inm-connman.h"
+#include "inm-error-analysis.h"
+#include "inm-error-logger.h"
+
+static inm_service_data_s old_service_data;
+static inm_tech_data_s old_tech_data;
+
+static gboolean inm_error_logger_service_data_cmp(inm_service_data_s *d1,
+                                                 inm_service_data_s *d2)
+{
+       if (g_strcmp0(d1->name, d2->name))
+               return FALSE;
+
+       if (d1->type != d2->type)
+               return FALSE;
+
+       if (d1->error != d2->error)
+               return FALSE;
+
+       if (d1->state_v4 != d2->state_v4)
+               return FALSE;
+
+       if (d1->state_v6 != d2->state_v6)
+               return FALSE;
+
+       if (d1->strength != d2->strength)
+               return FALSE;
+
+       if (d1->connect_reason != d2->connect_reason)
+               return FALSE;
+
+       if (d1->disconnection_requested != d2->disconnection_requested)
+               return FALSE;
+
+       return TRUE;
+}
+
+static void inm_error_logger_service_data_cpy(inm_service_data_s *dest,
+                                             const inm_service_data_s *src)
+{
+       g_free(dest->name);
+       dest->name = g_strdup(src->name);
+       dest->type = src->type;
+       dest->error = dest->error;
+       dest->state_v4 = src->state_v4;
+       dest->state_v6 = src->state_v6;
+       dest->strength = src->strength;
+       dest->connect_reason = dest->connect_reason;
+}
+
+static gboolean inm_error_logger_tech_data_cmp(inm_tech_data_s *d1,
+                                              inm_tech_data_s *d2)
+{
+       __INM_FUNC_ENTER__;
+
+       if (d1->state != d2->state) {
+               __INM_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       if (d1->type != d2->type) {
+               __INM_FUNC_EXIT__;
+               return FALSE;
+       }
+
+       __INM_FUNC_EXIT__;
+       return TRUE;
+}
+
+static void inm_error_logger_tech_data_cpy(inm_tech_data_s *dest,
+                                          const inm_tech_data_s *src)
+{
+       dest->state = src->state;
+       dest->type = src->type;
+}
+
+void inm_error_logger_connman_service_msg(inm_service_data_s *data)
+{
+       __INM_FUNC_ENTER__;
+
+       if (inm_error_logger_service_data_cmp(data, &old_service_data))
+               return;
+
+       INM_LOGD("[ConnmanService] name (%s), type (%d), error (%d), "
+                "state_v4 (%d), state_v6 (%d), strength (%d), "
+                "connect_reason (%d), disconnection_requested (%d)",
+                data->name, data->type, data->error, data->state_v4,
+                data->state_v6, data->strength, data->connect_reason,
+                data->disconnection_requested);
+
+       if (old_service_data.state_v4 == data->state_v4 &&
+           old_service_data.state_v6 == data->state_v6) {
+
+               INM_LOGD("no change in connection state");
+               goto done;
+       }
+
+       if (old_service_data.error != data->error) {
+               if (data->error == CONNMAN_SERVICE_ERROR_INVALID_KEY) {
+                       /* check whether password mismatched or changed */
+                       INM_LOGD("check whether password mismatched or changed");
+                       if (data->connect_reason ==
+                           CONNMAN_SERVICE_CONNECT_REASON_AUTO)
+                               inm_error_analysis_diagnose(INM_NET_ERR_TYPE_AP_PASSWORD_CHANGED);
+                       else
+                               inm_error_analysis_diagnose(INM_NET_ERR_TYPE_AP_PASSWORD_MISMATCH);
+                       goto done;
+
+               } else if (data->error == CONNMAN_SERVICE_ERROR_DHCP_FAILED) {
+                       /* DHCP failed */
+                       INM_LOGD("DHCP failed");
+                       inm_error_analysis_diagnose(INM_NET_ERR_TYPE_DHCP_FAILED);
+                       goto done;
+
+               } else if (data->error == CONNMAN_SERVICE_ERROR_CONNECT_FAILED) {
+                       /* Connect failed */
+                       INM_LOGD("Connect failed");
+
+                       goto done;
+               }
+       }
+
+       if (old_service_data.state_v4 == CONNMAN_SERVICE_STATE_ONLINE &&
+           data->state_v4 == CONNMAN_SERVICE_STATE_READY &&
+           data->state_v6 != CONNMAN_SERVICE_STATE_ONLINE) {
+               INM_LOGD("No internet");
+               /* No internet */
+               inm_error_analysis_diagnose(INM_NET_ERR_TYPE_NO_INTERNET);
+
+       } else if (old_service_data.state_v6 == CONNMAN_SERVICE_STATE_ONLINE &&
+                  data->state_v6 == CONNMAN_SERVICE_STATE_READY &&
+                  data->state_v4 != CONNMAN_SERVICE_STATE_ONLINE) {
+               INM_LOGD("No internet");
+               /* No internet */
+               inm_error_analysis_diagnose(INM_NET_ERR_TYPE_NO_INTERNET);
+
+       } else if (data->state_v4 >= CONNMAN_SERVICE_STATE_DISCONNECT ||
+                  data->state_v6 >= CONNMAN_SERVICE_STATE_DISCONNECT) {
+               INM_LOGD("AP disconnected");
+               /* AP is out of range */
+               if (data->strength < 60)
+                       inm_error_analysis_diagnose(INM_NET_ERR_TYPE_AP_OUT_OF_RANGE);
+               /* Disconnection is user initiated */
+               else if (data->disconnection_requested == TRUE)
+                       inm_error_analysis_diagnose(INM_NET_ERR_TYPE_DISCONNECTION_BY_USER);
+               /* AP powered off */
+               else
+                       inm_error_analysis_diagnose(INM_NET_ERR_TYPE_AP_POWERED_OFF);
+       }
+
+done:
+       inm_error_logger_service_data_cpy(&old_service_data, data);
+
+       __INM_FUNC_EXIT__;
+}
+
+void inm_error_logger_connman_tech_msg(inm_tech_data_s *data)
+{
+       __INM_FUNC_ENTER__;
+
+       if (inm_error_logger_tech_data_cmp(data, &old_tech_data))
+               return;
+
+       INM_LOGD("[ConnmanTech] state (%d), type (%d)",
+                data->state, data->type);
+
+       /* Wi-Fi deactivated */
+       if (old_tech_data.state != data->state &&
+           data->state == CONNMAN_TECH_STATE_UNKNOWN) {
+              switch (data->type) {
+              case CONNMAN_SERVICE_TYPE_ETHERNET:
+                      inm_error_analysis_diagnose(INM_NET_ERR_TYPE_ETHERNET_OFF);
+                      break;
+              case CONNMAN_SERVICE_TYPE_WIFI:
+                      inm_error_analysis_diagnose(INM_NET_ERR_TYPE_WIFI_OFF);
+                      break;
+              default:
+                      break;
+              };
+       }
+
+       inm_error_logger_tech_data_cpy(&old_tech_data, data);
+
+       __INM_FUNC_EXIT__;
+}
diff --git a/src/inm-error-recovery.c b/src/inm-error-recovery.c
new file mode 100644 (file)
index 0000000..5f37071
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Network Monitoring Module
+ *
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * This file implements functions for network error recovery.
+ *
+ * @file        inm-error-recovery.c
+ * @author      Nishant Chaprana (n.chaprana@samsung.com)
+ * @version     0.1
+ */
+
+#include <glib.h>
+
+#include "inm-util.h"
+#include "inm-manager-log.h"
+#include "inm-error.h"
+#include "inm-error-analysis.h"
+#include "inm-error-recovery.h"
+
+void inm_error_recovery_execute(inm_net_err_type_e error_type)
+{
+       __INM_FUNC_ENTER__;
+
+       /* TODO: do recovery steps */
+
+       __INM_FUNC_EXIT__;
+}
index 38c411052cc3b1e2e371989a5b867264c992f235..f27bceb4d0df9c63b9b71489f65922391afbe36b 100644 (file)
@@ -34,6 +34,7 @@
 #include "inm-manager-log.h"
 #include "inm-rtnl.h"
 #include "inm-error.h"
+#include "inm-error-analysis.h"
 #include "inm-gdbus.h"
 
 #define INM_MANAGER_ERROR_QUARK g_quark_from_string("nm-manager-error-quark")
@@ -1286,6 +1287,24 @@ void inm_gdbus_emit_port_scan_result(GVariant * result)
        __INM_FUNC_EXIT__;
 }
 
+void inm_gdbus_emit_network_error_occured(int error_type)
+{
+       __INM_FUNC_ENTER__;
+
+       if (error_type <= INM_NET_ERR_TYPE_NONE) {
+               __INM_FUNC_EXIT__;
+               return;
+       }
+
+       inm_gdbus_emit_signal(NULL,
+                       INM_MANAGER_OBJ,
+                       INM_MANAGER_SERVICE,
+                       "NetworkErrorOccured",
+                       g_variant_new("(i)", error_type));
+
+       __INM_FUNC_EXIT__;
+}
+
 void inm_gdbus_emit_ethernet_cable_state(gboolean state)
 {
        GVariantBuilder *builder = NULL;
index 5212c71000b7b103a1f9508401ebc239a21c7835..f7d07742d3fb157aed1b27f2605241f7319414cd 100644 (file)
@@ -30,6 +30,7 @@
 #include "inm-util.h"
 #include "inm-manager-log.h"
 #include "inm-ip-conflict.h"
+#include "inm-error-analysis.h"
 
 #define ARP_PACKET_SIZE 60
 #define CONFLICT_REMOVE_ITERATION_LIMIT 4
@@ -125,6 +126,9 @@ static void __check_arp_receive(arp_message_s* ah, gpointer data)
 
        ip_conflict_data->iteration = 0;
        PRINT_LOG("<ip conflict:detected>");
+#ifdef BUILD_ERROR_ANALYSIS
+       inm_error_analysis_diagnose(INM_NET_ERR_TYPE_IP_CONFLICT);
+#endif
        ip_conflict_data->state = IP_CONFLICT_STATE_CONFLICT_DETECTED;
        ip_conflict_data->timeout = BURST_ARP_SEND_TIME;
        if (ip_conflict_data->cb)
index 8a87a27218c6feb368e03a21ad8ee1b087bcb66a..2acb43313587de6e2a1a815957e587fac972ca21 100644 (file)
@@ -42,6 +42,7 @@
 #include "inm-port-scan.h"
 #include "inm-manager-log.h"
 #include "inm-error.h"
+#include "inm-error-analysis.h"
 
 #define IF_NAME_ETH "eth0"
 
@@ -933,6 +934,11 @@ static void __ethernet_cable_state_changed_cb(char *iface_name, int state, void
        is_attached = state == 1;
 
        PRINT_LOG("<Ethernet cable %s:%s>", IF_NAME_ETH, is_attached ? "Attached" : "Detached");
+#ifdef BUILD_ERROR_ANALYSIS
+       if (is_attached == 0)
+               inm_error_analysis_diagnose(INM_NET_ERR_TYPE_ETHERNET_DETACHED);
+#endif
+
        inm_gdbus_emit_ethernet_cable_state(is_attached);
 }
 
@@ -944,6 +950,11 @@ static void __wifi_module_state_changed_cb(char *iface_name, int state, void *us
        is_attached = state == 1;
 
        PRINT_LOG("<WiFi module %s:%s>", IF_NAME_WLAN, is_attached ? "Attached" : "Detached");
+#ifdef BUILD_ERROR_ANALYSIS
+       if (is_attached == 0)
+               inm_error_analysis_diagnose(INM_NET_ERR_TYPE_WIFI_DETACHED);
+#endif
+
        inm_gdbus_emit_wifi_module_state(is_attached);
 }
 
@@ -1018,6 +1029,14 @@ void __channel_interference_cb(int freq, double channel_interference, gpointer u
        g_inm_manager->freq = freq;
        g_inm_manager->channel_interference = channel_interference;
        inm_gdbus_emit_channel_interference(freq, channel_interference);
+
+#ifdef BUILD_ERROR_ANALYSIS
+#if 0
+       /* TODO: transmit callback only when channel interference is high */
+       if (channel_interference > 40) /* High channel interference */
+               inm_error_analysis_diagnose(INM_NET_ERR_TYPE_CHANNEL_INTERFERENCE_HIGH);
+#endif
+#endif
        __INM_FUNC_EXIT__;
 }
 
@@ -1046,6 +1065,11 @@ void __congestion_mon_cb(int congestion_level, gpointer user_data)
        __INM_FUNC_ENTER__;
        g_inm_manager->congestion_level = congestion_level;
        inm_gdbus_emit_congestion_level_changed(congestion_level);
+
+#ifdef BUILD_ERROR_ANALYSIS
+       if (congestion_level > 40) /* High congestion */
+               inm_error_analysis_diagnose(INM_NET_ERR_TYPE_CONGESTED_NETWORK);
+#endif
        __INM_FUNC_EXIT__;
 }
 
index d6615579c369550c8402be53474a91dac5585e18..5a0641ea058b1bc6907fbce310b729c55e290012 100644 (file)
@@ -424,6 +424,7 @@ static inline void __get_iface_disconnect_reason(GVariant *value, inm_supplicant
 
        g_variant_get(value, "i", &reason);
        PRINT_LOG("<WPA event:Disconnect reason %d>", reason);
+       INM_LOGD("<WPA event:Disconnect reason %d>", reason);
 }
 
 static inline void __get_iface_property(const gchar *key, GVariant *value, inm_supplicant_iface_s *iface)
@@ -467,7 +468,9 @@ DECLARE_DBUS_SIGNAL_HANDLER(handle_scan_done)
 {
        __INM_FUNC_ENTER__;
 
-       PRINT_STR("<WPA event:Scan done>");
+       gboolean status = FALSE;
+
+       g_variant_get(parameters, "(b)", &status);
 
        __INM_FUNC_EXIT__;
        return;
@@ -477,8 +480,6 @@ DECLARE_DBUS_SIGNAL_HANDLER(handle_sta_authorized)
 {
        __INM_FUNC_ENTER__;
 
-       PRINT_STR("<WPA event:Sta authorized>");
-
        __INM_FUNC_EXIT__;
        return;
 }
@@ -487,8 +488,6 @@ DECLARE_DBUS_SIGNAL_HANDLER(handle_sta_deauthorized)
 {
        __INM_FUNC_ENTER__;
 
-       PRINT_STR("<WPA event:Sta deauthorized>");
-
        __INM_FUNC_EXIT__;
        return;
 }
index 08d5facb63c0bb269c03f819a851c6baee7d1bf1..87fb1b99ce3c53f2d5fc5a1fcfb78dc651494f66 100644 (file)
@@ -64,6 +64,7 @@
 
 #include "inm-util.h"
 #include "inm-manager-log.h"
+#include "inm-error-analysis.h"
 
 #define ARP_PACKET_SIZE 60