ProfinetConnector/profinet_stack/p-net/test/test_dcp.cpp

381 lines
16 KiB
C++

/*********************************************************************
* _ _ _
* _ __ | |_ _ | | __ _ | |__ ___
* | '__|| __|(_)| | / _` || '_ \ / __|
* | | | |_ _ | || (_| || |_) |\__ \
* |_| \__|(_)|_| \__,_||_.__/ |___/
*
* www.rt-labs.com
* Copyright 2018 rt-labs AB, Sweden.
*
* This software is dual-licensed under GPLv3 and a commercial
* license. See the file LICENSE.md distributed with this software for
* full license information.
********************************************************************/
/**
* @file
* @brief Testing of DCP aspects.
*
* For example
* Sending hello frame
* Handling of get name request
* Read station name
* Set station name
* Set IP address
* Do factory reset
*
* Checks only function return codes. No checking of the sent Ethernet frames is
* done.
*
*/
#include "utils_for_testing.h"
#include "mocks.h"
#include "pf_includes.h"
#include <gtest/gtest.h>
class DcpTest : public PnetIntegrationTest
{
};
class DcpUnitTest : public PnetUnitTest
{
};
static uint8_t get_wrong_length_req[] = {
// clang-format off
// Destination MAC address. Pos 0
0x12, 0x34, 0x00, 0x78, 0x90, 0xab,
// Source MAC address. Pos 6
0xc8, 0x5b, 0x76, 0xe6, 0x89, 0xdf,
// Ethernet type = Profinet RT. Pos 12
0x88, 0x92,
// DCP set/get. Pos 14
0xfe, 0xfd,
// Get, request. Pos 16
0x03, 0x00,
// XID. Pos 20
0x00, 0x00, 0x00, 0x01,
// Reserved. Pos 22
0x04, 0x01,
// DCP data length. Wrong value. Pos 24
0x04, 0x00,
// Options. Pos 26
0x00, 0x00
// clang-format on
};
static uint8_t get_name_req[] = {
0x12, 0x34, 0x00, 0x78, 0x90, 0xab, 0xc8, 0x5b, 0x76, 0xe6, 0x89, 0xdf,
0x88, 0x92, 0xfe, 0xfd, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
0x00, 0x06, 0x02, 0x02, 0x02, 0x03, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static uint8_t ident_req[] = {
0x01, 0x0e, 0xcf, 0x00, 0x00, 0x00, 0xc8, 0x5b, 0x76, 0xe6, 0x89, 0xdf,
0x88, 0x92, 0xfe, 0xfe, 0x05, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,
0x00, 0x10, 0x02, 0x02, 0x00, 0x0c, 0x72, 0x74, 0x2d, 0x6c, 0x61, 0x62,
0x73, 0x2d, 0x64, 0x65, 0x6d, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static uint8_t set_name_req[] = {
0x12, 0x34, 0x00, 0x78, 0x90, 0xab, 0xc8, 0x5b, 0x76, 0xe6, 0x89, 0xdf,
0x88, 0x92, 0xfe, 0xfd, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
0x00, 0x12, 0x02, 0x02, 0x00, 0x0e, 0x00, 0x00, 0x72, 0x74, 0x2d, 0x6c,
0x61, 0x62, 0x73, 0x2d, 0x64, 0x65, 0x6d, 0x6f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static uint8_t set_ip_req[] = {
0x12, 0x34, 0x00, 0x78, 0x90, 0xab, 0xc8, 0x5b, 0x76, 0xe6, 0x89, 0xdf,
0x88, 0x92, 0xfe, 0xfd, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0x18, 0x01, 0x02, 0x00, 0x0e, 0x00, 0x00, 0xc0, 0xa8, 0x01, 0xab,
0xff, 0xff, 0xff, 0x00, 0xc0, 0xa8, 0x01, 0x01, 0x05, 0x02, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static uint8_t factory_reset_req[] = {
0x12, 0x34, 0x00, 0x78, 0x90, 0xab, 0xc8, 0x5b, 0x76, 0xe6, 0x89, 0xdf,
0x88, 0x92, 0xfe, 0xfd, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
0x00, 0x06, 0x05, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static uint8_t signal_req[] = {
0x12, 0x34, 0x00, 0x78, 0x90, 0xab, 0xc8, 0x5b, 0x76, 0xe6, 0x89, 0xdf,
0x88, 0x92, 0xfe, 0xfd, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00,
0x00, 0x06, 0x05, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
TEST_F (DcpTest, DcpHelloTest)
{
pnal_buf_t * p_buf;
int ret;
mock_clear();
ret = pf_dcp_hello_req (net);
EXPECT_EQ (ret, 0);
mock_clear();
p_buf = pnal_buf_alloc (PF_FRAME_BUFFER_SIZE);
memcpy (p_buf->payload, get_name_req, sizeof (get_name_req));
ret = pf_eth_recv (mock_os_data.eth_if_handle, net, p_buf);
EXPECT_EQ (ret, 1); // Incoming frame is handled
// LLDP frames and one additional frame
EXPECT_EQ (mock_os_data.eth_send_count, PNET_MAX_PHYSICAL_PORTS + 1);
EXPECT_EQ (appdata.call_counters.led_off_calls, 1);
EXPECT_EQ (appdata.call_counters.led_on_calls, 0);
EXPECT_EQ (appdata.call_counters.state_calls, 0);
EXPECT_EQ (appdata.call_counters.connect_calls, 0);
EXPECT_EQ (appdata.call_counters.release_calls, 0);
EXPECT_EQ (appdata.call_counters.dcontrol_calls, 0);
EXPECT_EQ (appdata.call_counters.ccontrol_calls, 0);
EXPECT_EQ (appdata.call_counters.read_calls, 0);
EXPECT_EQ (appdata.call_counters.write_calls, 0);
}
TEST_F (DcpTest, DcpGetWrongLengthTest)
{
pnal_buf_t * p_buf;
int ret;
mock_clear();
p_buf = pnal_buf_alloc (PF_FRAME_BUFFER_SIZE);
memcpy (p_buf->payload, get_wrong_length_req, sizeof (get_wrong_length_req));
p_buf->len = sizeof (get_wrong_length_req);
ret = pf_eth_recv (mock_os_data.eth_if_handle, net, p_buf);
EXPECT_EQ (ret, 1); // Incoming frame is handled
EXPECT_EQ (mock_os_data.eth_send_count, 0); // Drop malformed frame
EXPECT_EQ (appdata.call_counters.led_off_calls, 1);
EXPECT_EQ (appdata.call_counters.led_on_calls, 0);
EXPECT_EQ (appdata.call_counters.state_calls, 0);
EXPECT_EQ (appdata.call_counters.connect_calls, 0);
EXPECT_EQ (appdata.call_counters.release_calls, 0);
EXPECT_EQ (appdata.call_counters.dcontrol_calls, 0);
EXPECT_EQ (appdata.call_counters.ccontrol_calls, 0);
EXPECT_EQ (appdata.call_counters.read_calls, 0);
EXPECT_EQ (appdata.call_counters.write_calls, 0);
}
TEST_F (DcpTest, DcpRunTest)
{
pnal_buf_t * p_buf;
int ret;
TEST_TRACE ("\nGenerating mock set name request\n");
p_buf = pnal_buf_alloc (PF_FRAME_BUFFER_SIZE);
memcpy (p_buf->payload, set_name_req, sizeof (set_name_req));
p_buf->len = sizeof (set_name_req);
ret = pf_eth_recv (mock_os_data.eth_if_handle, net, p_buf);
EXPECT_EQ (ret, 1);
TEST_TRACE ("\nGenerating mock set IP request\n");
p_buf = pnal_buf_alloc (PF_FRAME_BUFFER_SIZE);
memcpy (p_buf->payload, set_ip_req, sizeof (set_ip_req));
p_buf->len = sizeof (set_ip_req);
ret = pf_eth_recv (mock_os_data.eth_if_handle, net, p_buf);
EXPECT_EQ (ret, 1);
TEST_TRACE ("\nGenerating mock set ident request\n");
p_buf = pnal_buf_alloc (PF_FRAME_BUFFER_SIZE);
memcpy (p_buf->payload, ident_req, sizeof (ident_req));
p_buf->len = sizeof (ident_req);
ret = pf_eth_recv (mock_os_data.eth_if_handle, net, p_buf);
EXPECT_EQ (ret, 1);
TEST_TRACE ("\nGenerating mock factory reset request\n");
p_buf = pnal_buf_alloc (PF_FRAME_BUFFER_SIZE);
memcpy (p_buf->payload, factory_reset_req, sizeof (factory_reset_req));
p_buf->len = sizeof (factory_reset_req);
ret = pf_eth_recv (mock_os_data.eth_if_handle, net, p_buf);
EXPECT_EQ (ret, 1);
TEST_TRACE ("\nGenerating mock flash LED request\n");
p_buf = pnal_buf_alloc (PF_FRAME_BUFFER_SIZE);
memcpy (p_buf->payload, signal_req, sizeof (signal_req));
p_buf->len = sizeof (signal_req);
ret = pf_eth_recv (mock_os_data.eth_if_handle, net, p_buf);
EXPECT_EQ (ret, 1);
/* Wait for LED to flash three times at 1 Hz */
run_stack (4 * 1000 * 1000);
EXPECT_EQ (
mock_os_data.eth_send_count,
9 + (PNET_MAX_PHYSICAL_PORTS - 1) * 4);
EXPECT_EQ (mock_os_data.set_ip_suite_count, 2);
EXPECT_EQ (appdata.call_counters.led_on_calls, 3);
EXPECT_EQ (appdata.call_counters.led_off_calls, 4);
EXPECT_EQ (appdata.call_counters.state_calls, 0);
EXPECT_EQ (appdata.call_counters.connect_calls, 0);
EXPECT_EQ (appdata.call_counters.release_calls, 0);
EXPECT_EQ (appdata.call_counters.dcontrol_calls, 0);
EXPECT_EQ (appdata.call_counters.ccontrol_calls, 0);
EXPECT_EQ (appdata.call_counters.read_calls, 0);
EXPECT_EQ (appdata.call_counters.write_calls, 0);
}
TEST_F (DcpUnitTest, DcpCalculateDelay)
{
pnet_ethaddr_t mac_address = {0};
const uint16_t step = 10000; /* Output resolution in microseconds */
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 2), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 10), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 100), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1000), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6400), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6401), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0xFFFF), 0U);
mac_address.addr[5] = 0x01;
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 2), 1U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 10), 1U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 100), 1U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1000), 1U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6400), 1U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6401), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0xFFFF), 0U);
mac_address.addr[5] = 0x02;
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 2), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 10), 2U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 100), 2U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1000), 2U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6400), 2U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6401), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0xFFFF), 0U);
mac_address.addr[5] = 0xC7; /* 199 */
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 100), 99U * step);
mac_address.addr[5] = 0xFF; /* 255 */
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 2), 1U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 10), 5U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 100), 55U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 252), 3U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 253), 2U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 254), 1U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 255), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 256), 255U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 257), 255U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 258), 255U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1000), 255U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6400), 255U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6401), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0xFFFF), 0U);
mac_address.addr[5] = 0x00;
mac_address.addr[4] = 0x01; /* 256 */
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 2), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 10), 6U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 100), 56U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 253), 3U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 254), 2U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 255), 1U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 256), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 257), 256U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 258), 256U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1000), 256U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1000), 256U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6400), 256U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6401), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0xFFFF), 0U);
mac_address.addr[4] = 0x02; /* 512 */
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 2), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 10), 2U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 100), 12U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1000), 512U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6400), 512U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6401), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0xFFFF), 0U);
mac_address.addr[4] = 0xFF; /* 65280 */
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 2), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 10), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 100), 80U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1000), 280U * step);
ASSERT_EQ (
pf_dcp_calculate_response_delay (&mac_address, 6400),
1280U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6401), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0xFFFF), 0U);
mac_address.addr[4] = 0xFF;
mac_address.addr[5] = 0xFF; /* 65535 */
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 2), 1U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 10), 5U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 100), 35U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 1000), 535U * step);
ASSERT_EQ (
pf_dcp_calculate_response_delay (&mac_address, 6400),
1535U * step);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 6401), 0U);
ASSERT_EQ (pf_dcp_calculate_response_delay (&mac_address, 0xFFFF), 0U);
}
TEST_F (DcpUnitTest, DcpCheckDestinationAddress)
{
pnet_ethaddr_t local_mac_address = {0x12, 0x34, 0x00, 0x78, 0x90, 0xab};
pnet_ethaddr_t unknown_mac_address = {0x12, 0x34, 0x00, 0x78, 0x95, 0xab};
pnet_ethaddr_t multicast_mac_address = {0x01, 0x0e, 0xcf, 0x00, 0x00, 0x00};
ASSERT_EQ (
pf_dcp_check_destination_address (&local_mac_address, &local_mac_address),
true);
ASSERT_EQ (
pf_dcp_check_destination_address (
&local_mac_address,
&unknown_mac_address),
false);
ASSERT_EQ (
pf_dcp_check_destination_address (
&local_mac_address,
&multicast_mac_address),
false);
}