Skip to content

Tests for wifi emac interface #5435

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions TESTS/network/emac/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Description

This document describes how to run EMAC tests. The EMAC test cases are made using Ethernet Configuration Testing Protocol (CTP). To run the tests, one device in the Ethernet segment needs to be configured to be a CTP echo server. The devices running the test cases, use the echo server to forward the CTP Ethernet frames back.

# Configuring CTP echo server

A device can be configured to be a CTP echo server by enabling `echo-server` setting in the test environment's application `json` file. When device is configured to be a CTP echo server, it starts to forward CTP messages automatically after power up and will continue forwarding until power down.

# Test cases

## EMAC interface initialise

Initializes EMAC interface driver.

For WLAN installs test case so that it can intercept incoming Ethernet messages from the WLAN driver. Incoming CTP frames are handed by the test case and other frames are forwarded to the LWIP stack.

## EMAC interface broadcast

Sends three 100 byte CTP broadcast messages, waits for three seconds and sends three 50 byte CTP broadcast messages. Listens for the CTP echo server responses and stores the addresses of the echo servers if replies are received. The test case will pass if there are no responses from echo server, but further test cases will be skipped.

## EMAC interface unicast

Sends three CTP unicast messages to the CTP echo server. Verifies that all are replied.

## EMAC interface unicast frame length

Sends CTP unicast messages with Ethernet message length from 100 bytes to maximum. Verifies that all are replied.

143 changes: 143 additions & 0 deletions TESTS/network/emac/emac_ctp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright (c) 2017, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest.h"

#if MBED_CONF_APP_TEST_WIFI || MBED_CONF_APP_TEST_ETHERNET

#include "mbed.h"

#include "lwip/opt.h" /* ETH_PAD_SIZE */

#include "emac_stack_mem.h"
#include "emac_api.h"

#include "emac_tests.h"
#include "emac_ctp.h"

#include "emac_initialize.h"
#include "emac_util.h"
#include "emac_membuf.h"

using namespace utest::v1;

// Unique identifier for message
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(&eth_frame[0], dest_addr, 6);
memcpy(&eth_frame[6], origin_addr, 6);

eth_frame[12] = 0x90; /* loop back */
eth_frame[13] = 0x00;

eth_frame[14] = 0x00; /* skip count */
eth_frame[15] = 0x00;

eth_frame[16] = 0x02; /* function, forward */
eth_frame[17] = 0x00;

memcpy(&eth_frame[18], forward_addr, 6);

eth_frame[24] = 0x01; /* function, reply */
eth_frame[25] = 0x00;

receipt_number++;

eth_frame[26] = receipt_number; /* receipt number */
eth_frame[27] = receipt_number >> 8;

return receipt_number;
}

ctp_function emac_if_ctp_header_handle(unsigned char *eth_input_frame, unsigned char *eth_output_frame, unsigned char *origin_addr, int *receipt_number)
{
if (eth_input_frame[12] != 0x90 || eth_input_frame[13] != 0x00) {
return CTP_NONE;
}

int skip_count = eth_input_frame[15] << 8 | eth_input_frame[14];
unsigned char *ethernet_ptr = &eth_input_frame[16] + skip_count;

int function = ethernet_ptr[1] << 8 | ethernet_ptr[0];
ethernet_ptr += 2;

// Forward
if (function == 0x0002) {
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;
// Set forward address to destination address
memcpy(&eth_output_frame[0], ethernet_ptr, 6);
// Copy own address to origin
memcpy(&eth_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;
}

return CTP_NONE;
}

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)
{
if (eth_frame_len < ETH_FRAME_HEADER_LEN) {
eth_frame_len = ETH_FRAME_HEADER_LEN;
}

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]);

int outgoing_msg_index = emac_if_add_outgoing_msg(eth_frame_len);

if (outgoing_msg_index < 0) {
SET_ERROR_FLAGS(OUT_OF_MSG_DATA);
return;
}

emac_stack_mem_chain_t *mem_chain_p = emac_stack_mem_alloc(0, eth_frame_len + ETH_PAD_SIZE, 0);

if (!mem_chain_p) {
SET_ERROR_FLAGS(NO_FREE_MEM_BUF);
emac_if_free_outgoing_msg(outgoing_msg_index);
return;
}

if (memcmp(dest_addr, eth_mac_broadcast_addr, 6) == 0) {
emac_if_set_outgoing_msg_flags(outgoing_msg_index, BROADCAST);
}

