diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 00000000..1aa7ef79
Binary files /dev/null and b/.DS_Store differ
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0b73f231..768ab64c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,6 +54,7 @@ get_directory_property(SEVICES_DEFINES COMPILE_DEFINITIONS)
option(ENABLE_LEGACY_PLUGINS "Enable Legacy Plugins" ON)
option(USE_RDK_LOGGER "Enable RDK Logger for logging" OFF )
option(ENABLE_UNIT_TESTING "Enable unit tests" OFF)
+option(USE_TELEMETRY "Enable Telemetry support for NetworkConnectionStats" ON)
add_subdirectory(interface)
@@ -64,6 +65,8 @@ if (ENABLE_LEGACY_PLUGINS)
add_subdirectory(legacy)
endif (ENABLE_LEGACY_PLUGINS)
+add_subdirectory(networkstats)
+
add_subdirectory(tools)
if(ENABLE_UNIT_TESTING)
diff --git a/networkstats/CMakeLists.txt b/networkstats/CMakeLists.txt
new file mode 100644
index 00000000..1c6329dc
--- /dev/null
+++ b/networkstats/CMakeLists.txt
@@ -0,0 +1,37 @@
+#############################################################################
+# If not stated otherwise in this file or this component's LICENSE file the
+# following copyright and licenses apply:
+#
+# Copyright 2025 RDK Management
+#
+# 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.
+#############################################################################
+cmake_minimum_required(VERSION 3.3)
+
+project(NetworkConnectionStats)
+
+find_package(WPEFramework QUIET CONFIG)
+
+message("Building ${PROJECT_NAME} Thunder Plugin (Internal-only, no external APIs)")
+
+# Set project version
+set(PROJECT_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
+
+# Build interface (ProxyStub generation)
+add_subdirectory(interface)
+
+# Build definition (JSON-RPC documentation)
+#add_subdirectory(definition)
+
+# Build plugin
+add_subdirectory(plugin)
diff --git a/networkstats/NetworkStatsDesign_ver1.md b/networkstats/NetworkStatsDesign_ver1.md
new file mode 100644
index 00000000..564bab73
--- /dev/null
+++ b/networkstats/NetworkStatsDesign_ver1.md
@@ -0,0 +1,455 @@
+# NetworkStats Module Design Document
+
+## Overview
+NetworkStats is a Thunder plugin that runs out-of-process and monitors network connectivity by subscribing to NetworkManager plugin events. It periodically collects network statistics and sends T2 telemetry events.
+
+## Architecture
+
+### Key Components
+- **NetworkStats Plugin**: Main Thunder plugin (out-of-process)
+- **NetworkManager Interface**: COM-RPC connection to NetworkManager plugin
+- **Timer Thread**: Periodic statistics collection (10-minute interval)
+- **T2 Telemetry Client**: Sends telemetry events
+- **Event Subscription Manager**: Manages NetworkManager event subscriptions
+
+---
+
+## Sequence Diagram
+
+```mermaid
+sequenceDiagram
+ participant Thunder as Thunder Framework
+ participant NS as NetworkStats Plugin
+ participant NM as NetworkManager Plugin
+ participant Timer as Timer Thread
+ participant T2 as T2 Telemetry
+
+ Note over Thunder,T2: Plugin Initialization
+ Thunder->>NS: Initialize(IShell* service)
+ activate NS
+ NS->>NS: Create NetworkStatsImplementation
+ NS->>Thunder: Register notification callbacks
+ NS->>NM: Establish COM-RPC connection
+ activate NM
+ NM-->>NS: Connection established
+ NS->>NM: Register(¬ification)
+ NS->>NM: Subscribe to events
(onInterfaceStateChange,
onIPAddressStatusChanged,
onInternetStatusChange)
+ NM-->>NS: Subscription confirmed
+
+ Note over NS,Timer: Timer Thread Creation
+ NS->>Timer: Create timer thread
(10 min interval)
+ activate Timer
+ Timer->>Timer: Initialize in stopped state
+ NS-->>Thunder: Initialization complete
+ deactivate NS
+
+ Note over NM,Timer: Network Connection Event
+ NM->>NS: onInterfaceStateChange(INTERFACE_CONNECTED)
+ activate NS
+ NS->>NS: Process connection event
+ NS->>Timer: Start timer thread
+ Timer->>Timer: Begin 10-min countdown
+ deactivate NS
+
+ Note over Timer,T2: Periodic Statistics Collection
+ loop Every 10 minutes
+ Timer->>Timer: Timer expired
+ Timer->>NS: Collect network statistics
+ activate NS
+ NS->>NM: GetIPSettings()
+ NM-->>NS: IP configuration
+ NS->>NM: GetActiveInterface()
+ NM-->>NS: Interface details
+ NS->>NS: Aggregate statistics
+ NS->>T2: Send telemetry event
(connection type, IP, DNS, etc.)
+ activate T2
+ T2-->>NS: Event sent
+ deactivate T2
+ Timer->>Timer: Restart 10-min timer
+ deactivate NS
+ end
+
+ Note over NM,Timer: Network Disconnection Event
+ NM->>NS: onInterfaceStateChange(INTERFACE_DISCONNECTED)
+ activate NS
+ NS->>NS: Process disconnection event
+ NS->>Timer: Stop timer thread
+ Timer->>Timer: Halt countdown
+ deactivate NS
+
+ Note over NM,Timer: Network Reconnection Event
+ NM->>NS: onInternetStatusChange(INTERNET_CONNECTED)
+ activate NS
+ NS->>NS: Process reconnection
+ NS->>Timer: Resume timer thread
+ Timer->>Timer: Resume 10-min countdown
+ deactivate NS
+
+ Note over Thunder,T2: Plugin Deinitialization
+ Thunder->>NS: Deinitialize()
+ activate NS
+ NS->>Timer: Stop timer thread
+ deactivate Timer
+ Timer-->>NS: Thread stopped
+ NS->>NM: Unregister notifications
+ NS->>NM: Unsubscribe from events
+ NM-->>NS: Unsubscribed
+ NS->>NM: Release COM-RPC connection
+ deactivate NM
+ NS->>NS: Cleanup resources
+ NS-->>Thunder: Deinitialization complete
+ deactivate NS
+```
+
+---
+
+## Flowchart
+
+```mermaid
+flowchart TD
+ Start([Thunder Starts NetworkStats Plugin]) --> Init[Initialize Plugin]
+ Init --> CreateImpl[Create NetworkStatsImplementation
Out-of-Process]
+ CreateImpl --> RegNotif[Register Notification Callbacks]
+ RegNotif --> EstablishComRPC[Establish COM-RPC Connection
to NetworkManager]
+
+ EstablishComRPC --> CheckConn{Connection
Successful?}
+ CheckConn -->|No| LogError[Log Error & Return Failure]
+ CheckConn -->|Yes| Subscribe[Subscribe to NetworkManager Events:
- onInterfaceStateChange
- onIPAddressStatusChanged
- onInternetStatusChange]
+
+ Subscribe --> CreateTimer[Create Timer Thread
10-min interval, stopped]
+ CreateTimer --> WaitEvent[Wait for Network Events]
+
+ WaitEvent --> EventReceived{Event
Received?}
+
+ EventReceived -->|Interface Connected| StartTimer[Start Timer Thread]
+ EventReceived -->|Interface Disconnected| StopTimer[Stop Timer Thread]
+ EventReceived -->|Internet Connected| ResumeTimer[Resume Timer Thread]
+ EventReceived -->|Internet Disconnected| PauseTimer[Pause Timer Thread]
+
+ StartTimer --> TimerActive[Timer Thread Active]
+ ResumeTimer --> TimerActive
+
+ TimerActive --> TimerLoop{Timer
Expired?}
+ TimerLoop -->|No| TimerActive
+ TimerLoop -->|Yes| CollectStats[Collect Network Statistics]
+
+ CollectStats --> GetIPSettings[Call NetworkManager:
GetIPSettings]
+ GetIPSettings --> GetInterface[Call NetworkManager:
GetActiveInterface]
+ GetInterface --> GetDNS[Call NetworkManager:
GetNameServers]
+ GetDNS --> AggregateData[Aggregate Statistics Data]
+
+ AggregateData --> SendT2[Send T2 Telemetry Event:
- Connection Type
- IP Addresses
- DNS Entries
- Interface Status]
+ SendT2 --> LogTelemetry[Log Telemetry Event]
+ LogTelemetry --> RestartTimer[Restart 10-min Timer]
+ RestartTimer --> TimerActive
+
+ StopTimer --> TimerStopped[Timer Thread Stopped]
+ PauseTimer --> TimerStopped
+ TimerStopped --> WaitEvent
+
+ EventReceived -->|Deinitialize| Shutdown[Thunder Shutdown Signal]
+ Shutdown --> StopTimerThread[Stop Timer Thread]
+ StopTimerThread --> UnsubEvents[Unsubscribe from All Events]
+ UnsubEvents --> UnregNotif[Unregister Notifications]
+ UnregNotif --> ReleaseComRPC[Release COM-RPC Connection]
+ ReleaseComRPC --> Cleanup[Cleanup Resources]
+ Cleanup --> End([Plugin Deinitialized])
+
+ LogError --> End
+
+ style Start fill:#90EE90
+ style End fill:#FFB6C1
+ style EstablishComRPC fill:#FFD700
+ style Subscribe fill:#FFD700
+ style CollectStats fill:#87CEEB
+ style SendT2 fill:#DDA0DD
+ style Shutdown fill:#FFA07A
+```
+
+---
+
+## Component Details
+
+### 1. NetworkStats Plugin Structure
+
+```cpp
+namespace WPEFramework {
+ namespace Plugin {
+ class NetworkStats : public PluginHost::IPlugin, public PluginHost::JSONRPC {
+ class Notification : public RPC::IRemoteConnection::INotification,
+ public Exchange::INetworkManager::INotification {
+ // Event handlers for NetworkManager events
+ void onInterfaceStateChange(const Exchange::INetworkManager::InterfaceState state,
+ const string interface) override;
+ void onIPAddressStatusChanged(const string& interface, const string& ipAddress,
+ const Exchange::INetworkManager::IPStatus status) override;
+ void onInternetStatusChange(const Exchange::INetworkManager::InternetStatus prevState,
+ const Exchange::INetworkManager::InternetStatus currState) override;
+ // ... other event handlers
+ };
+
+ private:
+ uint32_t _connectionId;
+ PluginHost::IShell* _service;
+ Exchange::INetworkManager* _networkManager;
+ Core::Sink _notification;
+
+ // Timer management
+ std::thread _statsCollectionThread;
+ std::atomic _timerRunning;
+ std::mutex _timerMutex;
+ std::condition_variable _timerCondVar;
+ };
+ }
+}
+```
+
+### 2. Timer Thread State Machine
+
+```
+States:
+┌─────────┐ Start Event ┌─────────┐
+│ STOPPED │ ───────────────► │ RUNNING │
+└─────────┘ └─────────┘
+ ▲ │
+ │ │
+ │ Stop/Disconnect │ Pause Event
+ │ Event │
+ │ ▼
+ │ ┌────────┐
+ └────────────────────────│ PAUSED │
+ Resume Event └────────┘
+```
+
+### 3. Statistics Collection Flow
+
+**Data Collected Every 10 Minutes:**
+- Active network interface (eth0/wlan0)
+- Connection type (Ethernet/WiFi)
+- IPv4 address and subnet
+- IPv6 address (if available)
+- DNS server entries (primary/secondary)
+- Default gateway
+- Interface state (UP/DOWN)
+- Internet connectivity status
+
+**T2 Telemetry Event Structure:**
+```json
+{
+ "timestamp": "2025-01-23T10:30:00Z",
+ "interface": "eth0",
+ "connectionType": "ETHERNET",
+ "ipv4Address": "192.168.1.100",
+ "ipv6Address": "fe80::1234:5678:90ab:cdef",
+ "dnsServers": ["8.8.8.8", "8.8.4.4"],
+ "gateway": "192.168.1.1",
+ "internetStatus": "CONNECTED",
+ "signalQuality": "EXCELLENT"
+}
+```
+
+---
+
+## Implementation Classes
+
+### NetworkStatsImplementation.cpp
+- **Purpose**: Out-of-process implementation
+- **Key Methods**:
+ - `Configure()`: Parses config, initializes COM-RPC connection
+ - `StartStatisticsCollection()`: Starts timer thread
+ - `StopStatisticsCollection()`: Stops timer thread
+ - `CollectAndSendStatistics()`: Gathers data and sends T2 events
+ - `OnNetworkEvent()`: Handles NetworkManager notifications
+
+### NetworkStatsTimer.cpp
+- **Purpose**: Manages periodic statistics collection
+- **Key Methods**:
+ - `Start()`: Begin 10-minute countdown
+ - `Stop()`: Halt timer thread
+ - `Pause()`: Suspend timer without destroying thread
+ - `Resume()`: Continue from paused state
+ - `OnTimerExpired()`: Callback for statistics collection
+
+### T2TelemetryClient.cpp
+- **Purpose**: Interface with T2 telemetry system
+- **Key Methods**:
+ - `SendEvent()`: Sends JSON telemetry data
+ - `FormatStatistics()`: Converts statistics to T2 format
+
+---
+
+## Configuration
+
+### NetworkStats.config
+```json
+{
+ "locator": "libWPEFrameworkNetworkStats.so",
+ "classname": "NetworkStats",
+ "callsign": "org.rdk.NetworkStats",
+ "autostart": true,
+ "configuration": {
+ "root": {
+ "outofprocess": true,
+ "locator": "libWPEFrameworkNetworkStatsImpl.so"
+ },
+ "collectionInterval": 600,
+ "networkManagerCallsign": "org.rdk.NetworkManager",
+ "enableT2Telemetry": true,
+ "telemetryMarker": "NETWORK_STATS"
+ }
+}
+```
+
+---
+
+## Event Subscription Logic
+
+### Subscribed Events
+| Event | Action |
+|-------|--------|
+| `onInterfaceStateChange(CONNECTED)` | Start timer thread |
+| `onInterfaceStateChange(DISCONNECTED)` | Stop timer thread |
+| `onInternetStatusChange(CONNECTED)` | Resume timer thread |
+| `onInternetStatusChange(DISCONNECTED)` | Pause timer thread |
+| `onIPAddressStatusChanged` | Log IP change, continue timer |
+
+---
+
+## Error Handling
+
+1. **COM-RPC Connection Failure**:
+ - Retry connection up to 5 times with exponential backoff
+ - Log fatal error if all retries fail
+ - Return initialization failure to Thunder
+
+2. **Timer Thread Crash**:
+ - Log exception details
+ - Attempt to restart timer thread once
+ - Notify Thunder of degraded operation
+
+3. **T2 Telemetry Failure**:
+ - Log warning (non-fatal)
+ - Cache statistics for next successful transmission
+ - Continue timer operation
+
+---
+
+## Threading Model
+
+```
+Thunder Main Process
+│
+└─► NetworkStats Plugin (Main Thread)
+ │
+ ├─► COM-RPC Communication Thread (Thunder managed)
+ │
+ └─► Out-of-Process Instance
+ │
+ ├─► Event Notification Thread (Thunder managed)
+ │
+ └─► Statistics Collection Timer Thread (Custom)
+ │
+ └─► T2 Telemetry Thread (System)
+```
+
+---
+
+## Shutdown Sequence
+
+1. Thunder sends `Deinitialize()` signal
+2. NetworkStats sets `_timerRunning = false`
+3. Notify timer condition variable to wake thread
+4. Join timer thread (wait for completion)
+5. Unregister from NetworkManager notifications
+6. Call `_networkManager->Unregister(&_notification)`
+7. Release COM-RPC interface: `_networkManager->Release()`
+8. Cleanup Thunder connection: `_service->Release()`
+9. Return control to Thunder
+
+---
+
+## Testing Strategy
+
+### L1 Unit Tests (`tests/l1Test/networkstats_l1_test.cpp`)
+- Timer thread start/stop/pause/resume logic
+- Statistics data aggregation
+- T2 telemetry formatting
+
+### L2 Integration Tests (`tests/l2Test/networkstats_l2_test.cpp`)
+- Mock NetworkManager COM-RPC interface
+- Simulate network events (connect/disconnect)
+- Verify timer behavior with event triggers
+- Validate T2 event payload structure
+
+---
+
+## Dependencies
+
+- **Thunder Framework**: COM-RPC infrastructure
+- **NetworkManager Plugin**: Network state provider
+- **T2 Library**: Telemetry event transmission
+- **libnm/GDBus** (indirect): Via NetworkManager backend
+
+---
+
+## Build Integration
+
+### CMakeLists.txt
+```cmake
+add_library(NetworkStats SHARED
+ plugin/networkstats/NetworkStats.cpp
+ plugin/networkstats/NetworkStatsImplementation.cpp
+ plugin/networkstats/NetworkStatsTimer.cpp
+ plugin/networkstats/T2TelemetryClient.cpp
+)
+
+target_link_libraries(NetworkStats
+ ${NAMESPACE}Plugins::${NAMESPACE}Plugins
+ ${NAMESPACE}Definitions::${NAMESPACE}Definitions
+ NetworkManagerInterfaces # For INetworkManager
+ t2log # T2 Telemetry
+)
+
+install(TARGETS NetworkStats DESTINATION lib/${NAMESPACE}/plugins)
+install(FILES NetworkStats.config DESTINATION ${CMAKE_INSTALL_PREFIX}/etc/${NAMESPACE}/plugins)
+```
+
+---
+
+## Logging
+
+Use `NetworkManagerLogger.h` macros:
+
+```cpp
+NMLOG_INFO("NetworkStats timer started (interval: %d sec)", interval);
+NMLOG_WARNING("Failed to collect statistics, retry scheduled");
+NMLOG_ERROR("COM-RPC connection to NetworkManager lost");
+NMLOG_DEBUG("Telemetry event sent: %s", jsonData.c_str());
+```
+
+---
+
+## Future Enhancements
+
+1. **Configurable Collection Interval**: Allow runtime adjustment via JSON-RPC
+2. **Historical Data Storage**: Cache last N statistics for trend analysis
+3. **Bandwidth Monitoring**: Track data usage per interface
+4. **Alert Thresholds**: Trigger events on connection quality degradation
+5. **Multi-Interface Support**: Collect statistics from all interfaces simultaneously
+
+---
+
+## References
+
+- NetworkManager Plugin Documentation
+- [Thunder Plugin Architecture](https://github.com/WebPlatformForEmbedded/Thunder)
+- COM-RPC Interface Guide
+- [T2 Telemetry Specification](https://github.com/rdkcentral/rdk-telemetry)
+
+---
+
+## Revision History
+
+| Version | Date | Author | Changes |
+|---------|------|--------|---------|
+| 1.0 | 2025-12-17 | Initial Design | Created sequence diagram and flowchart |
diff --git a/networkstats/README_INTERNAL_PLUGIN.md b/networkstats/README_INTERNAL_PLUGIN.md
new file mode 100644
index 00000000..be6cce23
--- /dev/null
+++ b/networkstats/README_INTERNAL_PLUGIN.md
@@ -0,0 +1,287 @@
+# NetworkConnectionStats - Internal Thunder Plugin (No External APIs)
+
+## Design Philosophy
+
+This plugin is designed to run **internally within Thunder framework** without exposing any external APIs. It automatically performs network diagnostics and reports telemetry data in the background.
+
+## Architecture
+
+```
+┌─────────────────────────────────────────┐
+│ Thunder/WPEFramework Process │
+│ ┌───────────────────────────────────┐ │
+│ │ NetworkConnectionStats │ │
+│ │ (Plugin - IPlugin only) │ │
+│ │ - Auto-activates │ │
+│ │ - No JSONRPC APIs │ │
+│ │ - Spawns out-of-process │ │
+│ └──────────┬────────────────────────┘ │
+└─────────────┼───────────────────────────┘
+ │ COM-RPC (internal)
+ ▼
+┌─────────────────────────────────────────┐
+│ Out-of-Process (Background Service) │
+│ ┌───────────────────────────────────┐ │
+│ │ NetworkConnectionStatsImpl │ │
+│ │ - Auto-starts periodic reporting │ │
+│ │ - Runs every N minutes (default10)│ │
+│ │ - Generates diagnostic reports │ │
+│ │ - Sends T2 telemetry events │ │
+│ │ - No external APIs exposed │ │
+│ └───────────────────────────────────┘ │
+└─────────────────────────────────────────┘
+```
+
+## What This Plugin Does
+
+### On Activation
+1. Thunder activates the plugin automatically (`startmode: "Activated"`)
+2. Plugin spawns out-of-process implementation
+3. Implementation initializes network provider
+4. **Generates initial diagnostic report**
+5. **Starts periodic reporting thread** (runs every N minutes)
+
+### Periodic Diagnostics (Every N Minutes)
+The plugin automatically runs these checks:
+
+1. **Connection Type Check**
+ - Detects Ethernet vs WiFi
+ - Logs to telemetry: `Connection_Type`
+
+2. **IP Configuration Check**
+ - Gets interface name, IPv4/IPv6 addresses
+ - Gets IPv4/IPv6 gateways and DNS servers
+ - Logs to telemetry: `Network_Interface_Info`, `IPv4_Gateway_DNS`, `IPv6_Gateway_DNS`
+
+3. **IPv4 Route Check**
+ - Validates IPv4 gateway availability
+ - Traces warnings if no gateway found
+
+4. **IPv6 Route Check**
+ - Validates IPv6 gateway availability
+ - Traces warnings if no gateway found
+
+5. **Gateway Packet Loss Check**
+ - Pings IPv4 gateway (5 packets, 30s timeout)
+ - Pings IPv6 gateway (5 packets, 30s timeout)
+ - Measures packet loss percentage and average RTT
+ - Logs to telemetry: `Gateway_Ping_Stats`
+
+6. **DNS Configuration Check**
+ - Verifies DNS servers are configured
+ - Logs warnings if no DNS found
+
+### Telemetry Events Sent
+
+All events use the T2 telemetry framework:
+
+| Event Name | Data Format | Example |
+|------------|-------------|---------|
+| `Connection_Type` | String | `"Ethernet"` or `"WiFi"` |
+| `Network_Interface_Info` | CSV | `"eth0,192.168.1.100,fe80::1"` |
+| `IPv4_Gateway_DNS` | CSV | `"192.168.1.1,8.8.8.8"` |
+| `IPv6_Gateway_DNS` | CSV | `"fe80::1,2001:4860:4860::8888"` |
+| `Gateway_Ping_Stats` | CSV | `"IPv4,192.168.1.1,0.0,2.5"` (version,gateway,loss%,avgRTT) |
+| `DNS_Status` | String | `"No DNS configured"` (only on error) |
+
+## Configuration
+
+### NetworkConnectionStats.config
+```json
+{
+ "locator": "libWPEFrameworkNetworkConnectionStats.so",
+ "classname": "NetworkConnectionStats",
+ "startmode": "Activated",
+ "configuration": {
+ "outofprocess": true,
+ "root": { "mode": "Local" },
+ "reportingInterval": 10,
+ "autoStart": true
+ }
+}
+```
+
+### Configuration Parameters
+
+| Parameter | Type | Default | Description |
+|-----------|------|---------|-------------|
+| `reportingInterval` | number | 10 | Diagnostic interval in minutes |
+| `autoStart` | boolean | true | Auto-start periodic reporting on plugin activation |
+| `outofprocess` | boolean | true | Run implementation out-of-process (recommended) |
+
+## Files Structure
+
+### Core Plugin Files
+- **Module.h/cpp** - Thunder module definition
+- **INetworkConnectionStats.h** - Minimal COM-RPC interface (no methods)
+- **NetworkConnectionStats.h** - Plugin class (IPlugin only)
+- **NetworkConnectionStats.cpp** - Plugin implementation
+- **NetworkConnectionStatsImplementation.h** - Out-of-process implementation header
+- **NetworkConnectionStatsImplementation.cpp** - All diagnostic logic
+
+### Supporting Files
+- **INetworkData.h** - Network data provider interface
+- **ThunderJsonRPCProvider.h/cpp** - NetworkManager plugin client
+- **NetworkConnectionStats.config** - Plugin configuration
+- **NetworkConnectionStats.conf.in** - CMake config template
+- **CMakeLists.txt** - Build system
+
+## No External APIs
+
+### What Was Removed
+- ❌ JSON-RPC API methods
+- ❌ External event notifications
+- ❌ Public getter/setter methods
+- ❌ NetworkConnectionStats.json API specification
+- ❌ INotification interface
+
+### What Remains
+- ✅ IPlugin interface (Initialize, Deinitialize, Information)
+- ✅ IConfiguration interface (for plugin config)
+- ✅ Internal diagnostic methods
+- ✅ Telemetry logging
+- ✅ Periodic reporting thread
+
+## How It Works
+
+### Startup Sequence
+```
+1. Thunder starts
+2. Thunder loads NetworkConnectionStats plugin
+3. Plugin Initialize() called
+4. Plugin spawns out-of-process NetworkConnectionStatsImplementation
+5. Implementation Configure() called
+6. NetworkJsonRPCProvider initialized
+7. Initial diagnostic report generated immediately
+8. Periodic reporting thread started (if autoStart=true)
+9. Thread sleeps for 'reportingInterval' minutes
+10. Thread wakes up, generates report
+11. Repeat steps 9-10 until plugin deactivated
+```
+
+### Logging
+
+All diagnostic output goes to Thunder trace logs:
+```bash
+# View logs
+journalctl -u wpeframework -f | grep NetworkConnectionStats
+
+# Example output:
+INFO: NetworkConnectionStats Constructor
+INFO: NetworkConnectionStatsImplementation::Configure
+INFO: Periodic reporting started with 10 minute interval
+INFO: Connection type: Ethernet
+INFO: Interface: eth0, IPv4: 192.168.1.100, IPv6: fe80::1
+INFO: IPv4 Gateway: 192.168.1.1, DNS: 8.8.8.8
+INFO: Pinging IPv4 gateway: 192.168.1.1
+INFO: IPv4 gateway ping - Loss: 0.0%, RTT: 2.5ms
+INFO: Network diagnostics report completed
+INFO: Periodic report generated
+```
+
+## Building
+
+```bash
+cmake -B build \
+ -DPLUGIN_NETWORKCONNECTIONSTATS=ON \
+ -DPLUGIN_NETWORKCONNECTIONSTATS_OUTOFPROCESS=ON \
+ -DUSE_TELEMETRY=ON \
+ -DPLUGIN_NETWORKCONNECTIONSTATS_REPORTING_INTERVAL=10
+
+cmake --build build
+sudo cmake --install build
+```
+
+## Deployment
+
+### Install Plugin
+```bash
+# Libraries installed to:
+/usr/lib/wpeframework/plugins/libWPEFrameworkNetworkConnectionStats.so
+/usr/lib/wpeframework/plugins/libWPEFrameworkNetworkConnectionStatsImplementation.so
+
+# Config installed to:
+/etc/wpeframework/plugins/NetworkConnectionStats.json
+```
+
+### Thunder Auto-Activation
+Plugin automatically activates on Thunder startup (no manual activation needed).
+
+## Monitoring
+
+### Check Plugin Status
+```bash
+curl http://localhost:9998/jsonrpc -d '{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "Controller.1.status@NetworkConnectionStats"
+}'
+```
+
+### Expected Response
+```json
+{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "result": [
+ {
+ "callsign": "NetworkConnectionStats",
+ "locator": "libWPEFrameworkNetworkConnectionStats.so",
+ "classname": "NetworkConnectionStats",
+ "autostart": true,
+ "state": "activated"
+ }
+ ]
+}
+```
+
+### View Telemetry Events
+Telemetry events are sent via T2 framework and uploaded to backend systems. Check T2 logs:
+```bash
+journalctl -u t2 -f
+```
+
+## Advantages of Internal-Only Design
+
+1. **Simplicity** - No API surface to maintain or secure
+2. **Background Operation** - Runs autonomously without external triggers
+3. **Zero Configuration** - Works out-of-the-box with defaults
+4. **Resource Efficient** - Periodic checks minimize CPU/network usage
+5. **Telemetry Integration** - Data flows automatically to analytics backend
+6. **Process Isolation** - Out-of-process prevents Thunder crashes
+7. **Automatic Recovery** - Thunder restarts implementation if it crashes
+
+## Use Cases
+
+This plugin is ideal for:
+- **Continuous network monitoring** - Track connection health 24/7
+- **Proactive diagnostics** - Detect issues before users report them
+- **Analytics/BigData** - Feed network metrics to data pipelines
+- **Fleet management** - Monitor thousands of devices remotely
+- **SLA tracking** - Measure uptime and connectivity quality
+
+## Comparison: Standalone vs Thunder Plugin
+
+| Aspect | Standalone (Old) | Thunder Plugin (New) |
+|--------|------------------|----------------------|
+| **Execution** | Separate process with main() | Thunder-managed lifecycle |
+| **Startup** | Manual launch | Auto-activated by Thunder |
+| **APIs** | None | None (internal-only) |
+| **Logging** | printf/fprintf | Thunder TRACE framework |
+| **Telemetry** | T2 direct calls | T2 direct calls (same) |
+| **Configuration** | Hardcoded | Thunder config system |
+| **Monitoring** | None | Thunder Controller API |
+| **Integration** | Isolated | Part of Thunder ecosystem |
+
+## Summary
+
+NetworkConnectionStats is now a **self-contained Thunder plugin** that:
+- ✅ Runs automatically in the background
+- ✅ Performs periodic network diagnostics (every N minutes)
+- ✅ Sends telemetry data to T2 framework
+- ✅ Requires zero external interaction
+- ✅ Has no exposed APIs (internal-only)
+- ✅ Integrates seamlessly with Thunder framework
+- ✅ Provides continuous network health monitoring
+
+**Perfect for production deployments that need passive network monitoring without exposing attack surfaces!**
diff --git a/networkstats/THUNDER_PLUGIN_CONVERSION.md b/networkstats/THUNDER_PLUGIN_CONVERSION.md
new file mode 100644
index 00000000..9c011574
--- /dev/null
+++ b/networkstats/THUNDER_PLUGIN_CONVERSION.md
@@ -0,0 +1,247 @@
+# NetworkConnectionStats Thunder Plugin Conversion
+
+## Overview
+Successfully transformed NetworkConnectionStats from a standalone application into a full-fledged WPEFramework/Thunder plugin module, following the Telemetry plugin architecture pattern.
+
+## Architecture Changes
+
+### 1. Thunder Plugin Framework Integration
+The plugin now follows the standard Thunder plugin architecture with:
+- **In-process plugin** (NetworkConnectionStats.cpp) - Runs in WPEFramework process
+- **Out-of-process implementation** (NetworkConnectionStatsImplementation.cpp) - Runs as separate process for isolation and stability
+
+### 2. Key Components Created
+
+#### Module Definition
+- **Module.h** - Defines plugin module name and includes Thunder headers
+- **Module.cpp** - Module registration macro
+
+#### COM-RPC Interface
+- **INetworkConnectionStats.h** - Defines the COM-RPC interface with:
+ - INetworkConnectionStats interface with all network diagnostic methods
+ - INotification sub-interface for event notifications
+ - Proper interface IDs and stubgen annotations
+
+#### Plugin Main Class
+- **NetworkConnectionStats.h** - Plugin header with:
+ - Inherits from `PluginHost::IPlugin` and `PluginHost::JSONRPC`
+ - Notification handler for RPC connection lifecycle and events
+ - Interface aggregation for COM-RPC
+
+- **NetworkConnectionStats.cpp** - Plugin implementation with:
+ - IPlugin lifecycle methods (Initialize, Deinitialize, Information)
+ - RPC connection management
+ - JSON-RPC registration
+ - Notification forwarding
+
+#### Out-of-Process Implementation
+- **NetworkConnectionStatsImplementation.h/.cpp** - Business logic implementation:
+ - All original diagnostic functionality preserved
+ - Implements INetworkConnectionStats and IConfiguration interfaces
+ - Notification management for event subscribers
+ - Periodic reporting thread with configurable interval
+ - Telemetry integration (T2)
+ - Network provider integration (NetworkJsonRPCProvider)
+
+#### API Specification
+- **NetworkConnectionStats.json** - JSON-RPC API definition:
+ - Method definitions with parameters and return types
+ - Event definitions (onReportGenerated)
+ - Schema-compliant for Thunder code generation
+
+#### Configuration Files
+- **NetworkConnectionStats.config** - Plugin configuration (JSON format)
+- **NetworkConnectionStats.conf.in** - CMake template for configuration generation
+
+#### Build System
+- **CMakeLists.txt** - Thunder-compliant build system:
+ - Interface library for COM-RPC definitions
+ - Plugin library (in-process)
+ - Implementation library (out-of-process)
+ - Proper dependency management
+ - Installation rules for plugins, headers, and API specs
+
+## API Methods Available
+
+### Diagnostic Methods
+1. **generateReport()** - Generate full network diagnostics report
+2. **getConnectionType()** - Get Ethernet/WiFi connection type
+3. **getIpv4Address(interface)** - Get IPv4 address
+4. **getIpv6Address(interface)** - Get IPv6 address
+5. **getIpv4Gateway()** - Get IPv4 gateway
+6. **getIpv6Gateway()** - Get IPv6 gateway
+7. **getIpv4Dns()** - Get IPv4 DNS server
+8. **getIpv6Dns()** - Get IPv6 DNS server
+9. **getInterface()** - Get active network interface
+10. **pingGateway(endpoint, ipversion, count, timeout)** - Ping gateway with stats
+
+### Configuration Methods
+11. **setPeriodicReporting(enable)** - Enable/disable periodic reports
+12. **setReportingInterval(intervalMinutes)** - Set reporting interval
+
+### Events
+- **onReportGenerated** - Fired when report is generated
+
+## Key Features Preserved
+
+### Network Diagnostics
+- Connection type detection (Ethernet/WiFi)
+- IPv4/IPv6 address retrieval
+- Gateway/route validation
+- DNS configuration checks
+- Packet loss monitoring
+- RTT measurements
+
+### Telemetry Integration
+- T2 telemetry events for network metrics
+- Conditional compilation with USE_TELEMETRY flag
+- Event logging for connection type, IP info, gateway stats
+
+### Periodic Reporting
+- Configurable reporting interval (default 10 minutes)
+- Background thread for periodic diagnostics
+- Thread-safe start/stop control
+
+## Migration from Standalone to Plugin
+
+### What Was Removed
+- `main()` function - No longer needed in plugin architecture
+- Singleton pattern - Thunder manages plugin lifecycle
+- Standalone initialization - Replaced with IPlugin::Initialize()
+
+### What Was Added
+- Thunder plugin lifecycle (IPlugin interface)
+- RPC connection management
+- Notification system for events
+- COM-RPC and JSON-RPC interfaces
+- Configuration interface (IConfiguration)
+- Proper Thunder logging (TRACE macros)
+
+### What Was Transformed
+- Constructor/Destructor - Now plugin-aware
+- Initialize/Deinitialize - Now IPlugin methods with PluginHost::IShell parameter
+- Network provider - Integrated with out-of-process implementation
+- Diagnostic methods - Exposed via COM-RPC interface
+
+## Build Configuration
+
+### CMake Options
+```cmake
+-DPLUGIN_NETWORKCONNECTIONSTATS=ON # Build the plugin
+-DPLUGIN_NETWORKCONNECTIONSTATS_OUTOFPROCESS=ON # Out-of-process mode
+-DUSE_TELEMETRY=ON # Enable T2 telemetry
+-DPLUGIN_NETWORKCONNECTIONSTATS_REPORTING_INTERVAL=10 # Default interval
+```
+
+### Dependencies
+- WPEFramework (Thunder)
+- libjsonrpccpp-client/common
+- jsoncpp
+- T2 (optional, for telemetry)
+- pthread
+
+## Usage Example
+
+### Activate Plugin
+```bash
+curl http://localhost:9998/jsonrpc -d '{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "Controller.1.activate",
+ "params": {"callsign": "NetworkConnectionStats"}
+}'
+```
+
+### Generate Report
+```bash
+curl http://localhost:9998/jsonrpc -d '{
+ "jsonrpc": "2.0",
+ "id": 2,
+ "method": "NetworkConnectionStats.1.generateReport"
+}'
+```
+
+### Enable Periodic Reporting
+```bash
+curl http://localhost:9998/jsonrpc -d '{
+ "jsonrpc": "2.0",
+ "id": 3,
+ "method": "NetworkConnectionStats.1.setPeriodicReporting",
+ "params": {"enable": true}
+}'
+```
+
+### Subscribe to Events
+```bash
+curl http://localhost:9998/jsonrpc -d '{
+ "jsonrpc": "2.0",
+ "id": 4,
+ "method": "NetworkConnectionStats.1.register",
+ "params": {"event": "onReportGenerated", "id": "client1"}
+}'
+```
+
+## File Structure
+```
+networkstats/
+├── Module.h # Thunder module definition
+├── Module.cpp # Module registration
+├── INetworkConnectionStats.h # COM-RPC interface
+├── NetworkConnectionStats.h # Plugin header
+├── NetworkConnectionStats.cpp # Plugin implementation
+├── NetworkConnectionStatsImplementation.h # Out-of-process header
+├── NetworkConnectionStatsImplementation.cpp # Out-of-process implementation
+├── NetworkConnectionStats.json # JSON-RPC API spec
+├── NetworkConnectionStats.config # Plugin config
+├── NetworkConnectionStats.conf.in # CMake config template
+├── CMakeLists.txt # Thunder build system
+├── INetworkData.h # Network provider interface (existing)
+├── ThunderJsonRPCProvider.h/cpp # Network provider impl (existing)
+└── *.old # Backup files
+```
+
+## Integration with Thunder Framework
+
+The plugin is now a first-class Thunder citizen with:
+- **Lifecycle Management** - Thunder controls activation/deactivation
+- **RPC Communication** - Both COM-RPC and JSON-RPC supported
+- **Process Isolation** - Out-of-process execution for stability
+- **Event System** - Notification framework for async events
+- **Configuration** - Dynamic configuration via Thunder config system
+- **Security** - Runs with Thunder's security policies
+
+## Next Steps
+
+1. **Code Generation**: Run Thunder's code generator to create JSON-RPC stubs:
+ ```bash
+ JsonGenerator.py --code NetworkConnectionStats.json
+ ```
+
+2. **Build**: Integrate into main CMake build system
+
+3. **Testing**:
+ - Unit tests for individual methods
+ - Integration tests with Thunder framework
+ - End-to-end API testing
+
+4. **Documentation**: Generate API documentation from JSON spec
+
+## Comparison: Before vs After
+
+| Aspect | Standalone | Thunder Plugin |
+|--------|-----------|----------------|
+| Execution | Single process with main() | Multi-process (in-process + out-of-process) |
+| Lifecycle | Manual start/stop | Thunder-managed activation |
+| API | Internal C++ only | COM-RPC + JSON-RPC |
+| Configuration | Hardcoded or command-line | Thunder config system |
+| Events | None | Notification framework |
+| Logging | printf/fprintf | Thunder TRACE macros |
+| Integration | Standalone binary | Thunder plugin ecosystem |
+
+## Notes
+
+- Original implementation preserved in `*.cpp.old` files for reference
+- All network diagnostic functionality maintained
+- Telemetry integration (T2) remains optional via compile flag
+- Thread-safe implementation with proper locking
+- Compatible with Thunder R2 and R4 APIs
diff --git a/networkstats/THUNDER_PLUGIN_QUICK_REFERENCE.md b/networkstats/THUNDER_PLUGIN_QUICK_REFERENCE.md
new file mode 100644
index 00000000..6a8a7abc
--- /dev/null
+++ b/networkstats/THUNDER_PLUGIN_QUICK_REFERENCE.md
@@ -0,0 +1,317 @@
+# NetworkConnectionStats Thunder Plugin - Quick Reference
+
+## Architecture Pattern (Following Telemetry)
+
+```
+┌─────────────────────────────────────────────────────────────────┐
+│ Thunder/WPEFramework Process │
+│ ┌────────────────────────────────────────────────────────────┐ │
+│ │ NetworkConnectionStats (Plugin) │ │
+│ │ - Inherits IPlugin + JSONRPC │ │
+│ │ - Manages RPC connection │ │
+│ │ - Forwards JSON-RPC calls │ │
+│ │ - Handles notifications │ │
+│ └────────────────┬───────────────────────────────────────────┘ │
+│ │ COM-RPC │
+└───────────────────┼──────────────────────────────────────────────┘
+ │
+ ▼
+┌─────────────────────────────────────────────────────────────────┐
+│ Out-of-Process (Separate Process) │
+│ ┌────────────────────────────────────────────────────────────┐ │
+│ │ NetworkConnectionStatsImplementation │ │
+│ │ - Implements INetworkConnectionStats │ │
+│ │ - Implements IConfiguration │ │
+│ │ - Contains business logic │ │
+│ │ - Manages network diagnostics │ │
+│ │ - Sends notifications via INotification │ │
+│ │ ┌──────────────────────────────────────────────────────┐ │ │
+│ │ │ NetworkJsonRPCProvider (INetworkData) │ │ │
+│ │ │ - Calls NetworkManager plugin APIs │ │ │
+│ │ │ - Gets network interface info │ │ │
+│ │ │ - Performs ping tests │ │ │
+│ │ └──────────────────────────────────────────────────────┘ │ │
+│ └────────────────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────────┘
+```
+
+## File Mapping: Telemetry → NetworkConnectionStats
+
+| Telemetry | NetworkConnectionStats | Purpose |
+|-----------|------------------------|---------|
+| Module.h/cpp | Module.h/cpp | Thunder module definition |
+| ITelemetry.h | INetworkConnectionStats.h | COM-RPC interface |
+| Telemetry.h | NetworkConnectionStats.h | Plugin class header |
+| Telemetry.cpp | NetworkConnectionStats.cpp | Plugin implementation |
+| TelemetryImplementation.h | NetworkConnectionStatsImplementation.h | Out-of-process header |
+| TelemetryImplementation.cpp | NetworkConnectionStatsImplementation.cpp | Out-of-process impl |
+| Telemetry.json | NetworkConnectionStats.json | JSON-RPC API spec |
+| Telemetry.config | NetworkConnectionStats.config | Config file |
+
+## Key Classes & Interfaces
+
+### 1. NetworkConnectionStats (Plugin)
+**File**: NetworkConnectionStats.h/cpp
+**Inherits**: PluginHost::IPlugin, PluginHost::JSONRPC
+**Purpose**: Main plugin class running in Thunder process
+
+**Key Methods**:
+- `Initialize(PluginHost::IShell*)` - Plugin activation
+- `Deinitialize(PluginHost::IShell*)` - Plugin cleanup
+- `Information()` - Plugin description
+- `Deactivated(RPC::IRemoteConnection*)` - Handle out-of-process crash
+
+**Inner Class**: `Notification`
+- Implements `RPC::IRemoteConnection::INotification`
+- Implements `INetworkConnectionStats::INotification`
+- Forwards events to JSON-RPC clients
+
+### 2. INetworkConnectionStats (Interface)
+**File**: INetworkConnectionStats.h
+**Purpose**: COM-RPC interface definition
+
+**Sub-Interface**: `INotification`
+- `OnReportGenerated(const string&)` - Event notification
+
+**Main Interface Methods**:
+- `Register/Unregister` - Notification subscription
+- `GenerateReport()` - Trigger diagnostics
+- `GetConnectionType()` - Network type
+- `GetIpv4Address/GetIpv6Address` - IP addresses
+- `GetIpv4Gateway/GetIpv6Gateway` - Gateways
+- `GetIpv4Dns/GetIpv6Dns` - DNS servers
+- `GetInterface()` - Active interface
+- `PingGateway()` - Gateway connectivity test
+- `SetPeriodicReporting()` - Enable/disable periodic reports
+- `SetReportingInterval()` - Configure interval
+
+### 3. NetworkConnectionStatsImplementation
+**File**: NetworkConnectionStatsImplementation.h/cpp
+**Inherits**: INetworkConnectionStats, IConfiguration
+**Purpose**: Out-of-process business logic
+
+**Key Methods**:
+- `Configure(PluginHost::IShell*)` - Initialize from config
+- All INetworkConnectionStats interface methods
+- `connectionTypeCheck()` - Internal diagnostic
+- `connectionIpCheck()` - Internal diagnostic
+- `defaultIpv4RouteCheck()` - Internal diagnostic
+- `defaultIpv6RouteCheck()` - Internal diagnostic
+- `gatewayPacketLossCheck()` - Internal diagnostic
+- `networkDnsCheck()` - Internal diagnostic
+- `logTelemetry()` - T2 event logging
+- `periodicReportingThread()` - Background thread
+
+## Interface Macros Explained
+
+### BEGIN_INTERFACE_MAP / END_INTERFACE_MAP
+Thunder's interface query mechanism (like COM's QueryInterface):
+
+```cpp
+BEGIN_INTERFACE_MAP(NetworkConnectionStats)
+ INTERFACE_ENTRY(PluginHost::IPlugin) // Standard plugin interface
+ INTERFACE_ENTRY(PluginHost::IDispatcher) // JSON-RPC dispatcher
+ INTERFACE_AGGREGATE(Exchange::INetworkConnectionStats, _networkStats) // Delegate to out-of-process
+END_INTERFACE_MAP
+```
+
+**INTERFACE_AGGREGATE**: Forwards interface queries to another object (_networkStats = out-of-process impl)
+
+## RPC Connection Flow
+
+1. **Plugin Activation** (In-process):
+ ```cpp
+ Initialize(service) {
+ _networkStats = service->Root(_connectionId, 5000, "NetworkConnectionStatsImplementation");
+ // Spawns out-of-process, creates proxy
+ }
+ ```
+
+2. **Out-of-process Creation**:
+ - Thunder spawns new process
+ - Loads NetworkConnectionStatsImplementation library
+ - Creates instance via SERVICE_REGISTRATION macro
+ - Establishes RPC channel
+
+3. **API Call Flow**:
+ ```
+ JSON-RPC Client → Thunder → NetworkConnectionStats (plugin)
+ → COM-RPC Proxy → Out-of-process → NetworkConnectionStatsImplementation
+ → NetworkJsonRPCProvider → NetworkManager Plugin
+ ```
+
+4. **Event Flow**:
+ ```
+ NetworkConnectionStatsImplementation::notifyReportGenerated()
+ → INotification::OnReportGenerated()
+ → COM-RPC channel
+ → NetworkConnectionStats::Notification::OnReportGenerated()
+ → JNetworkConnectionStats::Event::OnReportGenerated()
+ → JSON-RPC Event to subscribed clients
+ ```
+
+## Critical Thunder Patterns
+
+### 1. SERVICE_REGISTRATION
+Registers class with Thunder's factory:
+```cpp
+SERVICE_REGISTRATION(NetworkConnectionStats, 1, 0, 0);
+```
+
+### 2. Metadata Declaration
+Plugin version and lifecycle info:
+```cpp
+static Plugin::Metadata metadata(
+ 1, 0, 0, // Major, Minor, Patch
+ {}, // Preconditions
+ {}, // Terminations
+ {} // Controls
+);
+```
+
+### 3. Notification Pattern
+```cpp
+// Plugin side
+Core::Sink _notification;
+
+// Implementation side
+std::list _notifications;
+
+Register() {
+ _notifications.push_back(notification);
+ notification->AddRef(); // Reference counting!
+}
+
+Unregister() {
+ notification->Release();
+ _notifications.erase(notification);
+}
+```
+
+### 4. Thread Safety
+```cpp
+Core::CriticalSection _adminLock;
+
+void SomeMethod() {
+ _adminLock.Lock();
+ // Critical section
+ _adminLock.Unlock();
+}
+```
+
+### 5. Reference Counting
+```cpp
+_service->AddRef(); // Increment ref count
+_service->Release(); // Decrement ref count
+// Object destroyed when ref count reaches 0
+```
+
+## Configuration File Format
+
+### NetworkConnectionStats.config
+```json
+{
+ "locator": "libWPEFrameworkNetworkConnectionStats.so", // Plugin library
+ "classname": "NetworkConnectionStats", // Class name
+ "startmode": "Activated", // Auto-start
+ "configuration": {
+ "outofprocess": true, // Run out-of-process
+ "root": {
+ "mode": "Local" // Process mode
+ },
+ "reportingInterval": 10 // Custom config
+ }
+}
+```
+
+## Build Integration
+
+### Add to Parent CMakeLists.txt
+```cmake
+add_subdirectory(networkstats)
+```
+
+### Build Commands
+```bash
+cd build
+cmake .. -DPLUGIN_NETWORKCONNECTIONSTATS=ON -DUSE_TELEMETRY=ON
+make NetworkConnectionStats
+sudo make install
+```
+
+## Debugging Tips
+
+### 1. Enable Traces
+Set log level in Thunder config or via Controller plugin:
+```bash
+curl http://localhost:9998/jsonrpc -d '{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "Controller.1.configuration@NetworkConnectionStats",
+ "params": {"trace": ["Information", "Error"]}
+}'
+```
+
+### 2. Check Process
+```bash
+ps aux | grep NetworkConnectionStatsImplementation
+```
+
+### 3. Monitor Logs
+```bash
+journalctl -u wpeframework -f | grep NetworkConnectionStats
+```
+
+### 4. Verify Plugin Load
+```bash
+curl http://localhost:9998/jsonrpc -d '{
+ "jsonrpc": "2.0",
+ "id": 1,
+ "method": "Controller.1.status@NetworkConnectionStats"
+}'
+```
+
+## Common Issues & Solutions
+
+### Issue: Plugin doesn't load
+**Check**:
+- Library in correct path (`/usr/lib/wpeframework/plugins/`)
+- Dependencies present (`ldd libWPEFrameworkNetworkConnectionStats.so`)
+- Config file syntax valid
+
+### Issue: Out-of-process crashes
+**Check**:
+- NetworkJsonRPCProvider can reach NetworkManager plugin
+- Null pointer checks in implementation
+- Thread synchronization
+
+### Issue: Events not received
+**Check**:
+- Client subscribed to event
+- Notification registered in implementation
+- RPC connection active
+
+### Issue: "Interface not found"
+**Check**:
+- INTERFACE_AGGREGATE correctly set
+- Out-of-process implementation exports interface
+- SERVICE_REGISTRATION present
+
+## Testing Checklist
+
+- [ ] Plugin activates successfully
+- [ ] All JSON-RPC methods callable
+- [ ] Events received by subscribers
+- [ ] Periodic reporting works
+- [ ] Out-of-process survives restarts
+- [ ] Telemetry events logged (if enabled)
+- [ ] No memory leaks (valgrind)
+- [ ] Thread-safe under concurrent calls
+- [ ] Graceful deactivation/cleanup
+
+## Resources
+
+- **Thunder Documentation**: https://rdkcentral.github.io/Thunder/
+- **Plugin Template**: Telemetry plugin (reference implementation)
+- **API Generator**: JsonGenerator.py in Thunder tools
+- **Code Examples**: Other Thunder plugins in RDK repositories
diff --git a/networkstats/definition/CMakeLists.txt b/networkstats/definition/CMakeLists.txt
new file mode 100644
index 00000000..a31b8adc
--- /dev/null
+++ b/networkstats/definition/CMakeLists.txt
@@ -0,0 +1,28 @@
+#############################################################################
+# If not stated otherwise in this file or this component's LICENSE file the
+# following copyright and licenses apply:
+#
+# Copyright 2025 RDK Management
+#
+# 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.
+#############################################################################
+message("Generate JsonRPC Documentation for NetworkConnectionStats.json")
+
+find_package(JsonGenerator REQUIRED)
+
+if(NOT GENERATOR_SEARCH_PATH)
+ set(GENERATOR_SEARCH_PATH ${CMAKE_SYSROOT}${CMAKE_INSTALL_PREFIX}/include/${NAMESPACE})
+endif()
+
+set(JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/NetworkConnectionStats.json")
+JsonGenerator(CODE INPUT ${JSON_FILE} OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/generated" INCLUDE_PATH ${GENERATOR_SEARCH_PATH} CPPIFDIR "${CMAKE_CURRENT_SOURCE_DIR}" DOCS)
diff --git a/networkstats/definition/NetworkConnectionStats.json b/networkstats/definition/NetworkConnectionStats.json
new file mode 100644
index 00000000..31abe279
--- /dev/null
+++ b/networkstats/definition/NetworkConnectionStats.json
@@ -0,0 +1,256 @@
+{
+ "$schema": "interface.schema.json",
+ "jsonrpc": "2.0",
+ "info": {
+ "title": "NetworkConnectionStats API",
+ "class": "NetworkConnectionStats",
+ "description": "NetworkConnectionStats plugin for network diagnostics and monitoring"
+ },
+ "definitions": {
+ "success": {
+ "summary": "Whether the request succeeded",
+ "type": "boolean",
+ "example": true
+ },
+ "pingresult": {
+ "type": "object",
+ "properties": {
+ "packetLoss": {
+ "type": "string",
+ "description": "Packet loss percentage"
+ },
+ "avgRtt": {
+ "type": "string",
+ "description": "Average round-trip time in milliseconds"
+ }
+ },
+ "required": ["packetLoss", "avgRtt"]
+ }
+ },
+ "methods": {
+ "generateReport": {
+ "summary": "Generate network diagnostics report",
+ "description": "Triggers a full network diagnostic scan including connection type, IP configuration, routes, and DNS",
+ "result": {
+ "$ref": "#/definitions/success"
+ }
+ },
+ "getConnectionType": {
+ "summary": "Get current connection type",
+ "description": "Returns whether the device is using Ethernet or WiFi",
+ "result": {
+ "type": "object",
+ "properties": {
+ "connectionType": {
+ "type": "string",
+ "description": "Connection type (Ethernet/WiFi)",
+ "example": "Ethernet"
+ }
+ },
+ "required": ["connectionType"]
+ }
+ },
+ "getIpv4Address": {
+ "summary": "Get IPv4 address for interface",
+ "params": {
+ "type": "object",
+ "properties": {
+ "interface": {
+ "type": "string",
+ "description": "Network interface name",
+ "example": "eth0"
+ }
+ },
+ "required": ["interface"]
+ },
+ "result": {
+ "type": "object",
+ "properties": {
+ "ipv4Address": {
+ "type": "string",
+ "description": "IPv4 address",
+ "example": "192.168.1.100"
+ }
+ },
+ "required": ["ipv4Address"]
+ }
+ },
+ "getIpv6Address": {
+ "summary": "Get IPv6 address for interface",
+ "params": {
+ "type": "object",
+ "properties": {
+ "interface": {
+ "type": "string",
+ "description": "Network interface name",
+ "example": "eth0"
+ }
+ },
+ "required": ["interface"]
+ },
+ "result": {
+ "type": "object",
+ "properties": {
+ "ipv6Address": {
+ "type": "string",
+ "description": "IPv6 address",
+ "example": "fe80::1"
+ }
+ },
+ "required": ["ipv6Address"]
+ }
+ },
+ "getIpv4Gateway": {
+ "summary": "Get IPv4 gateway address",
+ "result": {
+ "type": "object",
+ "properties": {
+ "gateway": {
+ "type": "string",
+ "description": "IPv4 gateway address",
+ "example": "192.168.1.1"
+ }
+ },
+ "required": ["gateway"]
+ }
+ },
+ "getIpv6Gateway": {
+ "summary": "Get IPv6 gateway address",
+ "result": {
+ "type": "object",
+ "properties": {
+ "gateway": {
+ "type": "string",
+ "description": "IPv6 gateway address",
+ "example": "fe80::1"
+ }
+ },
+ "required": ["gateway"]
+ }
+ },
+ "getIpv4Dns": {
+ "summary": "Get IPv4 DNS server",
+ "result": {
+ "type": "object",
+ "properties": {
+ "dns": {
+ "type": "string",
+ "description": "IPv4 DNS server address",
+ "example": "8.8.8.8"
+ }
+ },
+ "required": ["dns"]
+ }
+ },
+ "getIpv6Dns": {
+ "summary": "Get IPv6 DNS server",
+ "result": {
+ "type": "object",
+ "properties": {
+ "dns": {
+ "type": "string",
+ "description": "IPv6 DNS server address",
+ "example": "2001:4860:4860::8888"
+ }
+ },
+ "required": ["dns"]
+ }
+ },
+ "getInterface": {
+ "summary": "Get current active interface name",
+ "result": {
+ "type": "object",
+ "properties": {
+ "interface": {
+ "type": "string",
+ "description": "Active network interface name",
+ "example": "eth0"
+ }
+ },
+ "required": ["interface"]
+ }
+ },
+ "pingGateway": {
+ "summary": "Ping gateway to check connectivity",
+ "params": {
+ "type": "object",
+ "properties": {
+ "endpoint": {
+ "type": "string",
+ "description": "Gateway IP address to ping",
+ "example": "192.168.1.1"
+ },
+ "ipversion": {
+ "type": "string",
+ "description": "IP version (IPv4 or IPv6)",
+ "example": "IPv4"
+ },
+ "count": {
+ "type": "number",
+ "description": "Number of ping packets to send",
+ "example": 5
+ },
+ "timeout": {
+ "type": "number",
+ "description": "Timeout in seconds",
+ "example": 30
+ }
+ },
+ "required": ["endpoint", "ipversion", "count", "timeout"]
+ },
+ "result": {
+ "$ref": "#/definitions/pingresult"
+ }
+ },
+ "setPeriodicReporting": {
+ "summary": "Enable or disable periodic reporting",
+ "params": {
+ "type": "object",
+ "properties": {
+ "enable": {
+ "type": "boolean",
+ "description": "Enable (true) or disable (false) periodic reporting",
+ "example": true
+ }
+ },
+ "required": ["enable"]
+ },
+ "result": {
+ "$ref": "#/definitions/success"
+ }
+ },
+ "setReportingInterval": {
+ "summary": "Set periodic reporting interval",
+ "params": {
+ "type": "object",
+ "properties": {
+ "intervalMinutes": {
+ "type": "number",
+ "description": "Reporting interval in minutes",
+ "example": 10
+ }
+ },
+ "required": ["intervalMinutes"]
+ },
+ "result": {
+ "$ref": "#/definitions/success"
+ }
+ }
+ },
+ "events": {
+ "onReportGenerated": {
+ "summary": "Notification when a network report is generated",
+ "params": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string",
+ "description": "Report generation status message",
+ "example": "Report generated successfully"
+ }
+ },
+ "required": ["status"]
+ }
+ }
+ }
+}
diff --git a/networkstats/interface/CMakeLists.txt b/networkstats/interface/CMakeLists.txt
new file mode 100644
index 00000000..e19aa82a
--- /dev/null
+++ b/networkstats/interface/CMakeLists.txt
@@ -0,0 +1,61 @@
+#############################################################################
+# If not stated otherwise in this file or this component's LICENSE file the
+# following copyright and licenses apply:
+#
+# Copyright 2025 RDK Management
+#
+# 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.
+#############################################################################
+message("Generate ProxyStub for INetworkConnectionStats.h")
+
+find_package(WPEFramework)
+find_package(${NAMESPACE}Core REQUIRED)
+find_package(${NAMESPACE}Plugins REQUIRED)
+find_package(CompileSettingsDebug CONFIG REQUIRED)
+find_package(ProxyStubGenerator REQUIRED)
+
+set(PROXYLIB ${NAMESPACE}NetworkConnectionStatsProxy)
+set(ProxyStubGenerator_DIR ${CMAKE_SYSROOT}${CMAKE_INSTALL_PREFIX}/tools/cmake ${ProxyStubGenerator_DIR})
+
+if(NOT GENERATOR_SEARCH_PATH)
+ set(GENERATOR_SEARCH_PATH ${CMAKE_SYSROOT}${CMAKE_INSTALL_PREFIX}/include/${NAMESPACE})
+endif()
+
+file(GLOB INTERFACE_HEADER ${CMAKE_CURRENT_SOURCE_DIR})
+
+ProxyStubGenerator(INPUT "${INTERFACE_HEADER}" OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/generated" INCLUDE_PATH ${GENERATOR_SEARCH_PATH})
+
+file(GLOB PROXY_STUB_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/generated/ProxyStubs*.cpp")
+
+add_library(${PROXYLIB} SHARED ${PROXY_STUB_SOURCES}
+ ../plugin/Module.cpp)
+
+target_include_directories(${PROXYLIB} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../plugin/)
+
+target_link_libraries(${PROXYLIB} PRIVATE
+ ${NAMESPACE}Core::${NAMESPACE}Core
+ ${NAMESPACE}COM::${NAMESPACE}COM
+ CompileSettingsDebug::CompileSettingsDebug)
+
+set_target_properties(${PROXYLIB} PROPERTIES
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED YES
+ FRAMEWORK FALSE)
+
+install(TARGETS ${PROXYLIB}
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/proxystubs
+ COMPONENT ${NAMESPACE}_Runtime)
+
+install(FILES INetworkConnectionStats.h
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${NAMESPACE}/interfaces
+ COMPONENT ${NAMESPACE}_Development)
diff --git a/networkstats/interface/INetworkConnectionStats.h b/networkstats/interface/INetworkConnectionStats.h
new file mode 100644
index 00000000..66872ff8
--- /dev/null
+++ b/networkstats/interface/INetworkConnectionStats.h
@@ -0,0 +1,52 @@
+/**
+* If not stated otherwise in this file or this component's LICENSE
+* file the following copyright and licenses apply:
+*
+* Copyright 2025 RDK Management
+*
+* 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.
+**/
+
+#pragma once
+
+#include "Module.h"
+
+namespace WPEFramework {
+namespace Exchange {
+ enum myIDs {
+ ID_NETWORKCONNECTIONSTATS = 0x800004F0,
+ ID_NETWORKCONNECTIONSTATS_NOTIFICATION = ID_NETWORKCONNECTIONSTATS + 1
+ };
+
+ // Interface for network connection statistics
+ struct EXTERNAL INetworkConnectionStats : virtual public Core::IUnknown {
+ enum { ID = ID_NETWORKCONNECTIONSTATS };
+
+ // Configuration method
+ virtual uint32_t Configure(const string configLine) = 0;
+
+ /* @event */
+ struct EXTERNAL INotification : virtual public Core::IUnknown {
+ enum { ID = ID_NETWORKCONNECTIONSTATS_NOTIFICATION };
+
+ // Placeholder for future notification events if needed
+ // Currently no events are exposed as this is an internal plugin
+ };
+
+ // Allow other processes to register/unregister for notifications
+ virtual uint32_t Register(INetworkConnectionStats::INotification* notification) = 0;
+ virtual uint32_t Unregister(INetworkConnectionStats::INotification* notification) = 0;
+ };
+
+} // namespace Exchange
+} // namespace WPEFramework
diff --git a/networkstats/plugin/CMakeLists.txt b/networkstats/plugin/CMakeLists.txt
new file mode 100644
index 00000000..f8b68c36
--- /dev/null
+++ b/networkstats/plugin/CMakeLists.txt
@@ -0,0 +1,123 @@
+#############################################################################
+# If not stated otherwise in this file or this component's LICENSE file the
+# following copyright and licenses apply:
+#
+# Copyright 2025 RDK Management
+#
+# 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.
+#############################################################################
+message("Build NetworkConnectionStats v${PROJECT_VERSION}")
+
+set(PLUGIN_NAME NetworkConnectionStats)
+set(MODULE_NAME ${NAMESPACE}${PLUGIN_NAME})
+set(MODULE_IMPL_NAME ${NAMESPACE}${PLUGIN_NAME}Implementation)
+
+find_package(${NAMESPACE}Core REQUIRED)
+find_package(${NAMESPACE}Plugins REQUIRED)
+find_package(${NAMESPACE}Definitions REQUIRED)
+find_package(CompileSettingsDebug CONFIG REQUIRED)
+
+# Optional Telemetry support
+if (USE_TELEMETRY)
+ find_package(T2 REQUIRED)
+ add_definitions(-DUSE_TELEMETRY)
+ message("Telemetry support enabled")
+endif()
+
+set(PLUGIN_BUILD_REFERENCE ${PROJECT_VERSION} CACHE STRING "To Set the Hash for the plugin")
+add_definitions(-DPLUGIN_BUILD_REFERENCE=${PLUGIN_BUILD_REFERENCE})
+
+# Include directories - use CMAKE_CURRENT_SOURCE_DIR for relative paths
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../interface)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+# Main Plugin Library (in-process)
+add_library(${MODULE_NAME} SHARED
+ Module.cpp
+ NetworkConnectionStats.cpp
+ NetworkConnectionStatsLogger.cpp
+)
+
+target_link_libraries(${MODULE_NAME}
+ PRIVATE
+ CompileSettingsDebug::CompileSettingsDebug
+ ${NAMESPACE}Core::${NAMESPACE}Core
+ ${NAMESPACE}Plugins::${NAMESPACE}Plugins
+ ${NAMESPACE}Definitions::${NAMESPACE}Definitions
+)
+
+target_include_directories(${MODULE_NAME}
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../interface
+)
+
+set_target_properties(${MODULE_NAME} PROPERTIES
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED YES
+ FRAMEWORK FALSE
+)
+
+# Out-of-process Implementation Library
+# Note: Both providers are compiled; selection is done at runtime via config
+add_library(${MODULE_IMPL_NAME} SHARED
+ Module.cpp
+ NetworkConnectionStatsImplementation.cpp
+ NetworkConnectionStatsLogger.cpp
+ ThunderComRPCProvider.cpp
+ ThunderJsonRPCProvider.cpp
+)
+
+target_link_libraries(${MODULE_IMPL_NAME}
+ PRIVATE
+ CompileSettingsDebug::CompileSettingsDebug
+ ${NAMESPACE}Core::${NAMESPACE}Core
+ ${NAMESPACE}Plugins::${NAMESPACE}Plugins
+ ${NAMESPACE}Definitions::${NAMESPACE}Definitions
+ pthread
+)
+
+if (USE_TELEMETRY)
+ target_link_libraries(${MODULE_IMPL_NAME} PRIVATE ${T2_LIBRARIES})
+ target_include_directories(${MODULE_IMPL_NAME} PRIVATE ${T2_INCLUDE_DIRS})
+endif()
+
+target_include_directories(${MODULE_IMPL_NAME}
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../interface
+)
+
+set_target_properties(${MODULE_IMPL_NAME} PROPERTIES
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED YES
+ FRAMEWORK FALSE
+ OUTPUT_NAME ${MODULE_NAME}Implementation
+)
+
+# Install plugin libraries
+install(
+ TARGETS ${MODULE_NAME} ${MODULE_IMPL_NAME}
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/${STORAGE_DIRECTORY}/plugins
+ COMPONENT ${NAMESPACE}_Runtime
+)
+
+# Configuration variables for plugin
+set(PLUGIN_NETWORKCONNECTIONSTATS_AUTOSTART "false" CACHE STRING "Automatically start the plugin")
+set(PLUGIN_NETWORKCONNECTIONSTATS_OUTOFPROCESS "true" CACHE STRING "Run plugin out-of-process")
+set(PLUGIN_NETWORKCONNECTIONSTATS_STARTUPORDER "50" CACHE STRING "Plugin startup order")
+set(PLUGIN_NETWORKCONNECTIONSTATS_REPORTING_INTERVAL "90" CACHE STRING "Reporting interval in seconds (default: 90 seconds)")
+set(PLUGIN_NETWORKCONNECTIONSTATS_PROVIDER_TYPE "comrpc" CACHE STRING "Network data provider type: 'comrpc' or 'jsonrpc' (default: comrpc)")
+
+# Install configuration
+write_config(PLUGINS NetworkConnectionStats)
diff --git a/networkstats/plugin/INetworkData.h b/networkstats/plugin/INetworkData.h
new file mode 100644
index 00000000..1b7c6c91
--- /dev/null
+++ b/networkstats/plugin/INetworkData.h
@@ -0,0 +1,102 @@
+/**
+* If not stated otherwise in this file or this component's LICENSE
+* file the following copyright and licenses apply:
+*
+* Copyright 2025 RDK Management
+*
+* 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.
+**/
+
+#ifndef __INETWORKDATA_H__
+#define __INETWORKDATA_H__
+
+#include
+#include
+#include
+
+class INetworkData
+{
+ public:
+ virtual ~INetworkData() {}
+
+ /* @brief Initialize the network data provider
+ * @return true if initialization successful, false otherwise
+ */
+ virtual bool Initialize() = 0;
+
+ /* @brief Retrieve IPv4 address for specified interface
+ * @param interface_name Interface name (e.g., eth0, wlan0)
+ * @return IPv4 address string
+ */
+ virtual std::string getIpv4Address(std::string interface_name) = 0;
+
+ /* @brief Retrieve IPv6 address for specified interface
+ * @param interface_name Interface name (e.g., eth0, wlan0)
+ * @return IPv6 address string
+ */
+ virtual std::string getIpv6Address(std::string interface_name) = 0;
+
+ /* @brief Get IPv4 gateway/route address from last getIpv4Address call */
+ virtual std::string getIpv4Gateway() = 0;
+
+ /* @brief Get IPv6 gateway/route address from last getIpv6Address call */
+ virtual std::string getIpv6Gateway() = 0;
+
+ /* @brief Get IPv4 primary DNS from last getIpv4Address call */
+ virtual std::string getIpv4PrimaryDns() = 0;
+
+ /* @brief Get IPv6 primary DNS from last getIpv6Address call */
+ virtual std::string getIpv6PrimaryDns() = 0;
+
+ /* @brief Get current network connection type */
+ virtual std::string getConnectionType() = 0;
+
+ /* @brief Get DNS server entries */
+ virtual std::string getDnsEntries() = 0;
+
+ /* @brief Populate network interface data */
+ virtual void populateNetworkData() = 0;
+
+ /* @brief Get current active interface name */
+ virtual std::string getInterface() = 0;
+
+ /* @brief Ping to gateway to check packet loss
+ * @param endpoint Gateway IP address to ping
+ * @param ipversion Either "IPv4" or "IPv6"
+ * @param count Number of ping packets to send
+ * @param timeout Timeout in seconds
+ * @return true if ping successful, false otherwise
+ */
+ virtual bool pingToGatewayCheck(std::string endpoint, std::string ipversion, int count, int timeout) = 0;
+
+ /* @brief Get packet loss from last ping call */
+ virtual std::string getPacketLoss() = 0;
+
+ /* @brief Get average RTT from last ping call */
+ virtual std::string getAvgRtt() = 0;
+
+ /* @brief Subscribe to NetworkManager events
+ * @param eventName Name of the event (e.g., "onInterfaceStateChange")
+ * @param callback Callback function to be called when event fires
+ * @return Error code (Core::ERROR_NONE on success)
+ */
+ virtual uint32_t SubscribeToEvent(const std::string& eventName,
+ std::function callback) = 0;
+
+ protected:
+ INetworkData() {}
+
+};
+
+
+#endif /* __INETWORKDATA_H__ */
diff --git a/networkstats/plugin/Module.cpp b/networkstats/plugin/Module.cpp
new file mode 100644
index 00000000..a05f0666
--- /dev/null
+++ b/networkstats/plugin/Module.cpp
@@ -0,0 +1,22 @@
+/**
+* If not stated otherwise in this file or this component's LICENSE
+* file the following copyright and licenses apply:
+*
+* Copyright 2025 RDK Management
+*
+* 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.
+**/
+
+#include "Module.h"
+
+MODULE_NAME_DECLARATION(BUILD_REFERENCE)
diff --git a/networkstats/plugin/Module.h b/networkstats/plugin/Module.h
new file mode 100644
index 00000000..f6c56b0e
--- /dev/null
+++ b/networkstats/plugin/Module.h
@@ -0,0 +1,30 @@
+/**
+* If not stated otherwise in this file or this component's LICENSE
+* file the following copyright and licenses apply:
+*
+* Copyright 2025 RDK Management
+*
+* 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.
+**/
+
+#pragma once
+#ifndef MODULE_NAME
+#define MODULE_NAME NetworkConnectionStats
+#endif
+
+#include
+#include
+#include
+
+#undef EXTERNAL
+#define EXTERNAL
diff --git a/networkstats/plugin/NetworkConnectionStats.conf.in b/networkstats/plugin/NetworkConnectionStats.conf.in
new file mode 100644
index 00000000..9dc64a05
--- /dev/null
+++ b/networkstats/plugin/NetworkConnectionStats.conf.in
@@ -0,0 +1,13 @@
+callsign = "org.rdk.NetworkConnectionStats"
+startuporder = "@PLUGIN_NETWORKCONNECTIONSTATS_STARTUPORDER@"
+autostart = "@PLUGIN_NETWORKCONNECTIONSTATS_AUTOSTART@"
+
+process = JSON()
+process.add("outofprocess", "@PLUGIN_NETWORKCONNECTIONSTATS_OUTOFPROCESS@")
+process.add("locator", "lib@MODULE_IMPL_NAME@.so")
+
+configuration = JSON()
+configuration.add("root", process)
+configuration.add("reportingInterval", "@PLUGIN_NETWORKCONNECTIONSTATS_REPORTING_INTERVAL@")
+configuration.add("autoStart", True)
+configuration.add("providerType", "@PLUGIN_NETWORKCONNECTIONSTATS_PROVIDER_TYPE@")
diff --git a/networkstats/plugin/NetworkConnectionStats.config b/networkstats/plugin/NetworkConnectionStats.config
new file mode 100644
index 00000000..e751992c
--- /dev/null
+++ b/networkstats/plugin/NetworkConnectionStats.config
@@ -0,0 +1,16 @@
+{
+ "callsign": "org.rdk.NetworkConnectionStats",
+ "locator": "libWPEFrameworkNetworkConnectionStats.so",
+ "classname": "NetworkConnectionStats",
+ "startmode": "Activated",
+ "precondition": ["Platform"],
+ "configuration": {
+ "outofprocess": true,
+ "root": {
+ "mode": "Local",
+ "locator": "libWPEFrameworkNetworkConnectionStatsImplementation.so"
+ },
+ "reportingInterval": 600,
+ "autoStart": true
+ }
+}
diff --git a/networkstats/plugin/NetworkConnectionStats.cpp b/networkstats/plugin/NetworkConnectionStats.cpp
new file mode 100644
index 00000000..cc79a037
--- /dev/null
+++ b/networkstats/plugin/NetworkConnectionStats.cpp
@@ -0,0 +1,176 @@
+/**
+* If not stated otherwise in this file or this component's LICENSE
+* file the following copyright and licenses apply:
+*
+* Copyright 2025 RDK Management
+*
+* 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.
+**/
+
+#include "NetworkConnectionStats.h"
+#include "NetworkConnectionStatsLogger.h"
+
+using namespace NetworkConnectionStatsLogger;
+
+#define API_VERSION_NUMBER_MAJOR 1
+#define API_VERSION_NUMBER_MINOR 0
+#define API_VERSION_NUMBER_PATCH 0
+
+namespace WPEFramework {
+
+ namespace {
+ static Plugin::Metadata metadata(
+ // Version (Major, Minor, Patch)
+ API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH,
+ // Preconditions
+ { PluginHost::ISubSystem::subsystem::PLATFORM },
+ // Terminations
+ {},
+ // Controls
+ {}
+ );
+ }
+
+ namespace Plugin {
+
+ /*
+ * Register NetworkConnectionStats module as WPEFramework plugin
+ * This plugin runs internally without exposing external APIs
+ */
+ SERVICE_REGISTRATION(NetworkConnectionStats, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH);
+
+ NetworkConnectionStats::NetworkConnectionStats()
+ : _service(nullptr)
+ , _connectionId(0)
+ , _networkStats(nullptr)
+ , _notification(this)
+ {
+ NSLOG_INFO("NetworkConnectionStats Constructor");
+ }
+
+ NetworkConnectionStats::~NetworkConnectionStats()
+ {
+ NSLOG_INFO("NetworkConnectionStats Destructor");
+ }
+
+ const string NetworkConnectionStats::Initialize(PluginHost::IShell* service)
+ {
+ string message;
+
+ if (nullptr == service) {
+ NSLOG_ERROR("Initialize: service parameter is nullptr");
+ return _T("Invalid service parameter");
+ }
+ if (nullptr != _service) {
+ NSLOG_ERROR("Initialize: plugin already initialized (_service is not nullptr)");
+ return _T("Plugin already initialized");
+ }
+ if (nullptr != _networkStats) {
+ NSLOG_ERROR("Initialize: plugin already initialized (_networkStats is not nullptr)");
+ return _T("Plugin already initialized");
+ }
+ if (0 != _connectionId) {
+ NSLOG_ERROR("Initialize: plugin already initialized (_connectionId is not 0)");
+ return _T("Plugin already initialized");
+ }
+
+ SYSLOG(Logging::Startup, (_T("Initializing NetworkConnectionStats")));
+ NetworkConnectionStatsLogger::Init();
+
+ // Register the Connection::Notification first
+ _service = service;
+ _service->Register(&_notification);
+
+ // Spawn out-of-process implementation
+ _networkStats = _service->Root(_connectionId, 25000, _T("NetworkConnectionStatsImplementation"));
+
+ NSLOG_INFO("NetworkConnectionStats::Initialize: PID=%u, ConnectionID=%u", getpid(), _connectionId);
+
+ if (nullptr != _networkStats) {
+ SYSLOG(Logging::Startup, (_T("Configuring NetworkConnectionStats")));
+ if (_networkStats->Configure(_service->ConfigLine()) != Core::ERROR_NONE)
+ {
+ SYSLOG(Logging::Shutdown, (_T("NetworkConnectionStats failed to configure")));
+ message = _T("NetworkConnectionStats could not be configured");
+ }
+ else
+ {
+ SYSLOG(Logging::Startup, (_T("NetworkConnectionStats configured successfully")));
+ }
+ } else {
+ // Something went wrong, clean up
+ SYSLOG(Logging::Shutdown, (_T("NetworkConnectionStats out-of-process creation failed")));
+ NSLOG_ERROR("Failed to initialize NetworkConnectionStats");
+ _service->Unregister(&_notification);
+ _service = nullptr;
+ message = _T("NetworkConnectionStats plugin could not be initialised");
+ }
+
+ return message;
+ }
+
+ void NetworkConnectionStats::Deinitialize(PluginHost::IShell* service)
+ {
+ if (_service != service) {
+ NSLOG_ERROR("Deinitialize: service parameter mismatch");
+ return;
+ }
+ if (nullptr == _networkStats) {
+ NSLOG_ERROR("Deinitialize: _networkStats is nullptr");
+ return;
+ }
+
+ SYSLOG(Logging::Shutdown, (_T("Deinitializing NetworkConnectionStats")));
+
+ if (_networkStats != nullptr)
+ {
+ SYSLOG(Logging::Shutdown, (_T("Unregister Thunder Notifications for NetworkConnectionStats")));
+ _service->Unregister(&_notification);
+
+ RPC::IRemoteConnection* connection = service->RemoteConnection(_connectionId);
+
+ SYSLOG(Logging::Shutdown, (_T("Release of COMRPC Interface of NetworkConnectionStats")));
+ _networkStats->Release();
+
+ if (connection != nullptr)
+ {
+ connection->Terminate();
+ connection->Release();
+ }
+ }
+
+ // Set everything back to default
+ _connectionId = 0;
+ _service = nullptr;
+ _networkStats = nullptr;
+ }
+
+ string NetworkConnectionStats::Information() const
+ {
+ return ("Internal network diagnostics and monitoring plugin - no external APIs");
+ }
+
+ void NetworkConnectionStats::Deactivated(RPC::IRemoteConnection* connection)
+ {
+ if (connection->Id() == _connectionId) {
+ if (nullptr == _service) {
+ NSLOG_ERROR("Deactivated: _service is nullptr");
+ return;
+ }
+ Core::IWorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(_service,
+ PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE));
+ }
+ }
+
+} // namespace Plugin
+} // namespace WPEFramework
diff --git a/networkstats/plugin/NetworkConnectionStats.h b/networkstats/plugin/NetworkConnectionStats.h
new file mode 100644
index 00000000..a42af25c
--- /dev/null
+++ b/networkstats/plugin/NetworkConnectionStats.h
@@ -0,0 +1,88 @@
+/**
+* If not stated otherwise in this file or this component's LICENSE
+* file the following copyright and licenses apply:
+*
+* Copyright 2025 RDK Management
+*
+* 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.
+**/
+
+#pragma once
+
+#include "Module.h"
+#include "INetworkConnectionStats.h"
+#include
+
+namespace WPEFramework {
+ namespace Plugin {
+ // Internal-only plugin - no external APIs exposed
+ class NetworkConnectionStats : public PluginHost::IPlugin {
+ private:
+ class Notification : public RPC::IRemoteConnection::INotification {
+ private:
+ Notification() = delete;
+ Notification(const Notification&) = delete;
+ Notification& operator=(const Notification&) = delete;
+
+ public:
+ explicit Notification(NetworkConnectionStats* parent)
+ : _parent(*parent) {
+ ASSERT(parent != nullptr);
+ }
+
+ virtual ~Notification() {}
+
+ BEGIN_INTERFACE_MAP(Notification)
+ INTERFACE_ENTRY(RPC::IRemoteConnection::INotification)
+ END_INTERFACE_MAP
+
+ void Activated(RPC::IRemoteConnection*) override {
+ TRACE(Trace::Information, (_T("NetworkConnectionStats Activated")));
+ }
+
+ void Deactivated(RPC::IRemoteConnection* connection) override {
+ TRACE(Trace::Information, (_T("NetworkConnectionStats Deactivated")));
+ _parent.Deactivated(connection);
+ }
+
+ private:
+ NetworkConnectionStats& _parent;
+ };
+
+ public:
+ NetworkConnectionStats(const NetworkConnectionStats&) = delete;
+ NetworkConnectionStats& operator=(const NetworkConnectionStats&) = delete;
+ NetworkConnectionStats();
+ virtual ~NetworkConnectionStats();
+
+ BEGIN_INTERFACE_MAP(NetworkConnectionStats)
+ INTERFACE_ENTRY(PluginHost::IPlugin)
+ INTERFACE_AGGREGATE(Exchange::INetworkConnectionStats, _networkStats)
+ END_INTERFACE_MAP
+
+ // IPlugin methods
+ const string Initialize(PluginHost::IShell* service) override;
+ void Deinitialize(PluginHost::IShell* service) override;
+ string Information() const override;
+
+ private:
+ void Deactivated(RPC::IRemoteConnection* connection);
+
+ private:
+ PluginHost::IShell* _service{};
+ uint32_t _connectionId{};
+ Exchange::INetworkConnectionStats* _networkStats{};
+ Core::Sink _notification;
+ };
+ } // namespace Plugin
+} // namespace WPEFramework
diff --git a/networkstats/plugin/NetworkConnectionStatsImplementation.cpp b/networkstats/plugin/NetworkConnectionStatsImplementation.cpp
new file mode 100644
index 00000000..24b14b10
--- /dev/null
+++ b/networkstats/plugin/NetworkConnectionStatsImplementation.cpp
@@ -0,0 +1,552 @@
+/**
+* If not stated otherwise in this file or this component's LICENSE
+* file the following copyright and licenses apply:
+*
+* Copyright 2025 RDK Management
+*
+* 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.
+**/
+
+#include "NetworkConnectionStatsImplementation.h"
+#include "NetworkConnectionStatsLogger.h"
+#include
+
+using namespace NetworkConnectionStatsLogger;
+
+#define API_VERSION_NUMBER_MAJOR 1
+#define API_VERSION_NUMBER_MINOR 0
+#define API_VERSION_NUMBER_PATCH 0
+#define SUBSCRIPTION_RETRY_INTERVAL_MS 500
+
+namespace WPEFramework {
+namespace Plugin {
+
+ SERVICE_REGISTRATION(NetworkConnectionStatsImplementation, 1, 0);
+
+ NetworkConnectionStatsImplementation::NetworkConnectionStatsImplementation()
+ : _adminLock()
+ , m_provider(nullptr)
+ , m_interface("")
+ , m_ipv4Address("")
+ , m_ipv6Address("")
+ , m_ipv4Route("")
+ , m_ipv6Route("")
+ , m_ipv4Dns("")
+ , m_ipv6Dns("")
+ , _periodicReportingEnabled(true) // Auto-enabled
+ , _reportingIntervalSeconds(600) // Default 10 minutes (600 seconds)
+ , _stopReporting(false)
+ , _stopSubscriptionRetry(false)
+ , m_subsIfaceStateChange(false)
+ , m_subsActIfaceChange(false)
+ , m_subsIPAddrChange(false)
+ {
+
+ NSLOG_INFO("NetworkConnectionStatsImplemen tation Constructor");
+ /* Set NetworkManager Out-Process name to be NWMgrPlugin */
+ Core::ProcessInfo().Name("NetworkConnectionStats");
+ NSLOG_INFO((_T("NetworkConnectionStats Out-Of-Process Instantiation; SHA: " _T(EXPAND_AND_QUOTE(PLUGIN_BUILD_REFERENCE)))));
+#if USE_TELEMETRY
+ t2_init("networkstats");
+#endif
+ }
+
+ NetworkConnectionStatsImplementation::~NetworkConnectionStatsImplementation()
+ {
+ NSLOG_INFO("NetworkConnectionStatsImplementation Destructor");
+
+ // Stop subscription retry thread
+ _stopSubscriptionRetry = true;
+ if (_subscriptionRetryThread.joinable()) {
+ _subscriptionRetryThread.join();
+ }
+
+ // Stop reporting threads
+ _stopReporting = true;
+
+ // Push STOP message to unblock consumer thread
+ {
+ std::lock_guard lock(_queueMutex);
+ _messageQueue.push({MessageType::STOP});
+ }
+ _queueCondition.notify_one();
+
+ // Wait for threads to finish
+ if (_timerThread.joinable()) {
+ _timerThread.join();
+ }
+ if (_reportingThread.joinable()) {
+ _reportingThread.join();
+ }
+
+ if (m_provider) {
+ delete m_provider;
+ m_provider = nullptr;
+ }
+ }
+
+ /**
+ * Register a notification callback
+ */
+ uint32_t NetworkConnectionStatsImplementation::Register(INetworkConnectionStats::INotification* notification)
+ {
+ if (nullptr == notification) {
+ NSLOG_ERROR("Register: notification parameter is nullptr");
+ return Core::ERROR_BAD_REQUEST;
+ }
+
+ NSLOG_INFO("Register::Enter");
+ _notificationLock.Lock();
+
+ // Make sure we can't register the same notification callback multiple times
+ if (std::find(_notificationCallbacks.begin(), _notificationCallbacks.end(), notification) == _notificationCallbacks.end()) {
+ _notificationCallbacks.push_back(notification);
+ notification->AddRef();
+ }
+
+ _notificationLock.Unlock();
+
+ return Core::ERROR_NONE;
+ }
+
+ /**
+ * Unregister a notification callback
+ */
+ uint32_t NetworkConnectionStatsImplementation::Unregister(INetworkConnectionStats::INotification* notification)
+ {
+ if (nullptr == notification) {
+ NSLOG_ERROR("Unregister: notification parameter is nullptr");
+ return Core::ERROR_BAD_REQUEST;
+ }
+
+ NSLOG_INFO("Unregister::Enter");
+ _notificationLock.Lock();
+
+ // Remove the notification callback if it exists
+ auto itr = std::find(_notificationCallbacks.begin(), _notificationCallbacks.end(), notification);
+ if (itr != _notificationCallbacks.end()) {
+ (*itr)->Release();
+ _notificationCallbacks.erase(itr);
+ }
+
+ _notificationLock.Unlock();
+
+ return Core::ERROR_NONE;
+ }
+
+
+ uint32_t NetworkConnectionStatsImplementation::Configure(const string configLine)
+ {
+ NSLOG_INFO("NetworkConnectionStatsImplementation::Configure");
+ uint32_t result = Core::ERROR_NONE;
+
+ // Parse configuration
+ JsonObject config;
+ config.FromString(configLine);
+
+ if (config.HasLabel("reportingInterval")) {
+ _reportingIntervalSeconds = config["reportingInterval"].Number();
+ NSLOG_INFO("Reporting interval set to %u seconds (%u minutes)",
+ _reportingIntervalSeconds.load(), _reportingIntervalSeconds.load() / 60);
+ }
+
+ if (config.HasLabel("autoStart")) {
+ _periodicReportingEnabled = config["autoStart"].Boolean();
+ NSLOG_INFO("Auto-start set to %s", _periodicReportingEnabled ? "true" : "false");
+ }
+
+ // Get provider type from configuration (default: comrpc)
+ std::string providerType = "comrpc";
+ if (config.HasLabel("providerType")) {
+ providerType = config["providerType"].Value();
+ }
+
+ // Create network provider using factory
+ m_provider = NetworkDataProviderFactory::CreateProvider(providerType);
+ if (m_provider == nullptr) {
+ NSLOG_ERROR("Failed to create network provider for type: %s", providerType.c_str());
+ result = Core::ERROR_GENERAL;
+ } else {
+ auto factoryType = NetworkDataProviderFactory::ParseProviderType(providerType);
+ std::string typeName = NetworkDataProviderFactory::GetProviderTypeName(factoryType);
+ NSLOG_INFO("%s provider created", typeName.c_str());
+
+ // Initialize the provider
+ if (m_provider->Initialize()) {
+ NSLOG_INFO("%s provider initialized successfully", typeName.c_str());
+
+ // Subscribe to NetworkManager events (with automatic retry)
+ _stopSubscriptionRetry = false;
+ subscribeToEvents();
+ _subscriptionRetryThread = std::thread(&NetworkConnectionStatsImplementation::subscriptionRetryThread, this);
+
+ // Generate initial report
+ generateReport();
+
+ // Start timer and consumer threads if enabled
+ if (_periodicReportingEnabled) {
+ _stopReporting = false;
+ _timerThread = std::thread(&NetworkConnectionStatsImplementation::timerThread, this);
+ _reportingThread = std::thread(&NetworkConnectionStatsImplementation::periodicReportingThread, this);
+ NSLOG_INFO("Timer and reporting threads started with %u second interval (%u minutes)",
+ _reportingIntervalSeconds.load(), _reportingIntervalSeconds.load() / 60);
+ }
+ } else {
+ auto factoryType = NetworkDataProviderFactory::ParseProviderType(providerType);
+ std::string typeName = NetworkDataProviderFactory::GetProviderTypeName(factoryType);
+ NSLOG_ERROR("Failed to initialize %s provider", typeName.c_str());
+ result = Core::ERROR_GENERAL;
+ }
+ }
+
+ return result;
+ }
+
+ void NetworkConnectionStatsImplementation::timerThread()
+ {
+ NSLOG_INFO("Timer thread started");
+
+ while (!_stopReporting && _periodicReportingEnabled) {
+ // Sleep for configured interval
+ std::this_thread::sleep_for(std::chrono::seconds(_reportingIntervalSeconds.load()));
+
+ if (_stopReporting || !_periodicReportingEnabled) {
+ break;
+ }
+
+ // Queue report generation
+ queueReportGeneration("Timer");
+ }
+
+ NSLOG_INFO("Timer thread stopped");
+ }
+
+ void NetworkConnectionStatsImplementation::periodicReportingThread()
+ {
+ NSLOG_INFO("Periodic reporting thread (consumer) started");
+
+ while (!_stopReporting && _periodicReportingEnabled) {
+ Message msg;
+
+ // Wait for message in queue
+ {
+ std::unique_lock lock(_queueMutex);
+ _queueCondition.wait(lock, [this] {
+ return !_messageQueue.empty() || _stopReporting;
+ });
+
+ if (_stopReporting) {
+ break;
+ }
+
+ if (_messageQueue.empty()) {
+ continue;
+ }
+
+ msg = _messageQueue.front();
+ _messageQueue.pop();
+ }
+
+ // Process message
+ if (msg.type == MessageType::GENERATE_REPORT) {
+ NSLOG_INFO("Consumer: Processing GENERATE_REPORT message");
+ generateReport();
+ NSLOG_INFO("Consumer: Periodic report generated");
+ } else if (msg.type == MessageType::STOP) {
+ NSLOG_INFO("Consumer: Received STOP message");
+ break;
+ }
+ }
+
+ NSLOG_INFO("Periodic reporting thread (consumer) stopped");
+ }
+
+ void NetworkConnectionStatsImplementation::generateReport()
+ {
+ NSLOG_INFO("Generating network diagnostics report");
+
+ _adminLock.Lock();
+
+ // Run all diagnostic checks
+ connectionTypeCheck();
+ connectionIpCheck();
+ defaultIpv4RouteCheck();
+ defaultIpv6RouteCheck();
+ networkDnsCheck();
+ gatewayPacketLossCheck();
+
+ _adminLock.Unlock();
+
+ NSLOG_INFO("Network diagnostics report completed");
+ }
+
+ void NetworkConnectionStatsImplementation::logTelemetry(const std::string& eventName, const std::string& message)
+ {
+ NSLOG_INFO("NS_T2: %s:%s", eventName.c_str(), message.c_str());
+#if USE_TELEMETRY
+ T2ERROR t2error = t2_event_s(eventName.c_str(), (char*)message.c_str());
+ if (t2error != T2ERROR_SUCCESS) {
+ NSLOG_ERROR("t2_event_s(\"%s\", \"%s\") failed with error %d",
+ eventName.c_str(), message.c_str(), t2error);
+ }
+#endif
+ }
+
+ void NetworkConnectionStatsImplementation::connectionTypeCheck()
+ {
+ if (m_provider) {
+ std::string connType = m_provider->getConnectionType();
+ NSLOG_INFO("Connection type: %s", connType.c_str());
+ logTelemetry("Connection_Type", connType);
+ }
+ }
+
+ void NetworkConnectionStatsImplementation::connectionIpCheck()
+ {
+ if (m_provider) {
+ m_interface = m_provider->getInterface();
+
+ // Get IPv4 settings
+ m_ipv4Address = m_provider->getIpv4Address(m_interface);
+ m_ipv4Route = m_provider->getIpv4Gateway();
+ m_ipv4Dns = m_provider->getIpv4PrimaryDns();
+
+ // Get IPv6 settings
+ m_ipv6Address = m_provider->getIpv6Address(m_interface);
+ m_ipv6Route = m_provider->getIpv6Gateway();
+ m_ipv6Dns = m_provider->getIpv6PrimaryDns();
+
+ NSLOG_INFO("Interface: %s, IPv4: %s, IPv6: %s",
+ m_interface.c_str(), m_ipv4Address.c_str(), m_ipv6Address.c_str());
+ NSLOG_INFO("IPv4 Gateway: %s, DNS: %s",
+ m_ipv4Route.c_str(), m_ipv4Dns.c_str());
+ NSLOG_INFO("IPv6 Gateway: %s, DNS: %s",
+ m_ipv6Route.c_str(), m_ipv6Dns.c_str());
+
+ // Log telemetry events
+ logTelemetry("Network_Interface", m_interface);
+ logTelemetry("Network_IPv4_Address", m_ipv4Address);
+ logTelemetry("Network_IPv6_Address", m_ipv6Address);
+ logTelemetry("IPv4_DNS", m_ipv4Dns);
+ logTelemetry("IPv6_DNS", m_ipv6Dns);
+ }
+ }
+
+ void NetworkConnectionStatsImplementation::defaultIpv4RouteCheck()
+ {
+ if (!m_ipv4Address.empty() && m_ipv4Address != "0.0.0.0") {
+ if (!m_ipv4Route.empty() && m_ipv4Route != "0.0.0.0") {
+ NSLOG_INFO("IPv4: Interface %s has gateway %s",
+ m_interface.c_str(), m_ipv4Route.c_str());
+ logTelemetry("IPv4_Route_Check", "Success," + m_interface + "," + m_ipv4Route);
+ } else {
+ NSLOG_INFO("IPv4: No valid gateway for interface %s", m_interface.c_str());
+ logTelemetry("IPv4_Route_Check", "Failed,No valid gateway," + m_interface);
+ }
+ }
+ }
+
+ void NetworkConnectionStatsImplementation::defaultIpv6RouteCheck()
+ {
+ if (!m_ipv6Address.empty() && m_ipv6Address != "::") {
+ if (!m_ipv6Route.empty() && m_ipv6Route != "::") {
+ NSLOG_INFO("IPv6: Interface %s has gateway %s",
+ m_interface.c_str(), m_ipv6Route.c_str());
+ logTelemetry("IPv6_Route_Check", "Success," + m_interface + "," + m_ipv6Route);
+ } else {
+ NSLOG_INFO("IPv6: No valid gateway for interface %s", m_interface.c_str());
+ logTelemetry("IPv6_Route_Check", "Failed,No valid gateway," + m_interface);
+ }
+ }
+ }
+
+ void NetworkConnectionStatsImplementation::gatewayPacketLossCheck()
+ {
+ if (!m_provider) {
+ return;
+ }
+
+ // Check IPv4 gateway packet loss
+ if (!m_ipv4Route.empty() && m_ipv4Route != "0.0.0.0") {
+ NSLOG_INFO("Pinging IPv4 gateway: %s", m_ipv4Route.c_str());
+ bool success = m_provider->pingToGatewayCheck(m_ipv4Route, "IPv4", 10, 30);
+ std::string packetLoss = m_provider->getPacketLoss();
+ std::string avgRtt = m_provider->getAvgRtt();
+ if (success) {
+ NSLOG_INFO("IPv4 gateway ping - Loss: %s%%, RTT: %sms",
+ packetLoss.c_str(), avgRtt.c_str());
+
+ logTelemetry("IPv4_Gateway_Packet_Loss", packetLoss);
+ logTelemetry("IPv4_Gateway_RTT", avgRtt);
+ } else {
+ NSLOG_ERROR("IPv4 gateway ping failed");
+ logTelemetry("IPv4_Gateway_Packet_Loss", packetLoss);
+ logTelemetry("IPv4_Gateway_RTT", avgRtt);
+ }
+ }
+
+ // Check IPv6 gateway packet loss
+ if (!m_ipv6Route.empty() && m_ipv6Route != "::") {
+ // Append zone ID for link-local IPv6 addresses
+ std::string ipv6Gateway = m_ipv6Route;
+ if (ipv6Gateway.find("fe80::") == 0 && !m_interface.empty()) {
+ ipv6Gateway += "%" + m_interface;
+ }
+ NSLOG_INFO("Pinging IPv6 gateway: %s", ipv6Gateway.c_str());
+ bool success = m_provider->pingToGatewayCheck(ipv6Gateway, "IPv6", 10, 30);
+ std::string packetLoss = m_provider->getPacketLoss();
+ std::string avgRtt = m_provider->getAvgRtt();
+ if (success) {
+ NSLOG_INFO("IPv6 gateway ping - Loss: %s%%, RTT: %sms",
+ packetLoss.c_str(), avgRtt.c_str());
+
+ logTelemetry("IPv6_Gateway_Packet_Loss", packetLoss);
+ logTelemetry("IPv6_Gateway_RTT", avgRtt);
+ } else {
+ NSLOG_ERROR("IPv6 gateway ping failed");
+ logTelemetry("IPv6_Gateway_Packet_Loss", packetLoss);
+ logTelemetry("IPv6_Gateway_RTT", avgRtt);
+ }
+ }
+ }
+
+ void NetworkConnectionStatsImplementation::networkDnsCheck()
+ {
+ bool hasDns = false;
+
+ if (!m_ipv4Dns.empty()) {
+ NSLOG_INFO("IPv4 DNS: %s", m_ipv4Dns.c_str());
+ hasDns = true;
+ }
+
+ if (!m_ipv6Dns.empty()) {
+ NSLOG_INFO("IPv6 DNS: %s", m_ipv6Dns.c_str());
+ hasDns = true;
+ }
+
+ if (hasDns) {
+ NSLOG_INFO("DNS configuration present");
+ logTelemetry("DNS_Status", "DNS configured");
+ } else {
+ NSLOG_WARNING("No DNS configuration found");
+ logTelemetry("DNS_Status", "No DNS configured");
+ }
+ }
+
+ /** NetworkManager Event Subscription */
+ void NetworkConnectionStatsImplementation::subscribeToEvents()
+ {
+ uint32_t errCode = Core::ERROR_GENERAL;
+ if (m_provider)
+ {
+ if (!m_subsIfaceStateChange)
+ {
+ errCode = m_provider->SubscribeToEvent("onInterfaceStateChange",
+ [this](const WPEFramework::Core::JSON::VariantContainer& parameters) {
+ this->ReportonInterfaceStateChange(parameters);
+ });
+ if (Core::ERROR_NONE == errCode)
+ m_subsIfaceStateChange = true;
+ else
+ NSLOG_ERROR("Subscribe to onInterfaceStateChange failed, errCode: %u", errCode);
+ }
+
+ if (!m_subsActIfaceChange)
+ {
+ errCode = m_provider->SubscribeToEvent("onActiveInterfaceChange",
+ [this](const WPEFramework::Core::JSON::VariantContainer& parameters) {
+ this->ReportonActiveInterfaceChange(parameters);
+ });
+ if (Core::ERROR_NONE == errCode)
+ m_subsActIfaceChange = true;
+ else
+ NSLOG_ERROR("Subscribe to onActiveInterfaceChange failed, errCode: %u", errCode);
+ }
+
+ if (!m_subsIPAddrChange)
+ {
+ errCode = m_provider->SubscribeToEvent("onIPAddressChange",
+ [this](const WPEFramework::Core::JSON::VariantContainer& parameters) {
+ this->ReportonIPAddressChange(parameters);
+ });
+ if (Core::ERROR_NONE == errCode)
+ m_subsIPAddrChange = true;
+ else
+ NSLOG_ERROR("Subscribe to onIPAddressChange failed, errCode: %u", errCode);
+ }
+ }
+ else
+ NSLOG_ERROR("m_provider is null");
+ }
+
+ void NetworkConnectionStatsImplementation::subscriptionRetryThread()
+ {
+ NSLOG_INFO("Subscription retry thread started");
+
+ while (!_stopSubscriptionRetry)
+ {
+ // Check if all subscriptions are successful
+ if (m_subsIfaceStateChange && m_subsActIfaceChange && m_subsIPAddrChange)
+ {
+ NSLOG_INFO("All required events subscribed; Stopping retry thread");
+ break;
+ }
+
+ // Wait before retry
+ std::this_thread::sleep_for(std::chrono::milliseconds(SUBSCRIPTION_RETRY_INTERVAL_MS));
+
+ if (_stopSubscriptionRetry)
+ break;
+
+ // Retry subscription
+ NSLOG_INFO("Retrying event subscriptions...");
+ subscribeToEvents();
+ }
+
+ NSLOG_INFO("Subscription retry thread stopped");
+ }
+
+ /** Event Handling - Report methods */
+ void NetworkConnectionStatsImplementation::ReportonInterfaceStateChange(const WPEFramework::Core::JSON::VariantContainer& parameters)
+ {
+ queueReportGeneration("Event: onInterfaceStateChange", ¶meters);
+ }
+
+ void NetworkConnectionStatsImplementation::ReportonActiveInterfaceChange(const WPEFramework::Core::JSON::VariantContainer& parameters)
+ {
+ queueReportGeneration("Event: onActiveInterfaceChange", ¶meters);
+ }
+
+ void NetworkConnectionStatsImplementation::ReportonIPAddressChange(const WPEFramework::Core::JSON::VariantContainer& parameters)
+ {
+ queueReportGeneration("Event: onIPAddressChange", ¶meters);
+ }
+
+ void NetworkConnectionStatsImplementation::queueReportGeneration(const std::string& source, const WPEFramework::Core::JSON::VariantContainer* parameters)
+ {
+ // Log event parameters if provided
+ if (parameters != nullptr) {
+ string json;
+ parameters->ToString(json);
+ NSLOG_INFO("%s - params: %s", source.c_str(), json.c_str());
+ }
+
+ // Queue report generation
+ std::lock_guard lock(_queueMutex);
+ _messageQueue.push({MessageType::GENERATE_REPORT});
+ NSLOG_INFO("%s: Pushed GENERATE_REPORT to queue", source.c_str());
+ _queueCondition.notify_one();
+ }
+
+} // namespace Plugin
+} // namespace WPEFramework
diff --git a/networkstats/plugin/NetworkConnectionStatsImplementation.h b/networkstats/plugin/NetworkConnectionStatsImplementation.h
new file mode 100644
index 00000000..c790ee8b
--- /dev/null
+++ b/networkstats/plugin/NetworkConnectionStatsImplementation.h
@@ -0,0 +1,134 @@
+/**
+* If not stated otherwise in this file or this component's LICENSE
+* file the following copyright and licenses apply:
+*
+* Copyright 2025 RDK Management
+*
+* 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.
+**/
+
+#pragma once
+
+#include "Module.h"
+#include "INetworkConnectionStats.h"
+#include "INetworkData.h"
+#include "NetworkDataProviderFactory.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#if USE_TELEMETRY
+#include
+#endif
+
+namespace WPEFramework {
+namespace Plugin {
+
+ // Internal implementation - runs network diagnostics automatically
+ // No external APIs exposed
+ class NetworkConnectionStatsImplementation
+ : public Exchange::INetworkConnectionStats {
+
+ public:
+
+ NetworkConnectionStatsImplementation(const NetworkConnectionStatsImplementation&) = delete;
+ NetworkConnectionStatsImplementation& operator=(const NetworkConnectionStatsImplementation&) = delete;
+ NetworkConnectionStatsImplementation();
+ virtual ~NetworkConnectionStatsImplementation();
+
+ BEGIN_INTERFACE_MAP(NetworkConnectionStatsImplementation)
+ INTERFACE_ENTRY(Exchange::INetworkConnectionStats)
+ END_INTERFACE_MAP
+
+ // Handle Notification registration/removal
+ uint32_t Register(INetworkConnectionStats::INotification* notification) override;
+ uint32_t Unregister(INetworkConnectionStats::INotification* notification) override;
+
+ // Configuration method
+ uint32_t Configure(const string configLine) override;
+
+ private:
+ // Message queue types
+ enum class MessageType {
+ GENERATE_REPORT,
+ STOP
+ };
+
+ struct Message {
+ MessageType type;
+ };
+
+ // Internal diagnostic methods
+ void connectionTypeCheck();
+ void connectionIpCheck();
+ void defaultIpv4RouteCheck();
+ void defaultIpv6RouteCheck();
+ void gatewayPacketLossCheck();
+ void networkDnsCheck();
+ void generateReport();
+ void logTelemetry(const std::string& eventName, const std::string& message);
+ void timerThread();
+ void periodicReportingThread();
+
+ // NetworkManager event subscription
+ void subscribeToEvents();
+ void subscriptionRetryThread();
+ void ReportonInterfaceStateChange(const WPEFramework::Core::JSON::VariantContainer& parameters);
+ void ReportonActiveInterfaceChange(const WPEFramework::Core::JSON::VariantContainer& parameters);
+ void ReportonIPAddressChange(const WPEFramework::Core::JSON::VariantContainer& parameters);
+ void queueReportGeneration(const std::string& source, const WPEFramework::Core::JSON::VariantContainer* parameters = nullptr);
+
+ private:
+ mutable Core::CriticalSection _adminLock;
+
+ // Notification callbacks
+ std::list _notificationCallbacks;
+ Core::CriticalSection _notificationLock;
+
+ // Network data provider
+ INetworkData* m_provider;
+
+ // Cached network data
+ std::string m_interface;
+ std::string m_ipv4Address;
+ std::string m_ipv6Address;
+ std::string m_ipv4Route;
+ std::string m_ipv6Route;
+ std::string m_ipv4Dns;
+ std::string m_ipv6Dns;
+
+ // Periodic reporting
+ std::atomic _periodicReportingEnabled;
+ std::atomic _reportingIntervalSeconds;
+ std::thread _timerThread;
+ std::thread _reportingThread;
+ std::atomic _stopReporting;
+
+ // Message queue system
+ std::queue _messageQueue;
+ std::mutex _queueMutex;
+ std::condition_variable _queueCondition;
+
+ // NetworkManager event subscription
+ std::thread _subscriptionRetryThread;
+ std::atomic _stopSubscriptionRetry;
+ bool m_subsIfaceStateChange;
+ bool m_subsActIfaceChange;
+ bool m_subsIPAddrChange;
+ };
+
+} // namespace Plugin
+} // namespace WPEFramework
diff --git a/networkstats/plugin/NetworkConnectionStatsLogger.cpp b/networkstats/plugin/NetworkConnectionStatsLogger.cpp
new file mode 100644
index 00000000..13fc6375
--- /dev/null
+++ b/networkstats/plugin/NetworkConnectionStatsLogger.cpp
@@ -0,0 +1,139 @@
+/**
+* If not stated otherwise in this file or this component's LICENSE
+* file the following copyright and licenses apply:
+*
+* Copyright 2025 RDK Management
+*
+* 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.
+**/
+
+#include "NetworkConnectionStatsLogger.h"
+#include
+#include
+#include
+#include
+#include
+#include