From d17f6ab319024f8a57abdb85779266ad3557c5fe Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Thu, 23 Jan 2025 00:06:33 -0800 Subject: [PATCH] Improvements to the EMAC test --- .../TESTS/network/emac/emac_test_memory.cpp | 26 ++---- .../emac/emac_test_multicast_filter.cpp | 64 ++++++++++---- .../network/emac/emac_test_unicast_long.cpp | 2 +- .../tests/TESTS/network/emac/main.cpp | 2 +- .../TESTS/network/emac/template_mbed_app.txt | 24 ------ .../emac/template_mbed_app_echo_server.txt | 24 ------ .../tests/emac_test_utils/emac_ctp.cpp | 85 +++++++++---------- .../tests/emac_test_utils/emac_ctp.h | 72 ++++++++++++++-- .../tests/emac_test_utils/emac_membuf.cpp | 2 +- .../tests/emac_test_utils/emac_membuf.h | 11 ++- .../tests/emac_test_utils/emac_util.cpp | 83 +++++++++--------- .../tests/emac_test_utils/emac_util.h | 1 + 12 files changed, 222 insertions(+), 174 deletions(-) delete mode 100644 connectivity/netsocket/tests/TESTS/network/emac/template_mbed_app.txt delete mode 100644 connectivity/netsocket/tests/TESTS/network/emac/template_mbed_app_echo_server.txt diff --git a/connectivity/netsocket/tests/TESTS/network/emac/emac_test_memory.cpp b/connectivity/netsocket/tests/TESTS/network/emac/emac_test_memory.cpp index a854d857176..bd09b28877c 100644 --- a/connectivity/netsocket/tests/TESTS/network/emac/emac_test_memory.cpp +++ b/connectivity/netsocket/tests/TESTS/network/emac/emac_test_memory.cpp @@ -30,7 +30,7 @@ using namespace utest::v1; void test_emac_memory_cb(int opt) { static bool send_request = true; - static bool memory = true; + static bool echo_should_work = true; static int no_response_cnt = 0; static int retries = 0; static int msg_len = 0; @@ -46,60 +46,52 @@ void test_emac_memory_cb(int opt) printf("STEP 0: memory available\r\n\r\n"); emac_if_set_output_memory(true); emac_if_set_input_memory(true); - memory = true; + echo_should_work = true; break; case 1: printf("STEP 1: no input memory buffer memory available\r\n\r\n"); emac_if_set_output_memory(true); emac_if_set_input_memory(false); - memory = false; + echo_should_work = false; break; case 2: printf("STEP 2: memory available\r\n\r\n"); emac_if_set_output_memory(true); emac_if_set_input_memory(true); - memory = true; + echo_should_work = true; break; case 3: printf("STEP 3: no output memory buffer memory available\r\n\r\n"); emac_if_set_output_memory(false); emac_if_set_input_memory(true); - memory = false; + echo_should_work = false; break; case 4: printf("STEP 4: memory available\r\n\r\n"); emac_if_set_output_memory(true); emac_if_set_input_memory(true); - memory = true; + echo_should_work = true; break; case 5: printf("STEP 5: no output or input memory buffer memory available\r\n\r\n"); emac_if_set_output_memory(false); emac_if_set_input_memory(false); - memory = false; + echo_should_work = false; break; case 6: printf("STEP 6: memory available\r\n\r\n"); emac_if_set_output_memory(true); emac_if_set_input_memory(true); - memory = true; + echo_should_work = true; break; case 7: - printf("STEP 7: memory available, alloc from heap\r\n\r\n"); - emac_if_set_output_memory(true); - emac_if_set_input_memory(true); - options |= CTP_OPT_HEAP; - memory = true; - break; - - case 8: // Test ended END_TEST_LOOP; } @@ -116,7 +108,7 @@ void test_emac_memory_cb(int opt) if (++no_response_cnt > 5) { if (++retries > 3) { // If echo replies should be received fails the test case - if (memory) { + if (echo_should_work) { printf("too many retries\r\n\r\n"); SET_ERROR_FLAGS(TEST_FAILED); END_TEST_LOOP; diff --git a/connectivity/netsocket/tests/TESTS/network/emac/emac_test_multicast_filter.cpp b/connectivity/netsocket/tests/TESTS/network/emac/emac_test_multicast_filter.cpp index 78e569f5df5..f94e45b9a33 100644 --- a/connectivity/netsocket/tests/TESTS/network/emac/emac_test_multicast_filter.cpp +++ b/connectivity/netsocket/tests/TESTS/network/emac/emac_test_multicast_filter.cpp @@ -52,7 +52,7 @@ void test_emac_multicast_filter_cb(int opt) break; case 1: - printf("STEP 1: set ipv6 multicast filter, test if input message is filtered\r\n\r\n"); + printf("STEP 1: set ipv6 multicast filter to wrong address, test if input message is correctly filtered out (NOT received)\r\n\r\n"); { unsigned char filter[] = {0x33, 0x33, 0x1b, 0x1c, 0x1d, 0x1e}; char forw_addr[] = {0x33, 0x33, 0x11, 0x22, 0x33, 0x44}; @@ -63,7 +63,7 @@ void test_emac_multicast_filter_cb(int opt) break; case 2: - printf("STEP 2: set ipv6 multicast filter, test that input message is not filtered\r\n\r\n"); + printf("STEP 2: set ipv6 multicast filter, test that input message is passed by mcast filter\r\n\r\n"); { unsigned char filter[] = {0x33, 0x33, 0xaa, 0xbb, 0xcc, 0xdd}; emac_if_add_multicast_group(filter); @@ -73,7 +73,7 @@ void test_emac_multicast_filter_cb(int opt) break; case 3: - printf("STEP 3: set ipv4 multicast filter, test if input message is filtered\r\n\r\n"); + printf("STEP 3: set ipv4 multicast filter to wrong address, test if input message is correctly filtered out (NOT received)\r\n\r\n"); { unsigned char filter[] = {0x01, 0x00, 0x5e, 0xa1, 0xa2, 0xa3}; char forw_addr[] = {0x01, 0x00, 0x5e, 0x11, 0x22, 0x33}; @@ -84,7 +84,7 @@ void test_emac_multicast_filter_cb(int opt) break; case 4: - printf("STEP 4: set ipv4 multicast filter, test that input message is not filtered\r\n\r\n"); + printf("STEP 4: set ipv4 multicast filter, test that input message is passed by mcast filter\r\n\r\n"); { unsigned char filter[] = {0x01, 0x00, 0x5e, 0xa5, 0xa6, 0xa7}; emac_if_add_multicast_group(filter); @@ -93,8 +93,45 @@ void test_emac_multicast_filter_cb(int opt) receive = true; break; + case 5: - printf("STEP 5: set receive all multicast, verify that input messages are not filtered\r\n\r\n"); + printf("STEP 5: Remove last added mcast address, check that it no longer works\r\n\r\n"); + { + unsigned char filter[] = {0x01, 0x00, 0x5e, 0xa5, 0xa6, 0xa7}; + emac_if_remove_multicast_group(filter); + } + receive = false; + break; + + case 6: + printf("STEP 6: Check that second to last added mcast address still works\r\n\r\n"); + { + unsigned char filter[] = {0x01, 0x00, 0x5e, 0xa1, 0xa2, 0xa3}; + memcpy(forward_addr, filter, 6); + } + receive = true; + break; + + case 7: + printf("STEP 7: Check that first added mcast address still works\r\n\r\n"); + { + unsigned char filter[] = {0x33, 0x33, 0xaa, 0xbb, 0xcc, 0xdd}; + memcpy(forward_addr, filter, 6); + } + receive = true; + break; + + case 8: + printf("STEP 8: Remove first added mcast address, check that it does not work now\r\n\r\n"); + { + unsigned char filter[] = {0x33, 0x33, 0xaa, 0xbb, 0xcc, 0xdd}; + emac_if_remove_multicast_group(filter); + } + receive = false; + break; + + case 9: + printf("STEP 9: set receive all multicast, verify that all mcast addresses are passed now\r\n\r\n"); { emac_if_set_all_multicast(true); char forw_addr[] = {0x33, 0x33, 0x11, 0x12, 0x33, 0x44}; @@ -103,10 +140,11 @@ void test_emac_multicast_filter_cb(int opt) receive = true; break; - case 6: + case 10: // Test ended if (!multicasts_are_filtered) { printf("multicast filtering was not enabled!!!\r\n\r\n"); + SET_ERROR_FLAGS(TEST_FAILED); } END_TEST_LOOP; } @@ -119,7 +157,7 @@ void test_emac_multicast_filter_cb(int opt) no_response_cnt = 0; } else if (opt == TIMEOUT) { if (++no_response_cnt > 5) { - if (++retries > 3) { + if (++retries > 1) { if (receive) { printf("too many retries\r\n\r\n"); SET_ERROR_FLAGS(TEST_FAILED); @@ -137,7 +175,7 @@ void test_emac_multicast_filter_cb(int opt) // Echo response received if (opt == INPUT) { if (receive == false) { - printf("multicast was not filtered\r\n\r\n"); + printf("ERROR: multicast was received but should not have been!\r\n\r\n"); multicasts_are_filtered = false; } next_step = true; @@ -145,15 +183,7 @@ void test_emac_multicast_filter_cb(int opt) if (next_step) { RESET_OUTGOING_MSG_DATA; -#if (MBED_CONF_NETWORK_EMAC_NO_SUPPORT_FOR_IPV4_MULTICAST_FILTER == 1) - if (test_step == 2) { - test_step = 5; - } else { - test_step++; - } -#else test_step++; -#endif retries = 0; send_request = true; } @@ -165,7 +195,7 @@ void test_emac_multicast_filter() SET_TRACE_LEVEL(TRACE_SEND | TRACE_ETH_FRAMES | TRACE_SUCCESS | TRACE_FAILURE); if (ECHO_SERVER_ADDRESS_KNOWN) { - START_TEST_LOOP(test_emac_multicast_filter_cb, 1s); + START_TEST_LOOP(test_emac_multicast_filter_cb, 250ms); } PRINT_ERROR_FLAGS; diff --git a/connectivity/netsocket/tests/TESTS/network/emac/emac_test_unicast_long.cpp b/connectivity/netsocket/tests/TESTS/network/emac/emac_test_unicast_long.cpp index 29e1909ac66..4f97dd7e282 100644 --- a/connectivity/netsocket/tests/TESTS/network/emac/emac_test_unicast_long.cpp +++ b/connectivity/netsocket/tests/TESTS/network/emac/emac_test_unicast_long.cpp @@ -55,7 +55,7 @@ void test_emac_unicast_long_cb(int opt) // Echo response received if (opt == INPUT) { - if (++test_step > 50000) { + if (++test_step > 10000) { END_TEST_LOOP; } diff --git a/connectivity/netsocket/tests/TESTS/network/emac/main.cpp b/connectivity/netsocket/tests/TESTS/network/emac/main.cpp index 17121536ab7..b6bd7a5c3f2 100644 --- a/connectivity/netsocket/tests/TESTS/network/emac/main.cpp +++ b/connectivity/netsocket/tests/TESTS/network/emac/main.cpp @@ -46,7 +46,7 @@ utest::v1::status_t test_setup(const size_t number_of_cases) Case cases[] = { Case("EMAC initialize", test_emac_initialize), - Case("EMAC broadcast", test_emac_broadcast), + Case("EMAC broadcast", test_emac_broadcast), // note: this test case has the side effect of finding the CTP server MAC address and saving it Case("EMAC unicast", test_emac_unicast), Case("EMAC unicast frame length", test_emac_unicast_frame_len), Case("EMAC unicast burst", test_emac_unicast_burst), diff --git a/connectivity/netsocket/tests/TESTS/network/emac/template_mbed_app.txt b/connectivity/netsocket/tests/TESTS/network/emac/template_mbed_app.txt deleted file mode 100644 index c73ba291506..00000000000 --- a/connectivity/netsocket/tests/TESTS/network/emac/template_mbed_app.txt +++ /dev/null @@ -1,24 +0,0 @@ -{ - "config": { - "echo-server": { - "help": "Build test to be echo server", - "value": 0 - }, - "echo-server-trace": { - "help": "Trace incoming messages on echo server", - "value": 0 - }, - "wifi-scan": { - "help": "Scan and list access points", - "value": 0 - } - }, - "target_overrides": { - "*": { - "nsapi.default-wifi-ssid": "\"WIFI_SSID\"", - "nsapi.default-wifi-password": "\"WIFI_PASSWORD\"", - "nsapi.default-wifi-security": "WIFI_SECURITY", - "nsapi.default-stack": "TEST" - } - } -} diff --git a/connectivity/netsocket/tests/TESTS/network/emac/template_mbed_app_echo_server.txt b/connectivity/netsocket/tests/TESTS/network/emac/template_mbed_app_echo_server.txt deleted file mode 100644 index 2dc2faa8c92..00000000000 --- a/connectivity/netsocket/tests/TESTS/network/emac/template_mbed_app_echo_server.txt +++ /dev/null @@ -1,24 +0,0 @@ -{ - "config": { - "echo-server": { - "help": "Build test to be echo server", - "value": 1 - }, - "echo-server-trace": { - "help": "Trace incoming messages on echo server", - "value": 0 - }, - "wifi-scan": { - "help": "Scan and list access points", - "value": 0 - } - }, - "target_overrides": { - "*": { - "nsapi.default-wifi-ssid": "\"WIFI_SSID\"", - "nsapi.default-wifi-password": "\"WIFI_PASSWORD\"", - "nsapi.default-wifi-security": "WIFI_SECURITY", - "nsapi.default-stack": "TEST" - } - } -} diff --git a/connectivity/netsocket/tests/emac_test_utils/emac_ctp.cpp b/connectivity/netsocket/tests/emac_test_utils/emac_ctp.cpp index a1c2e0b7bb7..ea8f8988d26 100644 --- a/connectivity/netsocket/tests/emac_test_utils/emac_ctp.cpp +++ b/connectivity/netsocket/tests/emac_test_utils/emac_ctp.cpp @@ -31,62 +31,63 @@ static int receipt_number = 0; static int emac_if_ctp_header_build(unsigned char *eth_frame, const unsigned char *dest_addr, const unsigned char *origin_addr, const unsigned char *forward_addr) { - memcpy(ð_frame[0], dest_addr, 6); - memcpy(ð_frame[6], origin_addr, 6); + auto *ctpFrame = reinterpret_cast(eth_frame); - eth_frame[12] = 0x90; /* loop back */ - eth_frame[13] = 0x00; + memcpy(ctpFrame->destMAC, dest_addr, 6); + memcpy(ctpFrame->srcMAC, origin_addr, 6); + ctpFrame->etherType = __builtin_bswap16(CTP_ETHERTYPE); + ctpFrame->skipCount = 0; - eth_frame[14] = 0x00; /* skip count */ - eth_frame[15] = 0x00; + auto *forwardCommand = reinterpret_cast(ctpFrame->nextCommand); - eth_frame[16] = 0x02; /* function, forward */ - eth_frame[17] = 0x00; + forwardCommand->function = ctp_function::FORWARD; + memcpy(forwardCommand->forwardMAC, forward_addr, 6); - memcpy(ð_frame[18], forward_addr, 6); - - eth_frame[24] = 0x01; /* function, reply */ - eth_frame[25] = 0x00; + auto *replyCommand = reinterpret_cast(forwardCommand->nextCommand); + replyCommand->function = ctp_function::REPLY; receipt_number++; - - eth_frame[26] = receipt_number; /* receipt number */ - eth_frame[27] = receipt_number >> 8; + replyCommand->receiptNumber = receipt_number; return receipt_number; } -ctp_function emac_if_ctp_header_handle(unsigned char *eth_input_frame, unsigned char *eth_output_frame, unsigned char const *origin_addr, int *receipt_number) +ctp_function emac_if_ctp_header_handle(unsigned char const *eth_input_frame, unsigned char *eth_output_frame, unsigned char const *origin_addr, int *receipt_number) { - if (eth_input_frame[12] != 0x90 || eth_input_frame[13] != 0x00) { - return CTP_NONE; - } + auto *ctpFrame = reinterpret_cast(eth_input_frame); - int skip_count = eth_input_frame[15] << 8 | eth_input_frame[14]; - unsigned char *ethernet_ptr = ð_input_frame[16] + skip_count; + if (__builtin_bswap16(ctpFrame->etherType) != CTP_ETHERTYPE) { + return ctp_function::INVALID; + } - int function = ethernet_ptr[1] << 8 | ethernet_ptr[0]; - ethernet_ptr += 2; + unsigned char const *command_ptr = ctpFrame->nextCommand + ctpFrame->skipCount; + ctp_function command_function = *reinterpret_cast(command_ptr); // Forward - if (function == 0x0002) { + if (command_function == ctp_function::FORWARD) { + auto const *forwardCommandPtr = reinterpret_cast(command_ptr); + memcpy(eth_output_frame, eth_input_frame, ETH_FRAME_HEADER_LEN); - // Update skip count - skip_count += 8; - eth_output_frame[14] = skip_count; - eth_output_frame[15] = skip_count >> 8; + auto *ctpFrameOut = reinterpret_cast(eth_output_frame); + + // Update skip count so that the receiver will process the command after this one + ctpFrameOut->skipCount = ctpFrame->skipCount + sizeof(CTPForwardCommand); + // Set forward address to destination address - memcpy(ð_output_frame[0], ethernet_ptr, 6); + memcpy(ctpFrameOut->destMAC, forwardCommandPtr->forwardMAC, 6); // Copy own address to origin - memcpy(ð_output_frame[6], origin_addr, 6); - return CTP_FORWARD; - // reply - } else if (function == 0x0001) { - *receipt_number = ethernet_ptr[1] << 8 | ethernet_ptr[0]; - return CTP_REPLY; + memcpy(ctpFrameOut->srcMAC, origin_addr, 6); + + return ctp_function::FORWARD; + } + // Reply + else if (command_function == ctp_function::REPLY) { + auto const *replyCommandPtr = reinterpret_cast(command_ptr); + *receipt_number = replyCommandPtr->receiptNumber; + return ctp_function::REPLY; } - return CTP_NONE; + return ctp_function::INVALID; } void emac_if_ctp_msg_build(int eth_frame_len, const unsigned char *dest_addr, const unsigned char *origin_addr, const unsigned char *forward_addr, int options) @@ -96,7 +97,9 @@ void emac_if_ctp_msg_build(int eth_frame_len, const unsigned char *dest_addr, co } if (emac_if_get_trace_level() & TRACE_SEND) { - printf("message sent %x:%x:%x:%x:%x:%x\r\n\r\n", dest_addr[0], dest_addr[1], dest_addr[2], dest_addr[3], dest_addr[4], dest_addr[5]); + printf("message sent to %x:%x:%x:%x:%x:%x, fwd to %x:%x:%x:%x:%x:%x \r\n\r\n", + dest_addr[0], dest_addr[1], dest_addr[2], dest_addr[3], dest_addr[4], dest_addr[5], + forward_addr[0], forward_addr[1], forward_addr[2], forward_addr[3], forward_addr[4], forward_addr[5]); } int outgoing_msg_index = emac_if_add_outgoing_msg(eth_frame_len); @@ -113,13 +116,7 @@ void emac_if_ctp_msg_build(int eth_frame_len, const unsigned char *dest_addr, co align = 1; // Reserve memory overhead to align to odd address } - emac_mem_buf_t *buf; - if (options & CTP_OPT_HEAP) { - buf = EmacTestMemoryManager::get_instance().alloc_heap(eth_frame_len, align, alloc_opt); - } else { - // Default allocation is from pool - buf = EmacTestMemoryManager::get_instance().alloc_pool(eth_frame_len, align, alloc_opt); - } + emac_mem_buf_t *buf = EmacTestMemoryManager::get_instance().alloc_heap(eth_frame_len, align, alloc_opt); if (!buf) { SET_ERROR_FLAGS(NO_FREE_MEM_BUF); diff --git a/connectivity/netsocket/tests/emac_test_utils/emac_ctp.h b/connectivity/netsocket/tests/emac_test_utils/emac_ctp.h index eedd5c17fbe..5d00bf1c714 100644 --- a/connectivity/netsocket/tests/emac_test_utils/emac_ctp.h +++ b/connectivity/netsocket/tests/emac_test_utils/emac_ctp.h @@ -18,14 +18,63 @@ #ifndef EMAC_CTP_H #define EMAC_CTP_H -enum ctp_function { - CTP_NONE, - CTP_FORWARD, - CTP_REPLY +// CTP types -------------------------------------------------------------------- + +enum class ctp_function : uint16_t { + + INVALID = 0, + FORWARD = 0x02, + REPLY = 0x01 +}; + +const uint16_t CTP_ETHERTYPE = 0x9000; + +// CTP structures --------------------------------------------------------------- + +/** + * @brief Structure for a CTP reply message. + */ +struct __attribute__((packed)) CTPReplyCommand { + ctp_function function; ///< Function. Should be set to REPLY + uint16_t receiptNumber; ///< Receipt number. Set arbitrarily by the originating station + uint8_t payload[0]; ///< Payload. Arbitrary, set by the originating station. +}; + +/** + * @brief Structure for a CTP forward message. + */ +struct CTPForwardCommand; +struct __attribute__((packed)) CTPForwardCommand { + ctp_function function; ///< Function. Should be set to FORWARD. + uint8_t forwardMAC[6]; ///< MAC to forward this message to. + + /// Contained command, as a generic pointer + uint8_t nextCommand[0]; }; +/** + * @brief Packed structure representing an Ethernet frame with a CTP packet + */ +struct __attribute__((packed)) EthernetCTPFrame { + + // Ethernet II header + uint8_t destMAC[6]; + uint8_t srcMAC[6]; + uint16_t etherType; + + /// CTP skip count. + /// Indicates the offset where the receiving station should find its command in this packet. + /// This will be 0 when a packet is sent from the originating station. When a station processes + /// a CTP REPLY command, it updates this field in the reply packet to point to the next command. + uint16_t skipCount; + + /// Contained command, as a generic pointer + uint8_t nextCommand[0]; +}; + +// CTP functions --------------------------------------------------------------- + // Test memory manager options -#define CTP_OPT_HEAP 0x01 // Allocate link_out() frame from heap #define CTP_OPT_NON_ALIGNED 0x02 // Force memory buffers to be non-aligned /* Builds and sends CTP message. Forward to address is the address where echo server sends the reply. @@ -34,7 +83,18 @@ enum ctp_function { #define CTP_MSG_SEND(length, send_to_address, own_address, forward_to_address, mem_mngr_options) \ emac_if_ctp_msg_build(length, send_to_address, own_address, forward_to_address, mem_mngr_options) -ctp_function emac_if_ctp_header_handle(unsigned char *eth_input_frame, unsigned char *eth_output_frame, unsigned char const *origin_addr, int *receipt_number); +/** + * @brief Handle an incoming Ethernet frame. + * + * If the frame is a CTP forward command, a response frame is written to \c eth_output_frame and + * FORWARD is returned. + * + * If the frame is a CTP reply (meaning, this packet reached its final destination at this station), + * REPLY is returned and the receipt number is saved to \c receipt_number . + * + * Otherwise (invalid or non CTP packet), INVALID is returned. + */ +ctp_function emac_if_ctp_header_handle(unsigned char const *eth_input_frame, unsigned char *eth_output_frame, unsigned char const *origin_addr, int *receipt_number); void emac_if_ctp_msg_build(int eth_frame_len, const unsigned char *dest_addr, const unsigned char *origin_addr, const unsigned char *forward_addr, int options); void emac_if_ctp_reply_handle(int lenght, int invalid_data_index); diff --git a/connectivity/netsocket/tests/emac_test_utils/emac_membuf.cpp b/connectivity/netsocket/tests/emac_test_utils/emac_membuf.cpp index a3fc6d9acfe..5e9f3f579e7 100644 --- a/connectivity/netsocket/tests/emac_test_utils/emac_membuf.cpp +++ b/connectivity/netsocket/tests/emac_test_utils/emac_membuf.cpp @@ -27,7 +27,7 @@ #include "emac_membuf.h" #include "emac_util.h" -int emac_if_memory_buffer_read(void *buf, unsigned char *eth_frame) +int emac_if_memory_buffer_read_and_check(void *buf, unsigned char *eth_frame) { int eth_frame_index = 0; int invalid_data_index = 0; diff --git a/connectivity/netsocket/tests/emac_test_utils/emac_membuf.h b/connectivity/netsocket/tests/emac_test_utils/emac_membuf.h index 17510ae161b..2eb2cf6c0f6 100644 --- a/connectivity/netsocket/tests/emac_test_utils/emac_membuf.h +++ b/connectivity/netsocket/tests/emac_test_utils/emac_membuf.h @@ -18,7 +18,16 @@ #ifndef EMAC_MEMBUF_H #define EMAC_MEMBUF_H -int emac_if_memory_buffer_read(void *buf, unsigned char *eth_frame); +/** + * Read data from an Ethernet CTP frame received from the MAC. + * The first ETH_FRAME_HEADER_LEN bytes are copied into \c eth_frame. + * Bytes after there must be a fixed test pattern. + * + * @return Index (with 0 being the first byte of the Ethernet payload) of the first + * byte that did not match the test pattern, or 0 on success. + */ +int emac_if_memory_buffer_read_and_check(void *buf, unsigned char *eth_frame); + void emac_if_memory_buffer_write(void *buf, unsigned char *eth_frame, bool write_data); #endif /* EMAC_MEMBUF_H */ diff --git a/connectivity/netsocket/tests/emac_test_utils/emac_util.cpp b/connectivity/netsocket/tests/emac_test_utils/emac_util.cpp index 1ac6ff58eac..5dbcbd08c90 100644 --- a/connectivity/netsocket/tests/emac_test_utils/emac_util.cpp +++ b/connectivity/netsocket/tests/emac_test_utils/emac_util.cpp @@ -80,8 +80,8 @@ static Event link_input_event(&worker_loop_event_queue, link_input static unsigned char eth_mac_echo_server_addr[ECHO_SERVER_COUNT][ETH_MAC_ADDR_LEN]; static int etc_mac_echo_server_free_index = 0; -static bool output_memory = true; -static bool input_memory = true; +static bool allow_output_memory_allocs = true; +static bool allow_input_memory_allocs = true; static void (*current_test_step_cb_fnc)(int opt); @@ -371,14 +371,19 @@ void emac_if_add_multicast_group(uint8_t *address) EmacTestNetworkStack::get_instance().get_emac()->add_multicast_group(address); } +void emac_if_remove_multicast_group(uint8_t *address) +{ + EmacTestNetworkStack::get_instance().get_emac()->remove_multicast_group(address); +} + void emac_if_set_output_memory(bool memory) { - output_memory = memory; + allow_output_memory_allocs = memory; } void emac_if_set_input_memory(bool memory) { - input_memory = memory; + allow_input_memory_allocs = memory; emac_if_set_memory(memory); } @@ -386,9 +391,9 @@ void emac_if_set_input_memory(bool memory) void emac_if_check_memory(bool output) { if (output) { - emac_if_set_memory(output_memory); + emac_if_set_memory(allow_output_memory_allocs); } else { - emac_if_set_memory(input_memory); + emac_if_set_memory(allow_input_memory_allocs); } } @@ -428,42 +433,44 @@ static void link_input_event_cb(void *buf) static unsigned char eth_input_frame_data[ETH_FRAME_HEADER_LEN]; memset(eth_input_frame_data, 0, ETH_FRAME_HEADER_LEN); - int invalid_data_index = emac_if_memory_buffer_read(buf, eth_input_frame_data); - - if (eth_input_frame_data[12] == 0x90 && eth_input_frame_data[13] == 0x00) { - unsigned char eth_output_frame_data[ETH_FRAME_HEADER_LEN]; - int receipt_number; - - ctp_function function = emac_if_ctp_header_handle(eth_input_frame_data, eth_output_frame_data, EmacTestNetworkStack::get_instance().get_mac_addr(), &receipt_number); - - if (function == CTP_REPLY) { - // If reply has valid receipt number - if (emac_if_update_reply_to_outgoing_msg(receipt_number, length, invalid_data_index)) { - // Checks received messages for errors - emac_if_validate_outgoing_msg(); - // Removes not replied retry entries if any - emac_if_reset_outgoing_msg(); - // Removes retry entries no response flags - emac_if_reset_error_flags(NO_RESPONSE); - // Calls test loop - worker_loop_event_queue.call(current_test_step_cb_fnc, INPUT); - } - } - // Echoes only if configured as echo server - else if (function == CTP_FORWARD && ctp_server_mode) { - emac_if_memory_buffer_write(buf, eth_output_frame_data, false); - EmacTestNetworkStack::get_instance().get_emac()->link_out(buf); - buf = nullptr; - } + int invalid_data_index = emac_if_memory_buffer_read_and_check(buf, eth_input_frame_data); - emac_if_add_echo_server_addr(ð_input_frame_data[6]); + if (trace_level & TRACE_ETH_FRAMES) { + printf("INP> LEN %i\r\n\r\n", length); + const char trace_type[] = "INP>"; - if (trace_level & TRACE_ETH_FRAMES) { - printf("INP> LEN %i\r\n\r\n", length); - const char trace_type[] = "INP>"; - emac_if_trace_to_ascii_hex_dump(trace_type, ETH_FRAME_HEADER_LEN, eth_input_frame_data); + emac_if_trace_to_ascii_hex_dump(trace_type, ETH_FRAME_HEADER_LEN, eth_input_frame_data); + } + + unsigned char eth_output_frame_data[ETH_FRAME_HEADER_LEN]; + int receipt_number; + + ctp_function function = emac_if_ctp_header_handle(eth_input_frame_data, eth_output_frame_data, EmacTestNetworkStack::get_instance().get_mac_addr(), &receipt_number); + + if (function == ctp_function::REPLY) { + // If reply has valid receipt number + if (emac_if_update_reply_to_outgoing_msg(receipt_number, length, invalid_data_index)) { + // Checks received messages for errors + emac_if_validate_outgoing_msg(); + // Removes not replied retry entries if any + emac_if_reset_outgoing_msg(); + // Removes retry entries no response flags + emac_if_reset_error_flags(NO_RESPONSE); + // Calls test loop + worker_loop_event_queue.call(current_test_step_cb_fnc, INPUT); } } + // Echoes only if configured as echo server + else if (function == ctp_function::FORWARD && ctp_server_mode) { + emac_if_memory_buffer_write(buf, eth_output_frame_data, false); + EmacTestNetworkStack::get_instance().get_emac()->link_out(buf); + buf = nullptr; + } + + // Save echo server address + if (function != ctp_function::INVALID) { + emac_if_add_echo_server_addr(ð_input_frame_data[6]); + } } if (buf) { diff --git a/connectivity/netsocket/tests/emac_test_utils/emac_util.h b/connectivity/netsocket/tests/emac_test_utils/emac_util.h index f6320110a07..82f0825fc76 100644 --- a/connectivity/netsocket/tests/emac_test_utils/emac_util.h +++ b/connectivity/netsocket/tests/emac_test_utils/emac_util.h @@ -111,6 +111,7 @@ extern void emac_if_link_state_change_cb(bool up); void emac_if_set_all_multicast(bool all); void emac_if_add_multicast_group(uint8_t *address); +void emac_if_remove_multicast_group(uint8_t *address); void emac_if_set_output_memory(bool memory); void emac_if_set_input_memory(bool memory);