unsigned char eth_output_frame_data[ETH_FRAME_HEADER_LEN];
int receipt_number = emac_if_ctp_header_build(eth_output_frame_data, dest_addr, origin_addr, forward_addr);
emac_if_set_outgoing_msg_receipt_num(outgoing_msg_index, receipt_number);

emac_if_memory_buffer_write(mem_chain_p, eth_output_frame_data, true);

//emac_if->ops.link_out(hw_driver, mem_chain_p);
emac_if_get()->ops.link_out(emac_if_get(), mem_chain_p);

emac_stack_mem_free(0, mem_chain_p);
}

#endif

31 changes: 31 additions & 0 deletions TESTS/network/emac/emac_ctp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2017, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 EMAC_CTP_H
#define EMAC_CTP_H

enum ctp_function {
CTP_NONE,
CTP_FORWARD,
CTP_REPLY
};

ctp_function emac_if_ctp_header_handle(unsigned char *eth_input_frame, unsigned char *eth_output_frame, unsigned char *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);
void emac_if_ctp_reply_handle(int lenght, int invalid_data_index);

#endif /* EMAC_CTP_H */
24 changes: 24 additions & 0 deletions TESTS/network/emac/emac_initialize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2017, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 EMAC_INITIALIZE_H
#define EMAC_INITIALIZE_H

uint8_t *emac_if_get_hw_addr(void);
emac_interface_t *emac_if_get(void);

#endif /* EMAC_INITIALIZE_H */
83 changes: 83 additions & 0 deletions TESTS/network/emac/emac_membuf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2017, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"

#if MBED_CONF_APP_TEST_WIFI || MBED_CONF_APP_TEST_ETHERNET

#include "lwip/opt.h" /* ETH_PAD_SIZE */

#include "emac_api.h"
#include "emac_stack_mem.h"

#include "emac_membuf.h"
#include "emac_util.h"

int emac_if_memory_buffer_read(emac_stack_mem_chain_t *mem_chain_p, unsigned char *eth_frame)
{
int eth_frame_index = 0;
int invalid_data_index = 0;
int index = ETH_PAD_SIZE;

for (emac_stack_mem_t *mem_p = emac_stack_mem_chain_dequeue(0, &mem_chain_p); mem_p != NULL; mem_p = emac_stack_mem_chain_dequeue(0, &mem_chain_p)) {
unsigned char *buf_payload = (unsigned char *) emac_stack_mem_ptr(0, mem_p);
int buf_payload_len = emac_stack_mem_len(0, mem_p);

for (; index < buf_payload_len; index++) {
if (eth_frame_index < ETH_FRAME_HEADER_LEN) {
eth_frame[eth_frame_index] = buf_payload[index];
} else {
if (buf_payload[index] != (uint8_t) eth_frame_index) {
invalid_data_index = eth_frame_index;
break;
}
}
eth_frame_index++;
}
index = 0;
}

return invalid_data_index;
}

void emac_if_memory_buffer_write(emac_stack_mem_chain_t *mem_chain_p, unsigned char *eth_frame, bool write_data)
{
int eth_frame_index = 0;
int index = ETH_PAD_SIZE;

for (emac_stack_mem_t *mem_p = emac_stack_mem_chain_dequeue(0, &mem_chain_p); mem_p != NULL; mem_p = emac_stack_mem_chain_dequeue(0, &mem_chain_p)) {
unsigned char *buf_payload = (unsigned char *) emac_stack_mem_ptr(0, mem_p);
int buf_payload_len = emac_stack_mem_len(0, mem_p);

for (; index < buf_payload_len; index++) {
if (eth_frame_index < ETH_FRAME_HEADER_LEN) {
buf_payload[index] = eth_frame[eth_frame_index];
} else if (write_data) {
buf_payload[index] = (char) eth_frame_index;
} else {
break;
}
eth_frame_index++;
}
index = 0;
}
}

#endif
24 changes: 24 additions & 0 deletions TESTS/network/emac/emac_membuf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2017, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* 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 EMAC_MEMBUF_H
#define EMAC_MEMBUF_H

int emac_if_memory_buffer_read(emac_stack_mem_chain_t *mem_chain_p, unsigned char *eth_frame);
void emac_if_memory_buffer_write(emac_stack_mem_chain_t *mem_chain_p, unsigned char *eth_frame, bool write_data);

#endif /* EMAC_MEMBUF_H */
Loading