mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #8592 from deepikabhavnani/nw_stats_ver2
Network Socket Statisticspull/8798/head
commit
2009f028b1
|
@ -38,6 +38,10 @@ NetworkInterface *net;
|
|||
Timer tc_bucket; // Timer to limit a test cases run time
|
||||
}
|
||||
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
mbed_stats_socket_t tcp_stats[MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT];
|
||||
#endif
|
||||
|
||||
char tcp_global::rx_buffer[RX_BUFF_SIZE];
|
||||
char tcp_global::tx_buffer[TX_BUFF_SIZE];
|
||||
|
||||
|
@ -115,6 +119,13 @@ int split2half_rmng_tcp_test_time()
|
|||
return (tcp_global::TESTS_TIMEOUT - tc_bucket.read()) / 2;
|
||||
}
|
||||
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
int fetch_stats()
|
||||
{
|
||||
return SocketStats::mbed_stats_socket_get_each(&tcp_stats[0], MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Test setup
|
||||
utest::v1::status_t greentea_setup(const size_t number_of_cases)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,11 @@ void fill_tx_buffer_ascii(char *buff, size_t len);
|
|||
nsapi_error_t tcpsocket_connect_to_echo_srv(TCPSocket &sock);
|
||||
nsapi_error_t tcpsocket_connect_to_discard_srv(TCPSocket &sock);
|
||||
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
extern mbed_stats_socket_t tcp_stats[MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT];
|
||||
int fetch_stats(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Single testcase might take only half of the remaining execution time
|
||||
*/
|
||||
|
|
|
@ -114,6 +114,13 @@ void tcpsocket_echotest_nonblock_receiver(void *receive_bytes)
|
|||
|
||||
void TCPSOCKET_ECHOTEST_NONBLOCK()
|
||||
{
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
int j = 0;
|
||||
int count = fetch_stats();
|
||||
for (; j < count; j++) {
|
||||
TEST_ASSERT_EQUAL(SOCK_CLOSED, tcp_stats[j].state);
|
||||
}
|
||||
#endif
|
||||
tc_exec_time.start();
|
||||
time_allotted = split2half_rmng_tcp_test_time(); // [s]
|
||||
|
||||
|
@ -160,6 +167,15 @@ void TCPSOCKET_ECHOTEST_NONBLOCK()
|
|||
bytes2send -= sent;
|
||||
}
|
||||
printf("[Sender#%02d] bytes sent: %d\n", s_idx, pkt_s);
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
count = fetch_stats();
|
||||
for (j = 0; j < count; j++) {
|
||||
if ((tcp_stats[j].state == SOCK_OPEN) && (tcp_stats[j].proto == NSAPI_TCP)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
TEST_ASSERT_EQUAL(bytes2send, tcp_stats[j].sent_bytes);
|
||||
#endif
|
||||
tx_sem.wait(split2half_rmng_tcp_test_time());
|
||||
thread->join();
|
||||
delete thread;
|
||||
|
|
|
@ -26,6 +26,12 @@ using namespace utest::v1;
|
|||
|
||||
void TCPSOCKET_OPEN_CLOSE_REPEAT()
|
||||
{
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
int count = fetch_stats();
|
||||
for (int j = 0; j < count; j++) {
|
||||
TEST_ASSERT_EQUAL(SOCK_CLOSED, tcp_stats[j].state);
|
||||
}
|
||||
#endif
|
||||
TCPSocket *sock = new TCPSocket;
|
||||
if (!sock) {
|
||||
TEST_FAIL();
|
||||
|
@ -36,4 +42,10 @@ void TCPSOCKET_OPEN_CLOSE_REPEAT()
|
|||
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock->close());
|
||||
}
|
||||
delete sock;
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
count = fetch_stats();
|
||||
for (int j = 0; j < count; j++) {
|
||||
TEST_ASSERT_EQUAL(SOCK_CLOSED, tcp_stats[j].state);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -70,6 +70,17 @@ void TCPSOCKET_OPEN_LIMIT()
|
|||
break;
|
||||
}
|
||||
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
int count = fetch_stats();
|
||||
int open_count = 0;
|
||||
for (int j = 0; j < count; j++) {
|
||||
if ((tcp_stats[j].state == SOCK_OPEN) && (tcp_stats[j].proto == NSAPI_TCP)) {
|
||||
open_count++;
|
||||
}
|
||||
}
|
||||
TEST_ASSERT(open_count >= 4);
|
||||
#endif
|
||||
|
||||
TCPSocketItem *tmp;
|
||||
for (TCPSocketItem *it = socket_list_head; it;) {
|
||||
++open_sockets[i];
|
||||
|
|
|
@ -37,6 +37,10 @@ namespace {
|
|||
NetworkInterface *net;
|
||||
}
|
||||
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
mbed_stats_socket_t udp_stats[MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT];
|
||||
#endif
|
||||
|
||||
NetworkInterface *get_interface()
|
||||
{
|
||||
return net;
|
||||
|
@ -76,6 +80,13 @@ void fill_tx_buffer_ascii(char *buff, size_t len)
|
|||
}
|
||||
}
|
||||
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
int fetch_stats()
|
||||
{
|
||||
return SocketStats::mbed_stats_socket_get_each(&udp_stats[0], MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Test setup
|
||||
utest::v1::status_t greentea_setup(const size_t number_of_cases)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,11 @@ NetworkInterface *get_interface();
|
|||
void drop_bad_packets(UDPSocket &sock, int orig_timeout);
|
||||
void fill_tx_buffer_ascii(char *buff, size_t len);
|
||||
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
extern mbed_stats_socket_t udp_stats[MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT];
|
||||
int fetch_stats(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Test cases
|
||||
*/
|
||||
|
|
|
@ -121,6 +121,14 @@ void udpsocket_echotest_nonblock_receiver(void *receive_bytes)
|
|||
|
||||
void UDPSOCKET_ECHOTEST_NONBLOCK()
|
||||
{
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
int j = 0;
|
||||
int count = fetch_stats();
|
||||
for (; j < count; j++) {
|
||||
TEST_ASSERT_EQUAL(SOCK_CLOSED, udp_stats[j].state);
|
||||
}
|
||||
#endif
|
||||
|
||||
SocketAddress udp_addr;
|
||||
get_interface()->gethostbyname(MBED_CONF_APP_ECHO_SERVER_ADDR, &udp_addr);
|
||||
udp_addr.set_port(MBED_CONF_APP_ECHO_SERVER_PORT);
|
||||
|
@ -174,11 +182,27 @@ void UDPSOCKET_ECHOTEST_NONBLOCK()
|
|||
}
|
||||
}
|
||||
free(stack_mem);
|
||||
|
||||
// Packet loss up to 30% tolerated
|
||||
if (packets_sent > 0) {
|
||||
double loss_ratio = 1 - ((double)packets_recv / (double)packets_sent);
|
||||
printf("Packets sent: %d, packets received %d, loss ratio %.2lf\r\n", packets_sent, packets_recv, loss_ratio);
|
||||
TEST_ASSERT_DOUBLE_WITHIN(TOLERATED_LOSS_RATIO, EXPECTED_LOSS_RATIO, loss_ratio);
|
||||
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
count = fetch_stats();
|
||||
for (j = 0; j < count; j++) {
|
||||
if ((NSAPI_UDP == udp_stats[j].proto) && (SOCK_OPEN == udp_stats[j].state)) {
|
||||
TEST_ASSERT(udp_stats[j].sent_bytes != 0);
|
||||
TEST_ASSERT(udp_stats[j].recv_bytes != 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
loss_ratio = 1 - ((double)udp_stats[j].recv_bytes / (double)udp_stats[j].sent_bytes);
|
||||
printf("Bytes sent: %d, bytes received %d, loss ratio %.2lf\r\n", udp_stats[j].sent_bytes, udp_stats[j].recv_bytes, loss_ratio);
|
||||
TEST_ASSERT_DOUBLE_WITHIN(TOLERATED_LOSS_RATIO, EXPECTED_LOSS_RATIO, loss_ratio);
|
||||
|
||||
#endif
|
||||
}
|
||||
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());
|
||||
}
|
||||
|
|
|
@ -26,6 +26,12 @@ using namespace utest::v1;
|
|||
|
||||
void UDPSOCKET_OPEN_CLOSE_REPEAT()
|
||||
{
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
int count = fetch_stats();
|
||||
for (int j = 0; j < count; j++) {
|
||||
TEST_ASSERT_EQUAL(SOCK_CLOSED, udp_stats[j].state);
|
||||
}
|
||||
#endif
|
||||
UDPSocket *sock = new UDPSocket;
|
||||
if (!sock) {
|
||||
TEST_FAIL();
|
||||
|
@ -36,4 +42,10 @@ void UDPSOCKET_OPEN_CLOSE_REPEAT()
|
|||
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock->close());
|
||||
}
|
||||
delete sock;
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
count = fetch_stats();
|
||||
for (int j = 0; j < count; j++) {
|
||||
TEST_ASSERT_EQUAL(SOCK_CLOSED, udp_stats[j].state);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "UDPSocket.h"
|
||||
#include "unity/unity.h"
|
||||
#include "utest.h"
|
||||
#include "SocketStats.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
|
||||
|
@ -69,7 +70,16 @@ void UDPSOCKET_OPEN_LIMIT()
|
|||
if (!socket_list_head) {
|
||||
break;
|
||||
}
|
||||
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
int count = fetch_stats();
|
||||
int open_count = 0;
|
||||
for (int j = 0; j < count; j++) {
|
||||
if ((udp_stats[j].state == SOCK_OPEN) && (udp_stats[j].proto == NSAPI_UDP)) {
|
||||
open_count++;
|
||||
}
|
||||
}
|
||||
TEST_ASSERT(open_count >= 3);
|
||||
#endif
|
||||
UDPSocketItem *tmp;
|
||||
for (UDPSocketItem *it = socket_list_head; it;) {
|
||||
++open_sockets[i];
|
||||
|
|
|
@ -31,6 +31,7 @@ set(unittest-test-sources
|
|||
stubs/stoip4_stub.c
|
||||
stubs/ip4tos_stub.c
|
||||
stubs/Kernel_stub.cpp
|
||||
stubs/SocketStats_Stub.cpp
|
||||
)
|
||||
|
||||
set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/DTLSSocket/dtls_test_config.h\"")
|
||||
|
|
|
@ -30,6 +30,7 @@ set(unittest-test-sources
|
|||
stubs/stoip4_stub.c
|
||||
stubs/ip4tos_stub.c
|
||||
stubs/Kernel_stub.cpp
|
||||
stubs/SocketStats_Stub.cpp
|
||||
)
|
||||
|
||||
set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/DTLSSocketWrapper/dtls_test_config.h\"")
|
||||
|
|
|
@ -33,4 +33,5 @@ set(unittest-test-sources
|
|||
stubs/stoip4_stub.c
|
||||
stubs/ip4tos_stub.c
|
||||
stubs/NetworkStack_stub.cpp
|
||||
stubs/SocketStats_Stub.cpp
|
||||
)
|
||||
|
|
|
@ -25,4 +25,5 @@ set(unittest-test-sources
|
|||
stubs/EventFlags_stub.cpp
|
||||
stubs/stoip4_stub.c
|
||||
stubs/ip4tos_stub.c
|
||||
stubs/SocketStats_Stub.cpp
|
||||
)
|
||||
|
|
|
@ -25,4 +25,5 @@ set(unittest-test-sources
|
|||
stubs/nsapi_dns_stub.cpp
|
||||
stubs/EventFlags_stub.cpp
|
||||
features/netsocket/NetworkInterface/test_NetworkInterface.cpp
|
||||
stubs/SocketStats_Stub.cpp
|
||||
)
|
||||
|
|
|
@ -28,4 +28,5 @@ set(unittest-test-sources
|
|||
stubs/nsapi_dns_stub.cpp
|
||||
stubs/EventFlags_stub.cpp
|
||||
features/netsocket/NetworkStack/test_NetworkStack.cpp
|
||||
stubs/SocketStats_Stub.cpp
|
||||
)
|
||||
|
|
|
@ -28,4 +28,5 @@ set(unittest-test-sources
|
|||
stubs/nsapi_dns_stub.cpp
|
||||
stubs/EventFlags_stub.cpp
|
||||
features/netsocket/TCPServer/test_TCPServer.cpp
|
||||
stubs/SocketStats_Stub.cpp
|
||||
)
|
||||
|
|
|
@ -26,4 +26,5 @@ set(unittest-test-sources
|
|||
stubs/EventFlags_stub.cpp
|
||||
stubs/stoip4_stub.c
|
||||
stubs/ip4tos_stub.c
|
||||
stubs/SocketStats_Stub.cpp
|
||||
)
|
||||
|
|
|
@ -29,6 +29,7 @@ set(unittest-test-sources
|
|||
stubs/EventFlags_stub.cpp
|
||||
stubs/stoip4_stub.c
|
||||
stubs/ip4tos_stub.c
|
||||
stubs/SocketStats_Stub.cpp
|
||||
)
|
||||
|
||||
set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/TLSSocket/tls_test_config.h\"")
|
||||
|
|
|
@ -28,6 +28,7 @@ set(unittest-test-sources
|
|||
stubs/EventFlags_stub.cpp
|
||||
stubs/stoip4_stub.c
|
||||
stubs/ip4tos_stub.c
|
||||
stubs/SocketStats_Stub.cpp
|
||||
)
|
||||
|
||||
set(MBEDTLS_USER_CONFIG_FILE_PATH "\"../UNITTESTS/features/netsocket/TLSSocketWrapper/tls_test_config.h\"")
|
||||
|
|
|
@ -26,4 +26,5 @@ set(unittest-test-sources
|
|||
stubs/nsapi_dns_stub.cpp
|
||||
stubs/stoip4_stub.c
|
||||
stubs/ip4tos_stub.c
|
||||
stubs/SocketStats_Stub.cpp
|
||||
)
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* 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 "SocketStats.h"
|
||||
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
int SocketStats::get_entry_position(const Socket *const reference_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t SocketStats::mbed_stats_socket_get_each(mbed_stats_socket_t *stats, size_t count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SocketStats::SocketStats()
|
||||
{
|
||||
}
|
||||
|
||||
void SocketStats::stats_new_socket_entry(const Socket *const reference_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void SocketStats::stats_update_socket_state(const Socket *const reference_id, socket_state state)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void SocketStats::stats_update_peer(const Socket *const reference_id, const SocketAddress &peer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void SocketStats::stats_update_proto(const Socket *const reference_id, nsapi_protocol_t proto)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void SocketStats::stats_update_sent_bytes(const Socket *const reference_id, size_t sent_bytes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void SocketStats::stats_update_recv_bytes(const Socket *const reference_id, size_t recv_bytes)
|
||||
{
|
||||
return;
|
||||
}
|
|
@ -450,7 +450,7 @@ private:
|
|||
* @param func Callback to be called
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
nsapi_error_t call_in(int delay, mbed::Callback<void()> func);
|
||||
virtual nsapi_error_t call_in(int delay, mbed::Callback<void()> func);
|
||||
|
||||
struct mbed_lwip_socket {
|
||||
bool in_use;
|
||||
|
|
|
@ -24,6 +24,7 @@ InternetSocket::InternetSocket()
|
|||
_readers(0), _writers(0), _pending(0),
|
||||
_factory_allocated(false)
|
||||
{
|
||||
_socket_stats.stats_new_socket_entry(this);
|
||||
}
|
||||
|
||||
InternetSocket::~InternetSocket()
|
||||
|
@ -48,6 +49,7 @@ nsapi_error_t InternetSocket::open(NetworkStack *stack)
|
|||
return err;
|
||||
}
|
||||
|
||||
_socket_stats.stats_update_socket_state(this, SOCK_OPEN);
|
||||
_socket = socket;
|
||||
_event = callback(this, &InternetSocket::event);
|
||||
_stack->socket_attach(_socket, Callback<void()>::thunk, &_event);
|
||||
|
@ -72,7 +74,7 @@ nsapi_error_t InternetSocket::close()
|
|||
_socket = 0;
|
||||
ret = _stack->socket_close(socket);
|
||||
_stack = 0; // Invalidate the stack pointer - otherwise open() fails.
|
||||
|
||||
_socket_stats.stats_update_socket_state(this, SOCK_CLOSED);
|
||||
// Wakeup anything in a blocking operation
|
||||
// on this socket
|
||||
event();
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "rtos/EventFlags.h"
|
||||
#include "Callback.h"
|
||||
#include "mbed_toolchain.h"
|
||||
#include "SocketStats.h"
|
||||
|
||||
/** Socket implementation that uses IP network stack.
|
||||
* Not to be directly used by applications. Cannot be directly instantiated.
|
||||
|
@ -176,6 +177,7 @@ protected:
|
|||
static const int FINISHED_FLAG = 0x3u;
|
||||
|
||||
friend class DTLSSocket; // Allow DTLSSocket::connect() to do name resolution on the _stack
|
||||
SocketStats _socket_stats;
|
||||
|
||||
#endif //!defined(DOXYGEN_ONLY)
|
||||
};
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* 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 "SocketStats.h"
|
||||
#include "platform/mbed_error.h"
|
||||
#include "platform/mbed_assert.h"
|
||||
#ifdef MBED_CONF_RTOS_PRESENT
|
||||
#include "rtos/Kernel.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
SingletonPtr<PlatformMutex> SocketStats::_mutex;
|
||||
mbed_stats_socket_t SocketStats::_stats[MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT];
|
||||
uint32_t SocketStats::_size = 0;
|
||||
|
||||
int SocketStats::get_entry_position(const Socket *const reference_id)
|
||||
{
|
||||
for (uint32_t j = 0; j < _size; j++) {
|
||||
if (_stats[j].reference_id == reference_id) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t SocketStats::mbed_stats_socket_get_each(mbed_stats_socket_t *stats, size_t count)
|
||||
{
|
||||
MBED_ASSERT(stats != NULL);
|
||||
size_t i = 0;
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
memset(stats, 0, count * sizeof(mbed_stats_socket_t));
|
||||
_mutex->lock();
|
||||
for (uint32_t j = 0; j < count; j++) {
|
||||
if (_stats[j].reference_id) {
|
||||
memcpy(&stats[i], &_stats[j], sizeof(mbed_stats_socket_t));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
_mutex->unlock();
|
||||
#endif
|
||||
return i;
|
||||
}
|
||||
|
||||
SocketStats::SocketStats()
|
||||
{
|
||||
}
|
||||
|
||||
void SocketStats::stats_new_socket_entry(const Socket *const reference_id)
|
||||
{
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
_mutex->lock();
|
||||
if (get_entry_position(reference_id) >= 0) {
|
||||
// Duplicate entry
|
||||
MBED_WARNING1(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STATS, MBED_ERROR_CODE_INVALID_INDEX), "Duplicate socket Reference ID ", reference_id);
|
||||
} else if (_size < MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT) {
|
||||
// Add new entry
|
||||
_stats[_size].reference_id = (Socket *)reference_id;
|
||||
_size++;
|
||||
} else {
|
||||
int position = -1;
|
||||
uint64_t oldest_time = 0;
|
||||
// Determine which entry in the list shall be over-written
|
||||
for (uint32_t j = 0; j < MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT; j++) {
|
||||
if (SOCK_CLOSED == _stats[j].state) {
|
||||
if ((0 == oldest_time) || (oldest_time < _stats[j].last_change_tick)) {
|
||||
oldest_time = _stats[j].last_change_tick;
|
||||
position = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-1 == position) {
|
||||
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_NETWORK_STATS, MBED_ERROR_CODE_OUT_OF_RESOURCES), "List full with all open sockets");
|
||||
}
|
||||
memset(&_stats[position], 0, sizeof(mbed_stats_socket_t));
|
||||
_stats[position].reference_id = (Socket *)reference_id;
|
||||
}
|
||||
_mutex->unlock();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
void SocketStats::stats_update_socket_state(const Socket *const reference_id, socket_state state)
|
||||
{
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
_mutex->lock();
|
||||
int position = get_entry_position(reference_id);
|
||||
if (position >= 0) {
|
||||
_stats[position].state = state;
|
||||
#ifdef MBED_CONF_RTOS_PRESENT
|
||||
_stats[position].last_change_tick = rtos::Kernel::get_ms_count();
|
||||
#endif
|
||||
}
|
||||
_mutex->unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
void SocketStats::stats_update_peer(const Socket *const reference_id, const SocketAddress &peer)
|
||||
{
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
_mutex->lock();
|
||||
int position = get_entry_position(reference_id);
|
||||
if ((position >= 0) && (!_stats[position].peer)) {
|
||||
_stats[position].peer = peer;
|
||||
}
|
||||
_mutex->unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
void SocketStats::stats_update_proto(const Socket *const reference_id, nsapi_protocol_t proto)
|
||||
{
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
_mutex->lock();
|
||||
int position = get_entry_position(reference_id);
|
||||
if (position >= 0) {
|
||||
_stats[position].proto = proto;
|
||||
}
|
||||
_mutex->unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
void SocketStats::stats_update_sent_bytes(const Socket *const reference_id, size_t sent_bytes)
|
||||
{
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
_mutex->lock();
|
||||
int position = get_entry_position(reference_id);
|
||||
if ((position >= 0) && ((int32_t)sent_bytes > 0)) {
|
||||
_stats[position].sent_bytes += sent_bytes;
|
||||
}
|
||||
_mutex->unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
void SocketStats::stats_update_recv_bytes(const Socket *const reference_id, size_t recv_bytes)
|
||||
{
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
_mutex->lock();
|
||||
int position = get_entry_position(reference_id);
|
||||
if ((position >= 0) && ((int32_t)recv_bytes > 0)) {
|
||||
_stats[position].recv_bytes += recv_bytes;
|
||||
}
|
||||
_mutex->unlock();
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2018 ARM Limited
|
||||
*
|
||||
* 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 SOCKET_STATS_H
|
||||
#define SOCKET_STATS_H
|
||||
|
||||
#include "platform/SingletonPtr.h"
|
||||
#include "platform/PlatformMutex.h"
|
||||
#include "netsocket/Socket.h"
|
||||
#include "SocketAddress.h"
|
||||
#include "hal/ticker_api.h"
|
||||
|
||||
#ifndef MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT
|
||||
#define MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT 10
|
||||
#endif
|
||||
|
||||
/** Enum of socket states
|
||||
*
|
||||
* Can be used to specify current state of socket - open, closed, connected or listen.
|
||||
*
|
||||
* @enum socket_state
|
||||
*/
|
||||
typedef enum {
|
||||
SOCK_CLOSED, /**< Socket is closed and does not exist anymore in the system */
|
||||
SOCK_OPEN, /**< Socket is open but not associated to any peer address */
|
||||
SOCK_CONNECTED, /**< Socket is associated to peer address, either by connect() or sendto()/recvfrom() calls */
|
||||
SOCK_LISTEN, /**< Socket is listening for incoming connections */
|
||||
} socket_state;
|
||||
|
||||
/** Structure to parse socket statistics
|
||||
*/
|
||||
typedef struct {
|
||||
Socket *reference_id; /**< Used for identifying socket */
|
||||
SocketAddress peer; /**< Last associated peername of this socket (Destination address) */
|
||||
socket_state state; /**< State of this socket */
|
||||
nsapi_protocol_t proto; /**< Specifies a protocol used with socket */
|
||||
size_t sent_bytes; /**< Data sent through this socket */
|
||||
size_t recv_bytes; /**< Data received through this socket */
|
||||
us_timestamp_t last_change_tick;/**< osKernelGetTick() when state last changed */
|
||||
} mbed_stats_socket_t;
|
||||
|
||||
/** SocketStats class
|
||||
*
|
||||
* Class to get the network socket statistics
|
||||
*/
|
||||
class SocketStats {
|
||||
public:
|
||||
|
||||
#if !defined(DOXYGEN_ONLY)
|
||||
/** Create an socket statictics object
|
||||
*
|
||||
* Application users must not create class objects.
|
||||
* Entities reporting network statistics create the class object.
|
||||
* Application can fetch network statistics using static `mbed_stats_socket_get_each` API
|
||||
* without creating an object.
|
||||
*/
|
||||
SocketStats();
|
||||
virtual ~SocketStats()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* Fill the passed array of structures with the socket statistics for each created socket.
|
||||
*
|
||||
* @param stats A pointer to an array of mbed_stats_socket_t structures to fill
|
||||
* @param count The number of mbed_stats_socket_t structures in the provided array
|
||||
* @return The number of mbed_stats_socket_t structures that have been filled.
|
||||
* If the number of sockets on the system is less than or equal to count,
|
||||
* it will equal the number of sockets created (active or closed).
|
||||
* If the number of sockets on the system is greater than count,
|
||||
* it will equal count.
|
||||
*/
|
||||
static size_t mbed_stats_socket_get_each(mbed_stats_socket_t *stats, size_t count);
|
||||
|
||||
#if !defined(DOXYGEN_ONLY)
|
||||
/** Add entry of newly created socket in statistics array.
|
||||
* API used by socket (TCP or UDP) layers only, not to be used by application.
|
||||
*
|
||||
* @param reference_id ID to identify socket in data array.
|
||||
*
|
||||
* @Note: The entry in the array is maintained even after the socket is closed.
|
||||
* The entry is overwritten for sockets that were closed first, in case
|
||||
* the socket creation count exceeds `MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT`.
|
||||
*
|
||||
*/
|
||||
void stats_new_socket_entry(const Socket *const reference_id);
|
||||
|
||||
/** Updates the state of the socket and records `tick_last_change`.
|
||||
* API used by socket (TCP or UDP) layers only, not to be used by application.
|
||||
*
|
||||
* @param reference_id ID to identify socket in data array.
|
||||
* @param state Parameter to update the current state of the socket.
|
||||
*
|
||||
*/
|
||||
void stats_update_socket_state(const Socket *const reference_id, socket_state state);
|
||||
|
||||
/** Update the peer information of the socket.
|
||||
* API used by socket (TCP or UDP) layers only, not to be used by application.
|
||||
*
|
||||
* @param reference_id ID to identify socket in data array.
|
||||
* @param peer Parameter to update destination peer information.
|
||||
*
|
||||
*/
|
||||
void stats_update_peer(const Socket *const reference_id, const SocketAddress &peer);
|
||||
|
||||
/** Update socket protocol.
|
||||
* API used by socket (TCP or UDP) layers only, not to be used by application.
|
||||
*
|
||||
* @param reference_id ID to identify socket in data array.
|
||||
* @param proto Parameter to update the protocol type of socket.
|
||||
*
|
||||
*/
|
||||
void stats_update_proto(const Socket *const reference_id, nsapi_protocol_t proto);
|
||||
|
||||
/** Update bytes sent on socket, which is cumulative count per socket.
|
||||
* API used by socket (TCP or UDP) layers only, not to be used by application.
|
||||
*
|
||||
* @param reference_id ID to identify socket in data array.
|
||||
* @param sent_bytes Parameter to append bytes sent over the socket.
|
||||
*
|
||||
*/
|
||||
void stats_update_sent_bytes(const Socket *const reference_id, size_t sent_bytes);
|
||||
|
||||
/** Update bytes received on socket, which is cumulative count per socket
|
||||
* API used by socket (TCP or UDP) layers only, not to be used by application.
|
||||
*
|
||||
* @param reference_id ID to identify socket in data array.
|
||||
* @param recv_bytes Parameter to append bytes the socket receives.
|
||||
*
|
||||
*/
|
||||
void stats_update_recv_bytes(const Socket *const reference_id, size_t recv_bytes);
|
||||
|
||||
#if MBED_CONF_NSAPI_SOCKET_STATS_ENABLE
|
||||
private:
|
||||
static mbed_stats_socket_t _stats[MBED_CONF_NSAPI_SOCKET_STATS_MAX_COUNT];
|
||||
static SingletonPtr<PlatformMutex> _mutex;
|
||||
static uint32_t _size;
|
||||
|
||||
/** Internal function to scan the array and get the position of the element in the list.
|
||||
*
|
||||
* @param reference_id ID to identify the socket in the data array.
|
||||
*
|
||||
*/
|
||||
int get_entry_position(const Socket *const reference_id);
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
|
@ -20,6 +20,7 @@ using mbed::Callback;
|
|||
|
||||
TCPServer::TCPServer()
|
||||
{
|
||||
_socket_stats.stats_update_proto(this, NSAPI_TCP);
|
||||
}
|
||||
|
||||
TCPServer::~TCPServer()
|
||||
|
@ -52,7 +53,8 @@ nsapi_error_t TCPServer::accept(TCPSocket *connection, SocketAddress *address)
|
|||
connection->_socket = socket;
|
||||
connection->_event = Callback<void()>(connection, &TCPSocket::event);
|
||||
_stack->socket_attach(socket, &Callback<void()>::thunk, &connection->_event);
|
||||
|
||||
_socket_stats.stats_update_peer(connection, *address);
|
||||
_socket_stats.stats_update_socket_state(connection, SOCK_CONNECTED);
|
||||
connection->_lock.unlock();
|
||||
break;
|
||||
} else if ((_timeout == 0) || (ret != NSAPI_ERROR_WOULD_BLOCK)) {
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
TCPSocket::TCPSocket()
|
||||
{
|
||||
_socket_stats.stats_update_proto(this, NSAPI_TCP);
|
||||
}
|
||||
|
||||
TCPSocket::TCPSocket(TCPSocket *parent, nsapi_socket_t socket, SocketAddress address)
|
||||
|
@ -28,7 +29,7 @@ TCPSocket::TCPSocket(TCPSocket *parent, nsapi_socket_t socket, SocketAddress add
|
|||
_stack = parent->_stack;
|
||||
_factory_allocated = true;
|
||||
_remote_peer = address;
|
||||
|
||||
_socket_stats.stats_new_socket_entry(this);
|
||||
_event = mbed::Callback<void()>(this, &TCPSocket::event);
|
||||
_stack->socket_attach(socket, &mbed::Callback<void()>::thunk, &_event);
|
||||
}
|
||||
|
@ -64,6 +65,7 @@ nsapi_error_t TCPSocket::connect(const SocketAddress &address)
|
|||
_pending = 0;
|
||||
ret = _stack->socket_connect(_socket, address);
|
||||
if ((_timeout == 0) || !(ret == NSAPI_ERROR_IN_PROGRESS || ret == NSAPI_ERROR_ALREADY)) {
|
||||
_socket_stats.stats_update_socket_state(this, SOCK_CONNECTED);
|
||||
break;
|
||||
} else {
|
||||
blocking_connect_in_progress = true;
|
||||
|
@ -89,11 +91,13 @@ nsapi_error_t TCPSocket::connect(const SocketAddress &address)
|
|||
|
||||
/* Non-blocking connect gives "EISCONN" once done - convert to OK for blocking mode if we became connected during this call */
|
||||
if (ret == NSAPI_ERROR_IS_CONNECTED && blocking_connect_in_progress) {
|
||||
_socket_stats.stats_update_socket_state(this, SOCK_CONNECTED);
|
||||
ret = NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
if (ret == NSAPI_ERROR_OK || ret == NSAPI_ERROR_IN_PROGRESS) {
|
||||
_remote_peer = address;
|
||||
_socket_stats.stats_update_peer(this, _remote_peer);
|
||||
}
|
||||
|
||||
_lock.unlock();
|
||||
|
@ -178,6 +182,7 @@ nsapi_size_or_error_t TCPSocket::send(const void *data, nsapi_size_t size)
|
|||
} else if (written == 0) {
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
} else {
|
||||
_socket_stats.stats_update_sent_bytes(this, written);
|
||||
return written;
|
||||
}
|
||||
}
|
||||
|
@ -208,6 +213,7 @@ nsapi_size_or_error_t TCPSocket::recv(void *data, nsapi_size_t size)
|
|||
_pending = 0;
|
||||
ret = _stack->socket_recv(_socket, data, size);
|
||||
if ((_timeout == 0) || (ret != NSAPI_ERROR_WOULD_BLOCK)) {
|
||||
_socket_stats.stats_update_recv_bytes(this, ret);
|
||||
break;
|
||||
} else {
|
||||
uint32_t flag;
|
||||
|
@ -252,6 +258,9 @@ nsapi_error_t TCPSocket::listen(int backlog)
|
|||
ret = NSAPI_ERROR_NO_SOCKET;
|
||||
} else {
|
||||
ret = _stack->socket_listen(_socket, backlog);
|
||||
if (NSAPI_ERROR_OK == ret) {
|
||||
_socket_stats.stats_update_socket_state(this, SOCK_LISTEN);
|
||||
}
|
||||
}
|
||||
|
||||
_lock.unlock();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
UDPSocket::UDPSocket()
|
||||
{
|
||||
_socket_stats.stats_update_proto(this, NSAPI_UDP);
|
||||
}
|
||||
|
||||
UDPSocket::~UDPSocket()
|
||||
|
@ -34,6 +35,8 @@ nsapi_protocol_t UDPSocket::get_proto()
|
|||
nsapi_error_t UDPSocket::connect(const SocketAddress &address)
|
||||
{
|
||||
_remote_peer = address;
|
||||
_socket_stats.stats_update_peer(this, _remote_peer);
|
||||
_socket_stats.stats_update_socket_state(this, SOCK_CONNECTED);
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
|
@ -57,7 +60,10 @@ nsapi_size_or_error_t UDPSocket::sendto(const SocketAddress &address, const void
|
|||
nsapi_size_or_error_t ret;
|
||||
|
||||
_writers++;
|
||||
|
||||
if (_socket) {
|
||||
_socket_stats.stats_update_socket_state(this, SOCK_OPEN);
|
||||
_socket_stats.stats_update_peer(this, address);
|
||||
}
|
||||
while (true) {
|
||||
if (!_socket) {
|
||||
ret = NSAPI_ERROR_NO_SOCKET;
|
||||
|
@ -67,6 +73,7 @@ nsapi_size_or_error_t UDPSocket::sendto(const SocketAddress &address, const void
|
|||
_pending = 0;
|
||||
nsapi_size_or_error_t sent = _stack->socket_sendto(_socket, address, data, size);
|
||||
if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != sent)) {
|
||||
_socket_stats.stats_update_sent_bytes(this, sent);
|
||||
ret = sent;
|
||||
break;
|
||||
} else {
|
||||
|
@ -114,6 +121,9 @@ nsapi_size_or_error_t UDPSocket::recvfrom(SocketAddress *address, void *buffer,
|
|||
|
||||
_readers++;
|
||||
|
||||
if (_socket) {
|
||||
_socket_stats.stats_update_socket_state(this, SOCK_OPEN);
|
||||
}
|
||||
while (true) {
|
||||
if (!_socket) {
|
||||
ret = NSAPI_ERROR_NO_SOCKET;
|
||||
|
@ -128,9 +138,11 @@ nsapi_size_or_error_t UDPSocket::recvfrom(SocketAddress *address, void *buffer,
|
|||
continue;
|
||||
}
|
||||
|
||||
_socket_stats.stats_update_peer(this, _remote_peer);
|
||||
// Non-blocking sockets always return. Blocking only returns when success or errors other than WOULD_BLOCK
|
||||
if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != recv)) {
|
||||
ret = recv;
|
||||
_socket_stats.stats_update_recv_bytes(this, recv);
|
||||
break;
|
||||
} else {
|
||||
uint32_t flag;
|
||||
|
|
|
@ -30,6 +30,14 @@
|
|||
"dns-cache-size": {
|
||||
"help": "Number of cached host name resolutions",
|
||||
"value": 3
|
||||
},
|
||||
"socket-stats-enable": {
|
||||
"help": "Enable network socket statistics",
|
||||
"value": false
|
||||
},
|
||||
"socket-stats-max-count": {
|
||||
"help": "Maximum number of socket statistics cached",
|
||||
"value": 10
|
||||
}
|
||||
},
|
||||
"target_overrides": {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#ifndef SINGLETONPTR_H
|
||||
#define SINGLETONPTR_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <new>
|
||||
#include "platform/mbed_assert.h"
|
||||
|
|
|
@ -254,6 +254,7 @@ typedef enum _mbed_error_type_t {
|
|||
MBED_MODULE_DRIVER_USB 21 USB Driver
|
||||
MBED_MODULE_TARGET_SDK 22 SDK
|
||||
MBED_MODULE_BLE 23 BLE
|
||||
MBED_MODULE_NETWORK_STATS 24 Network Statistics
|
||||
|
||||
MBED_MODULE_UNKNOWN 255 Unknown module
|
||||
\endverbatim
|
||||
|
@ -284,6 +285,7 @@ typedef enum _mbed_module_type {
|
|||
MBED_MODULE_DRIVER_USB,
|
||||
MBED_MODULE_TARGET_SDK,
|
||||
MBED_MODULE_BLE,
|
||||
MBED_MODULE_NETWORK_STATS,
|
||||
/* Add More entities here as required */
|
||||
|
||||
MBED_MODULE_UNKNOWN = 255,
|
||||
|
|
|
@ -1,33 +1,41 @@
|
|||
{
|
||||
"UBLOX_EVK_ODIN_W2": {
|
||||
"nsapi.socket-stats-enable": true,
|
||||
"default_test_configuration": "NONE",
|
||||
"test_configurations": ["HEAPBLOCKDEVICE_AND_WIFI", "HEAPBLOCKDEVICE_AND_ETHERNET"]
|
||||
},
|
||||
"REALTEK_RTL8195AM": {
|
||||
"nsapi.socket-stats-enable": true,
|
||||
"default_test_configuration": "NONE",
|
||||
"test_configurations": ["HEAPBLOCKDEVICE_AND_WIFI"]
|
||||
},
|
||||
"K64F": {
|
||||
"nsapi.socket-stats-enable": true,
|
||||
"default_test_configuration": "HEAPBLOCKDEVICE_AND_ETHERNET",
|
||||
"test_configurations": ["HEAPBLOCKDEVICE_AND_ETHERNET", "NANOSTACK_MAC_TESTER", "ESP8266_WIFI", "ETHERNET"]
|
||||
},
|
||||
"NUCLEO_F429ZI": {
|
||||
"nsapi.socket-stats-enable": true,
|
||||
"default_test_configuration": "HEAPBLOCKDEVICE_AND_ETHERNET",
|
||||
"test_configurations": ["HEAPBLOCKDEVICE_AND_ETHERNET", "NANOSTACK_MAC_TESTER"]
|
||||
},
|
||||
"DISCO_L475VG_IOT01A": {
|
||||
"nsapi.socket-stats-enable": true,
|
||||
"default_test_configuration": "NONE",
|
||||
"test_configurations": ["ISM43362_WIFI"]
|
||||
},
|
||||
"DISCO_F413ZH": {
|
||||
"nsapi.socket-stats-enable": true,
|
||||
"default_test_configuration": "NONE",
|
||||
"test_configurations": ["ISM43362_WIFI"]
|
||||
},
|
||||
"MTB_UBLOX_ODIN_W2": {
|
||||
"nsapi.socket-stats-enable": true,
|
||||
"default_test_configuration": "NONE",
|
||||
"test_configurations": ["HEAPBLOCKDEVICE_AND_WIFI"]
|
||||
},
|
||||
"MTB_ADV_WISE_1530": {
|
||||
"nsapi.socket-stats-enable": true,
|
||||
"default_test_configuration": "NONE",
|
||||
"test_configurations": ["HEAPBLOCKDEVICE_AND_WIFI"]
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue