From d3e8351f241278b38cc9db6029c6c60863ee1ec7 Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Wed, 4 Mar 2026 13:52:09 -0500 Subject: [PATCH 1/2] RDKEMW-14959: Implement T2 Eventing in Network Manager Plugin (#282) * RDK-55826: Implement T2 Eventing in Network Manager Plugin Reason for Change: Added T2 marker for the identified T1 telemetry markers Test Procedure: Check whether the T2 events are received in the elk. Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR * RDK-55826: Implement T2 Eventing in Network Manager Plugin Reason for Change: Added T2 marker for the identified T1 telemetry markers Test Procedure: Check whether the T2 events are received in the elk. Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR --------- Signed-off-by: Gururaaja ESR --- CMakeLists.txt | 8 +- plugin/CMakeLists.txt | 9 +- plugin/NetworkManagerImplementation.cpp | 52 ++++++++++++ plugin/NetworkManagerImplementation.h | 1 + plugin/gnome/NetworkManagerGnomeEvents.cpp | 35 +++++++- plugin/gnome/NetworkManagerGnomeUtils.cpp | 97 ++++++++++++++++++++++ plugin/gnome/NetworkManagerGnomeUtils.h | 2 + plugin/gnome/NetworkManagerGnomeWIFI.cpp | 1 - tools/plugincli/CMakeLists.txt | 2 +- tools/upnp/CMakeLists.txt | 4 +- 10 files changed, 203 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b0c64c82..a0d5fdeb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,13 @@ if(ENABLE_ETHERNET_CONNECTION_HANDLING) add_definitions(-DENABLE_ETHERNET_CONNECTION_HANDLING) message(STATUS "Ethernet connection handling: enabled") endif() +option(USE_TELEMETRY "Enable Telemetry T2 support" OFF) + +if (USE_TELEMETRY) + find_package(T2 REQUIRED) + add_compile_definitions(USE_TELEMETRY=1) + message("Telemetry support enabled") +endif(USE_TELEMETRY) add_subdirectory(interface) add_subdirectory(definition) @@ -76,4 +83,3 @@ if(ENABLE_UNIT_TESTING) add_subdirectory(tests/l1Test) add_subdirectory(tests/l2Test) endif(ENABLE_UNIT_TESTING) - diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 3294912b..77dc8237 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -33,7 +33,9 @@ if (USE_RDK_LOGGER) include_directories(${RDKLOGGER_INCLUDE_DIRS}) endif (USE_RDK_LOGGER) - +if (USE_TELEMETRY) + include_directories(${T2_INCLUDE_DIRS}) +endif (USE_TELEMETRY) if(ENABLE_GNOME_NETWORKMANAGER) pkg_check_modules(GLIB REQUIRED glib-2.0) @@ -142,6 +144,11 @@ if (USE_RDK_LOGGER) target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${RDKLOGGER_LIBRARIES}) endif (USE_RDK_LOGGER) +if (USE_TELEMETRY) + target_link_libraries(${MODULE_NAME} PRIVATE ${T2_LIBRARIES}) + target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${T2_LIBRARIES}) +endif (USE_TELEMETRY) + install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) install(TARGETS ${MODULE_IMPL_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index e2b6e46a..c7d9cc57 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -20,6 +20,12 @@ #include #include #include "NetworkManagerImplementation.h" + +#if USE_TELEMETRY +#include "NetworkManagerJsonEnum.h" +#include +#endif + using namespace WPEFramework; using namespace WPEFramework::Plugin; using namespace NetworkManagerLogger; @@ -58,6 +64,10 @@ namespace WPEFramework NetworkManagerLogger::Init(); NMLOG_INFO((_T("NWMgrPlugin Out-Of-Process Instantiation; SHA: " _T(EXPAND_AND_QUOTE(PLUGIN_BUILD_REFERENCE))))); m_processMonThread = std::thread(&NetworkManagerImplementation::processMonitor, this, NM_PROCESS_MONITOR_INTERVAL_SEC); + #if USE_TELEMETRY + // Initialize Telemetry T2 for NwMgrPlugin + t2_init("NwMgrPlugin"); + #endif } NetworkManagerImplementation::~NetworkManagerImplementation() @@ -361,6 +371,13 @@ namespace WPEFramework interface = m_defaultInterface; ipaddress = result.public_ip; +#if USE_TELEMETRY + if(ipversion == "IPv4") + { + NMLOG_INFO("NM_PUBLIC_IPV4 = %s", ipaddress.c_str()); + logTelemetry("NM_PUBLIC_IPV4", ipaddress); + } +#endif return Core::ERROR_NONE; } else @@ -714,6 +731,10 @@ namespace WPEFramework for (const auto callback : _notificationCallbacks) { callback->onActiveInterfaceChange(prevActiveInterface, currentActiveinterface); } +#if USE_TELEMETRY + NMLOG_INFO("NM_INTERFACE_STATUS = Interface changed to %s", currentActiveinterface.c_str()); + logTelemetry("NM_INTERFACE_STATUS", "Interface changed to " + currentActiveinterface); +#endif _notificationLock.Unlock(); } @@ -760,9 +781,24 @@ namespace WPEFramework { _notificationLock.Lock(); NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); +#if USE_TELEMETRY + // Log error only when ethernet is down and there's no internet + if(currState == Exchange::INetworkManager::INTERNET_NOT_AVAILABLE && + !m_ethConnected.load() && + prevState != Exchange::INetworkManager::INTERNET_NOT_AVAILABLE) + { + NMLOG_INFO("NM_ETHERNET_CONNECTIVITY = Ethernet connectivity failed"); + logTelemetry("NM_ETHERNET_CONNECTIVITY", "Ethernet connectivity failed"); + } +#endif for (const auto callback : _notificationCallbacks) { callback->onInternetStatusChange(prevState, currState, interface); } +#if USE_TELEMETRY + string stateStr = Core::EnumerateType(currState).Data(); + NMLOG_INFO("NM_INTERNET_STATUS = %s", stateStr.c_str()); + logTelemetry("NM_INTERNET_STATUS", stateStr); +#endif _notificationLock.Unlock(); } @@ -1111,6 +1147,11 @@ namespace WPEFramework _notificationLock.Lock(); NMLOG_INFO("Posting onWiFiStateChange (%d)", state); +#if USE_TELEMETRY + string stateStr = Core::EnumerateType(state).Data(); + NMLOG_INFO("NM_WIFI_STATUS = %s", stateStr.c_str()); + logTelemetry("NM_WIFI_STATUS", stateStr); +#endif for (const auto callback : _notificationCallbacks) { callback->onWiFiStateChange(state); } @@ -1246,5 +1287,16 @@ namespace WPEFramework } } } + + void NetworkManagerImplementation::logTelemetry(const std::string& eventName, const std::string& message) + { +#if USE_TELEMETRY + T2ERROR t2error = t2_event_s(eventName.c_str(), const_cast(message.c_str())); + if (t2error != T2ERROR_SUCCESS) { + NMLOG_ERROR("t2_event_s(\"%s\", \"%s\") failed with error %d", + eventName.c_str(), message.c_str(), t2error); + } +#endif + } } } diff --git a/plugin/NetworkManagerImplementation.h b/plugin/NetworkManagerImplementation.h index 793dc4c0..827854ec 100644 --- a/plugin/NetworkManagerImplementation.h +++ b/plugin/NetworkManagerImplementation.h @@ -275,6 +275,7 @@ namespace WPEFramework void ReportAvailableSSIDs(const JsonArray &arrayofWiFiScanResults); void ReportWiFiStateChange(const Exchange::INetworkManager::WiFiState state); void ReportWiFiSignalQualityChange(const string ssid, const int strength, const int noise, const int snr, const Exchange::INetworkManager::WiFiSignalQuality quality); + void logTelemetry(const std::string& eventName, const std::string& message); // INetworkPowerCallback overrides void OnPowerModePreChange(const Exchange::IPowerManager::PowerState currentState, diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index 90f9b03f..fd6ab361 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -271,8 +271,41 @@ namespace WPEFramework } if (nm_ip_address_get_family(address) == AF_INET) { const char *ipAddress = nm_ip_address_get_address(address); - if(ipAddress != NULL) + if(ipAddress != NULL) { GnomeNetworkManagerEvents::onAddressChangeCb(iface, ipAddress, true, false); + // Get gateway MAC address for WiFi and Ethernet after IP is acquired + if(ifname == nmUtils::wlanIface() || ifname == nmUtils::ethIface()) { + static std::map gatewayMacCache; + NMClient *client = nm_object_get_client(NM_OBJECT(device)); + if (client != NULL) { + std::string gatewayMac = nmUtils::getGatewayMacAddress(client, ifname); + if (!gatewayMac.empty()) { + // Only log when MAC changes or is first time + if (gatewayMacCache[ifname] != gatewayMac) { + gatewayMacCache[ifname] = gatewayMac; +#if USE_TELEMETRY + if(ifname == nmUtils::wlanIface()) + { + NMLOG_INFO("NM_WIFI_GW_MAC = %s", gatewayMac.c_str()); + if (_instance != nullptr) + { + _instance->logTelemetry("NM_WIFI_GW_MAC", gatewayMac); + } + } + else if(ifname == nmUtils::ethIface()) + { + NMLOG_INFO("NM_ETHERNET_GW_MAC = %s", gatewayMac.c_str()); + if (_instance != nullptr) + { + _instance->logTelemetry("NM_ETHERNET_GW_MAC", gatewayMac); + } + } +#endif + } + } + } + } + } } } } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index d175b27a..394fedbb 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include "Module.h" @@ -389,5 +391,100 @@ namespace WPEFramework return false; } + std::string nmUtils::resolveGatewayMac(const std::string& gatewayIp) + { + std::string mac = ""; + std::string arpFile = "/proc/net/arp"; + std::ifstream file(arpFile); + std::string line; + + if (!file.is_open()) { + NMLOG_ERROR("Failed to open %s", arpFile.c_str()); + return mac; + } + + // Skip header + std::getline(file, line); + + while (std::getline(file, line)) { + std::istringstream iss(line); + std::string ip, hwType, flags, hwAddr; + + if (iss >> ip >> hwType >> flags >> hwAddr) { + if (ip == gatewayIp && hwAddr != "00:00:00:00:00:00") { + mac = hwAddr; + NMLOG_INFO("Resolved gateway IP %s to MAC %s", gatewayIp.c_str(), mac.c_str()); + break; + } + } + } + + if (mac.empty()) { + NMLOG_WARNING("Could not resolve gateway IP %s to MAC address", gatewayIp.c_str()); + } + + return mac; + } + + std::string nmUtils::getGatewayMacAddress(NMClient* client, const std::string& interface) + { + std::string gatewayMac = ""; + + if (client == NULL) { + NMLOG_ERROR("NMClient is NULL"); + return gatewayMac; + } + + if (interface.empty()) { + NMLOG_ERROR("Interface name is empty"); + return gatewayMac; + } + + // Get all active connections and find the one for our interface + const GPtrArray *activeConnections = nm_client_get_active_connections(client); + if (!activeConnections) { + NMLOG_WARNING("No active connections found"); + return gatewayMac; + } + + for (guint i = 0; i < activeConnections->len; i++) { + NMActiveConnection *activeConn = NM_ACTIVE_CONNECTION(g_ptr_array_index(activeConnections, i)); + if (!activeConn) continue; + + // Get devices for this connection + const GPtrArray *devices = nm_active_connection_get_devices(activeConn); + if (!devices) continue; + + // Check if this connection belongs to our interface + for (guint j = 0; j < devices->len; j++) { + NMDevice *device = NM_DEVICE(g_ptr_array_index(devices, j)); + if (!device) continue; + + const char *ifname = nm_device_get_iface(device); + if (ifname && interface == ifname) { + // Found the connection for our interface + NMIPConfig *ip4Config = nm_active_connection_get_ip4_config(activeConn); + if (ip4Config) { + const char *gateway = nm_ip_config_get_gateway(ip4Config); + if (gateway) { + NMLOG_DEBUG("Found gateway IP for %s: %s", interface.c_str(), gateway); + // Use ARP to resolve gateway IP to MAC address + gatewayMac = resolveGatewayMac(gateway); + return gatewayMac; + } else { + NMLOG_WARNING("No gateway found for %s", interface.c_str()); + } + } else { + NMLOG_WARNING("No IPv4 configuration found for %s", interface.c_str()); + } + return gatewayMac; + } + } + } + + NMLOG_WARNING("No active connection found for interface %s", interface.c_str()); + return gatewayMac; + } + } // Plugin } // WPEFramework diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index b9632d2e..dbfb24b1 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -50,6 +50,8 @@ namespace WPEFramework static bool isInterfaceEnabled(const std::string& interface); static bool writePersistentHostname(const std::string& hostname); static bool readPersistentHostname(std::string& hostname); + static std::string resolveGatewayMac(const std::string& gatewayIp); + static std::string getGatewayMacAddress(NMClient* client, const std::string& interface); }; } } diff --git a/plugin/gnome/NetworkManagerGnomeWIFI.cpp b/plugin/gnome/NetworkManagerGnomeWIFI.cpp index ff06ff5c..64d49d9f 100644 --- a/plugin/gnome/NetworkManagerGnomeWIFI.cpp +++ b/plugin/gnome/NetworkManagerGnomeWIFI.cpp @@ -1144,7 +1144,6 @@ m_cancellable(nullptr){ std::string activeSSID{}; NMLOG_DEBUG("wifi connect ssid: %s, security %d persist %d", ssidInfoParam.ssid.c_str(), ssidInfoParam.security, ssidInfoParam.persist); - Exchange::INetworkManager::WiFiConnectTo ssidInfo = ssidInfoParam; m_isSuccess = false; if(!createClientNewConnection()) diff --git a/tools/plugincli/CMakeLists.txt b/tools/plugincli/CMakeLists.txt index e1f5fd62..56883676 100644 --- a/tools/plugincli/CMakeLists.txt +++ b/tools/plugincli/CMakeLists.txt @@ -85,7 +85,7 @@ if(ENABLE_GNOME_GDBUS) target_compile_options(${PLUGIN_GDBUS_CLI} PRIVATE ${COMMON_COMPILE_OPTIONS}) target_include_directories(${PLUGIN_GDBUS_CLI} PRIVATE ${COMMON_INCLUDES}) - target_link_libraries(${PLUGIN_GDBUS_CLI} PRIVATE ${COMMON_LIBS} uuid) + target_link_libraries(${PLUGIN_GDBUS_CLI} PRIVATE ${COMMON_LIBS} ${LIBNM_LIBRARIES} uuid) install(TARGETS ${PLUGIN_GDBUS_CLI} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) diff --git a/tools/upnp/CMakeLists.txt b/tools/upnp/CMakeLists.txt index 1cfa40e8..788f0540 100644 --- a/tools/upnp/CMakeLists.txt +++ b/tools/upnp/CMakeLists.txt @@ -34,9 +34,7 @@ if (NOT GUPNP_FOUND) endif () if (USE_TELEMETRY) - find_package(T2 REQUIRED) - add_definitions(-DUSE_TELEMETRY) - include_directories(${TELEMETRY_INCLUDE_DIRS}) + include_directories(${T2_INCLUDE_DIRS}) endif (USE_TELEMETRY) add_definitions(-DENABLE_ROUTER_DISCOVERY_MAIN) From 5b18f09c869e9893862dd6fa86875f5755295b1c Mon Sep 17 00:00:00 2001 From: gururaajar <83449026+gururaajar@users.noreply.github.com> Date: Thu, 19 Mar 2026 10:38:13 -0400 Subject: [PATCH 2/2] RDKEMW-14959: Implement T2 Eventing in Network Manager Plugin (#292) * RDKEMW-14959: Implement T2 Eventing in Network Manager Plugin Reason for Change: Added T2 marker for the identified T1 telemetry markers Test Procedure: Check whether the T2 events are received in the elk. Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR * RDKEMW-14959: Implement T2 Eventing in Network Manager Plugin Reason for Change: Added T2 marker for the identified T1 telemetry markers Test Procedure: Check whether the T2 events are received in the elk. Priority: P1 Risks: Medium Signed-off-by: Gururaaja ESR --------- Signed-off-by: Gururaaja ESR --- plugin/NetworkManagerImplementation.cpp | 10 ++- plugin/gnome/NetworkManagerGnomeEvents.cpp | 61 +++++++++---------- plugin/gnome/NetworkManagerGnomeUtils.cpp | 58 +++++------------- plugin/gnome/NetworkManagerGnomeUtils.h | 2 +- tests/l2Test/libnm/CMakeLists.txt | 5 ++ .../l2Test/libnm/l2_test_libnmproxyEvent.cpp | 51 ++++++++++++++-- tests/mocks/LibnmWraps.cpp | 9 +++ tests/mocks/LibnmWraps.h | 2 + tests/mocks/LibnmWrapsMock.h | 4 ++ 9 files changed, 118 insertions(+), 84 deletions(-) diff --git a/plugin/NetworkManagerImplementation.cpp b/plugin/NetworkManagerImplementation.cpp index c7d9cc57..8e15ff28 100644 --- a/plugin/NetworkManagerImplementation.cpp +++ b/plugin/NetworkManagerImplementation.cpp @@ -377,6 +377,11 @@ namespace WPEFramework NMLOG_INFO("NM_PUBLIC_IPV4 = %s", ipaddress.c_str()); logTelemetry("NM_PUBLIC_IPV4", ipaddress); } + else + { + NMLOG_INFO("NM_PUBLIC_IPV6 = %s", ipaddress.c_str()); + logTelemetry("NM_PUBLIC_IPV6", ipaddress); + } #endif return Core::ERROR_NONE; } @@ -782,9 +787,10 @@ namespace WPEFramework _notificationLock.Lock(); NMLOG_INFO("Posting onInternetStatusChange with current state as %u", (unsigned)currState); #if USE_TELEMETRY - // Log error only when ethernet is down and there's no internet + // Log error only when ethernet is up and there's no internet if(currState == Exchange::INetworkManager::INTERNET_NOT_AVAILABLE && - !m_ethConnected.load() && + m_ethConnected.load() && + interface == "eth0" && prevState != Exchange::INetworkManager::INTERNET_NOT_AVAILABLE) { NMLOG_INFO("NM_ETHERNET_CONNECTIVITY = Ethernet connectivity failed"); diff --git a/plugin/gnome/NetworkManagerGnomeEvents.cpp b/plugin/gnome/NetworkManagerGnomeEvents.cpp index fd6ab361..16bf3376 100644 --- a/plugin/gnome/NetworkManagerGnomeEvents.cpp +++ b/plugin/gnome/NetworkManagerGnomeEvents.cpp @@ -163,6 +163,20 @@ namespace WPEFramework case NM_DEVICE_STATE_ACTIVATED: wifiState = "WIFI_STATE_CONNECTED"; GnomeNetworkManagerEvents::onWIFIStateChanged(Exchange::INetworkManager::WIFI_STATE_CONNECTED); +#if USE_TELEMETRY + { + static std::string lastWlanGatewayMac; + std::string gatewayMac = nmUtils::getGatewayMacAddress(device); + if (!gatewayMac.empty() && lastWlanGatewayMac != gatewayMac) { + lastWlanGatewayMac = gatewayMac; + NMLOG_INFO("NM_WIFI_GW_MAC = %s", gatewayMac.c_str()); + if (_instance != nullptr) + { + _instance->logTelemetry("NM_WIFI_GW_MAC", gatewayMac); + } + } + } +#endif break; case NM_DEVICE_STATE_DEACTIVATING: wifiState = "WIFI_STATE_CONNECTION_LOST"; @@ -211,9 +225,22 @@ namespace WPEFramework case NM_DEVICE_STATE_IP_CONFIG: GnomeNetworkManagerEvents::onInterfaceStateChangeCb(Exchange::INetworkManager::INTERFACE_ACQUIRING_IP, nmUtils::ethIface()); break; + case NM_DEVICE_STATE_ACTIVATED: +#if USE_TELEMETRY + { + static std::string lastEthGatewayMac; + std::string gatewayMac = nmUtils::getGatewayMacAddress(device); + if (!gatewayMac.empty() && lastEthGatewayMac != gatewayMac) { + lastEthGatewayMac = gatewayMac; + NMLOG_INFO("NM_ETHERNET_GW_MAC = %s", gatewayMac.c_str()); + if (_instance != nullptr) + _instance->logTelemetry("NM_ETHERNET_GW_MAC", gatewayMac); + } + } +#endif + break; case NM_DEVICE_STATE_NEED_AUTH: case NM_DEVICE_STATE_SECONDARIES: - case NM_DEVICE_STATE_ACTIVATED: case NM_DEVICE_STATE_DEACTIVATING: default: NMLOG_WARNING("Unhandiled state change %d", deviceState); @@ -273,38 +300,6 @@ namespace WPEFramework const char *ipAddress = nm_ip_address_get_address(address); if(ipAddress != NULL) { GnomeNetworkManagerEvents::onAddressChangeCb(iface, ipAddress, true, false); - // Get gateway MAC address for WiFi and Ethernet after IP is acquired - if(ifname == nmUtils::wlanIface() || ifname == nmUtils::ethIface()) { - static std::map gatewayMacCache; - NMClient *client = nm_object_get_client(NM_OBJECT(device)); - if (client != NULL) { - std::string gatewayMac = nmUtils::getGatewayMacAddress(client, ifname); - if (!gatewayMac.empty()) { - // Only log when MAC changes or is first time - if (gatewayMacCache[ifname] != gatewayMac) { - gatewayMacCache[ifname] = gatewayMac; -#if USE_TELEMETRY - if(ifname == nmUtils::wlanIface()) - { - NMLOG_INFO("NM_WIFI_GW_MAC = %s", gatewayMac.c_str()); - if (_instance != nullptr) - { - _instance->logTelemetry("NM_WIFI_GW_MAC", gatewayMac); - } - } - else if(ifname == nmUtils::ethIface()) - { - NMLOG_INFO("NM_ETHERNET_GW_MAC = %s", gatewayMac.c_str()); - if (_instance != nullptr) - { - _instance->logTelemetry("NM_ETHERNET_GW_MAC", gatewayMac); - } - } -#endif - } - } - } - } } } } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.cpp b/plugin/gnome/NetworkManagerGnomeUtils.cpp index 394fedbb..c819e17b 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.cpp +++ b/plugin/gnome/NetworkManagerGnomeUtils.cpp @@ -426,63 +426,35 @@ namespace WPEFramework return mac; } - std::string nmUtils::getGatewayMacAddress(NMClient* client, const std::string& interface) + std::string nmUtils::getGatewayMacAddress(NMDevice* device) { std::string gatewayMac = ""; - if (client == NULL) { - NMLOG_ERROR("NMClient is NULL"); + if (!device) { + NMLOG_ERROR("device is NULL"); return gatewayMac; } - if (interface.empty()) { - NMLOG_ERROR("Interface name is empty"); + if (!NM_IS_DEVICE(device)) { + NMLOG_ERROR("device is not an NMDevice"); return gatewayMac; } - // Get all active connections and find the one for our interface - const GPtrArray *activeConnections = nm_client_get_active_connections(client); - if (!activeConnections) { - NMLOG_WARNING("No active connections found"); + NMIPConfig *ip4Config = nm_device_get_ip4_config(device); + if (!ip4Config) { + NMLOG_WARNING("No IPv4 configuration found"); return gatewayMac; } - for (guint i = 0; i < activeConnections->len; i++) { - NMActiveConnection *activeConn = NM_ACTIVE_CONNECTION(g_ptr_array_index(activeConnections, i)); - if (!activeConn) continue; - - // Get devices for this connection - const GPtrArray *devices = nm_active_connection_get_devices(activeConn); - if (!devices) continue; - - // Check if this connection belongs to our interface - for (guint j = 0; j < devices->len; j++) { - NMDevice *device = NM_DEVICE(g_ptr_array_index(devices, j)); - if (!device) continue; - - const char *ifname = nm_device_get_iface(device); - if (ifname && interface == ifname) { - // Found the connection for our interface - NMIPConfig *ip4Config = nm_active_connection_get_ip4_config(activeConn); - if (ip4Config) { - const char *gateway = nm_ip_config_get_gateway(ip4Config); - if (gateway) { - NMLOG_DEBUG("Found gateway IP for %s: %s", interface.c_str(), gateway); - // Use ARP to resolve gateway IP to MAC address - gatewayMac = resolveGatewayMac(gateway); - return gatewayMac; - } else { - NMLOG_WARNING("No gateway found for %s", interface.c_str()); - } - } else { - NMLOG_WARNING("No IPv4 configuration found for %s", interface.c_str()); - } - return gatewayMac; - } - } + const char *ifname = nm_device_get_iface(device); + const char *gateway = nm_ip_config_get_gateway(ip4Config); + if (!gateway) { + NMLOG_WARNING("No gateway found for %s", ifname ? ifname : "unknown"); + return gatewayMac; } - NMLOG_WARNING("No active connection found for interface %s", interface.c_str()); + NMLOG_DEBUG("Found gateway IP for %s: %s", ifname ? ifname : "unknown", gateway); + gatewayMac = resolveGatewayMac(gateway); return gatewayMac; } diff --git a/plugin/gnome/NetworkManagerGnomeUtils.h b/plugin/gnome/NetworkManagerGnomeUtils.h index dbfb24b1..c74944c8 100644 --- a/plugin/gnome/NetworkManagerGnomeUtils.h +++ b/plugin/gnome/NetworkManagerGnomeUtils.h @@ -51,7 +51,7 @@ namespace WPEFramework static bool writePersistentHostname(const std::string& hostname); static bool readPersistentHostname(std::string& hostname); static std::string resolveGatewayMac(const std::string& gatewayIp); - static std::string getGatewayMacAddress(NMClient* client, const std::string& interface); + static std::string getGatewayMacAddress(NMDevice* device); }; } } diff --git a/tests/l2Test/libnm/CMakeLists.txt b/tests/l2Test/libnm/CMakeLists.txt index 9f8a07bc..9b1a44d0 100644 --- a/tests/l2Test/libnm/CMakeLists.txt +++ b/tests/l2Test/libnm/CMakeLists.txt @@ -30,6 +30,7 @@ add_executable(${NM_LIBNM_PROXY_L2_TEST} ${CMAKE_SOURCE_DIR}/tests/mocks/thunder/Module.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/Iarm.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/Wraps.cpp + ${CMAKE_SOURCE_DIR}/tests/mocks/CurlWraps.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/LibnmWraps.cpp ${CMAKE_SOURCE_DIR}/tests/mocks/GLibWraps.cpp ${CMAKE_SOURCE_DIR}/plugin/NetworkManager.cpp @@ -164,6 +165,10 @@ target_link_options(${NM_LIBNM_PROXY_L2_TEST} PUBLIC -Wl,-wrap,nm_remote_connection_delete -Wl,-wrap,nm_remote_connection_delete_finish -Wl,-wrap,nm_access_point_connection_valid + -Wl,-wrap,curl_multi_perform + -Wl,-wrap,curl_multi_info_read + -Wl,-wrap,curl_multi_poll + -Wl,-wrap,nm_device_get_ip4_config ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") diff --git a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp index 2a83d168..61ba95e1 100644 --- a/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp +++ b/tests/l2Test/libnm/l2_test_libnmproxyEvent.cpp @@ -26,6 +26,7 @@ #include "FactoriesImplementation.h" #include "WrapsMock.h" +#include "CurlWrapsMock.h" #include "LibnmWrapsMock.h" #include "GLibWrapsMock.h" #include "ServiceMock.h" @@ -54,6 +55,7 @@ class NetworkManagerEventTest : public ::testing::Test { GCallback nmStateChange = NULL; WrapsImplMock *p_wrapsImplMock = nullptr; + CurlWrapsImplMock *p_curlWrapsImplMock = nullptr; GLibWrapsImplMock *p_gLibWrapsImplMock = nullptr; LibnmWrapsImplMock *p_libnmWrapsImplMock = nullptr; Core::ProxyType NetworkManagerImpl; @@ -79,6 +81,18 @@ class NetworkManagerEventTest : public ::testing::Test { p_wrapsImplMock = new NiceMock ; Wraps::setImpl(p_wrapsImplMock); + + p_curlWrapsImplMock = new NiceMock ; + CurlWraps::setImpl(p_curlWrapsImplMock); + ON_CALL(*p_curlWrapsImplMock, curl_multi_perform(::testing::_, ::testing::_)) + .WillByDefault(::testing::DoAll( + ::testing::SetArgPointee<1>(0), + ::testing::Return(CURLM_OK))); + ON_CALL(*p_curlWrapsImplMock, curl_multi_info_read(::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(nullptr)); + ON_CALL(*p_curlWrapsImplMock, curl_multi_poll(::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .WillByDefault(::testing::Return(CURLM_OK)); + ON_CALL(service, COMLink()) .WillByDefault(::testing::Invoke( [this]() { @@ -158,6 +172,13 @@ class NetworkManagerEventTest : public ::testing::Test { p_wrapsImplMock = nullptr; } + CurlWraps::setImpl(nullptr); + if (p_curlWrapsImplMock != nullptr) + { + delete p_curlWrapsImplMock; + p_curlWrapsImplMock = nullptr; + } + LibnmWraps::setImpl(nullptr); if (p_libnmWrapsImplMock != nullptr) { @@ -257,6 +278,7 @@ TEST_F(NetworkManagerEventTest, onWIFIStateChanged) TEST_F(NetworkManagerEventTest, deviceStateChangeCb) { + NMDevice *ethDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); NMDevice *wifiDummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_WIFI, NULL)); EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)) @@ -299,11 +321,11 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb) // Test with nullptr and with mock device WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(nullptr, nullptr, nullptr); - WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); - WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); - WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); - WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); - WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(0x100179), nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(ethDummyDevice, nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(ethDummyDevice, nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(ethDummyDevice, nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(ethDummyDevice, nullptr, nullptr); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(ethDummyDevice, nullptr, nullptr); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); @@ -311,6 +333,8 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb) WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(wifiDummyDevice), nullptr, nullptr); + g_object_unref(ethDummyDevice); + g_object_unref(wifiDummyDevice); } TEST_F(NetworkManagerEventTest, deviceStateChangeCb_activated) @@ -467,6 +491,7 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_unmanaged) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); + g_object_unref(DummyDevice); } TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_disconnected) @@ -479,6 +504,7 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_disconnected) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); + g_object_unref(DummyDevice); } TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_prepare) @@ -491,6 +517,7 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_prepare) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); + g_object_unref(DummyDevice); } TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_ipconfig) @@ -503,4 +530,18 @@ TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_ipconfig) EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(reinterpret_cast(DummyDevice), nullptr, nullptr); + g_object_unref(DummyDevice); +} + +TEST_F(NetworkManagerEventTest, deviceStateChangeCb_eth0_activated) +{ + NMDevice *DummyDevice = static_cast(g_object_new(NM_TYPE_DEVICE_ETHERNET, NULL)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_ACTIVATED)); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_iface(::testing::_)) + .WillOnce(::testing::Return("eth0")); + EXPECT_CALL(*p_libnmWrapsImplMock, nm_device_get_state_reason(::testing::_)) + .WillOnce(::testing::Return(NM_DEVICE_STATE_REASON_NONE)); + WPEFramework::Plugin::GnomeNetworkManagerEvents::deviceStateChangeCb(DummyDevice, nullptr, nullptr); + g_object_unref(DummyDevice); } diff --git a/tests/mocks/LibnmWraps.cpp b/tests/mocks/LibnmWraps.cpp index 0a5741fb..3e039fd4 100644 --- a/tests/mocks/LibnmWraps.cpp +++ b/tests/mocks/LibnmWraps.cpp @@ -134,6 +134,10 @@ extern "C" const char* __wrap_nm_setting_connection_get_interface_name(NMSetting return LibnmWraps::getInstance().nm_setting_connection_get_interface_name(setting); } +extern "C" NMIPConfig* __wrap_nm_device_get_ip4_config(NMDevice* device) { + return LibnmWraps::getInstance().nm_device_get_ip4_config(device); +} + extern "C" NMIPConfig* __wrap_nm_active_connection_get_ip4_config(NMActiveConnection* connection) { return LibnmWraps::getInstance().nm_active_connection_get_ip4_config(connection); } @@ -435,6 +439,11 @@ const char* LibnmWraps::nm_setting_connection_get_interface_name(NMSettingConnec return impl->nm_setting_connection_get_interface_name(setting); } +NMIPConfig* LibnmWraps::nm_device_get_ip4_config(NMDevice* device) { + EXPECT_NE(impl, nullptr); + return impl->nm_device_get_ip4_config(device); +} + NMIPConfig* LibnmWraps::nm_active_connection_get_ip4_config(NMActiveConnection* connection) { EXPECT_NE(impl, nullptr); return impl->nm_active_connection_get_ip4_config(connection); diff --git a/tests/mocks/LibnmWraps.h b/tests/mocks/LibnmWraps.h index dc62f0a9..e492e64d 100644 --- a/tests/mocks/LibnmWraps.h +++ b/tests/mocks/LibnmWraps.h @@ -33,6 +33,7 @@ class LibnmWrapsImpl { virtual const char* nm_setting_ip_config_get_method(NMSettingIPConfig* setting) = 0; virtual NMSettingConnection* nm_connection_get_setting_connection(NMConnection* connection) = 0; virtual const char* nm_setting_connection_get_interface_name(NMSettingConnection* setting) = 0; + virtual NMIPConfig* nm_device_get_ip4_config(NMDevice* device) = 0; virtual NMIPConfig* nm_active_connection_get_ip4_config(NMActiveConnection* connection) = 0; virtual NMIPConfig* nm_active_connection_get_ip6_config(NMActiveConnection* connection) = 0; virtual GPtrArray* nm_ip_config_get_addresses(NMIPConfig* config) = 0; @@ -220,6 +221,7 @@ class LibnmWraps { static const char* nm_setting_ip_config_get_method(NMSettingIPConfig* setting); static NMSettingConnection* nm_connection_get_setting_connection(NMConnection* connection); static const char* nm_setting_connection_get_interface_name(NMSettingConnection* setting); + static NMIPConfig* nm_device_get_ip4_config(NMDevice* device); static NMIPConfig* nm_active_connection_get_ip4_config(NMActiveConnection* connection); static NMIPConfig* nm_active_connection_get_ip6_config(NMActiveConnection* connection); static GPtrArray* nm_ip_config_get_addresses(NMIPConfig* config); diff --git a/tests/mocks/LibnmWrapsMock.h b/tests/mocks/LibnmWrapsMock.h index a728ac94..5fb09e69 100644 --- a/tests/mocks/LibnmWrapsMock.h +++ b/tests/mocks/LibnmWrapsMock.h @@ -28,6 +28,7 @@ extern "C" NMSettingIPConfig* __real_nm_connection_get_setting_ip6_config(NMConn extern "C" const char* __real_nm_setting_ip_config_get_method(NMSettingIPConfig* setting); extern "C" NMSettingConnection* __real_nm_connection_get_setting_connection(NMConnection* connection); extern "C" const char* __real_nm_setting_connection_get_interface_name(NMSettingConnection* setting); +extern "C" NMIPConfig* __real_nm_device_get_ip4_config(NMDevice* device); extern "C" NMIPConfig* __real_nm_active_connection_get_ip4_config(NMActiveConnection* connection); extern "C" NMIPConfig* __real_nm_active_connection_get_ip6_config(NMActiveConnection* connection); extern "C" GPtrArray* __real_nm_ip_config_get_addresses(NMIPConfig* config); @@ -491,6 +492,8 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { [&](NMClient *client, GAsyncResult *result, GError **error) -> gboolean { return __real_nm_client_dbus_set_property_finish(client, result, error); })); + ON_CALL(*this, nm_device_get_ip4_config(::testing::_)) + .WillByDefault(::testing::Return(nullptr)); ON_CALL(*this, nm_remote_connection_delete(::testing::_, ::testing::_, ::testing::_)) .WillByDefault(::testing::Invoke( [&](NMRemoteConnection *connection, GCancellable *cancellable, GError **error) -> gboolean { @@ -589,4 +592,5 @@ class LibnmWrapsImplMock : public LibnmWrapsImpl { MOCK_METHOD(NMDeviceStateReason, nm_device_get_state_reason, (NMDevice *device), (override)); MOCK_METHOD(int, nm_ip_address_get_family, (NMIPAddress *address), (override)); MOCK_METHOD(GVariant*, nm_connection_to_dbus, (NMConnection *connection, NMConnectionSerializationFlags flags), (override)); + MOCK_METHOD(NMIPConfig*, nm_device_get_ip4_config, (NMDevice* device), (override)); };