1155 lines
36 KiB
C++
1155 lines
36 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 Integration test that a LLDP frame is sent at init.
|
|
*
|
|
*/
|
|
|
|
#include "utils_for_testing.h"
|
|
#include "mocks.h"
|
|
|
|
#include "pf_includes.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#define LOCAL_PORT 1
|
|
|
|
#define MAX_ETH_FRAME_SIZE 1514u
|
|
#define MAX_ETH_PAYLOAD_SIZE 1500u
|
|
|
|
#define LLDP_TYPE_END 0
|
|
#define LLDP_TYPE_CHASSIS_ID 1
|
|
#define LLDP_TYPE_PORT_ID 2
|
|
#define LLDP_TYPE_TTL 3
|
|
#define LLDP_TYPE_PORT_DESCRIPTION 4
|
|
#define LLDP_TYPE_MANAGEMENT_ADDRESS 8
|
|
#define LLDP_TYPE_ORG_SPEC 127
|
|
|
|
#define TLV_BYTE_0(len, type) (((len) >> 8) | ((type) << 1))
|
|
#define TLV_BYTE_1(len) (((len) >> 0) & 0xff)
|
|
#define TLV_TYPE(tlv) ((tlv)[0] >> 1)
|
|
#define TLV_LEN(tlv) ((size_t) (((tlv)[0] << 8) + (tlv)[1]) & 0x1FF)
|
|
|
|
static const char * chassis_id_test_sample_1 =
|
|
"\x53\x43\x41\x4c\x41\x4e\x43\x45\x20\x58\x2d\x32\x30\x30\x20"
|
|
"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x36\x47\x4b\x35\x20"
|
|
"\x32\x30\x34\x2d\x30\x42\x41\x30\x30\x2d\x32\x42\x41\x33\x20\x20"
|
|
"\x53\x56\x50\x4c\x36\x31\x34\x37\x39\x32\x30\x20\x20\x20\x20\x20"
|
|
"\x20\x20\x20\x20\x20\x39\x20\x56\x20\x20\x35\x20\x20\x34\x20\x20"
|
|
"\x32";
|
|
|
|
static const char * port_id_test_sample_1 =
|
|
"\x70\x6f\x72\x74\x2d\x30\x30\x33\x2e\x61\x62\x63\x64\x65\x66\x67"
|
|
"\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77"
|
|
"\x78\x79\x7a\x2d\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c"
|
|
"\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x31\x32"
|
|
"\x33\x34\x35\x36\x37\x38\x39\x30\x2e\x61\x62\x63\x64\x65\x66\x67"
|
|
"\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77"
|
|
"\x78\x79\x7a\x2d\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c"
|
|
"\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x31\x32"
|
|
"\x2e\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
|
|
"\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x2d\x61\x62\x63\x64"
|
|
"\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74"
|
|
"\x75\x76\x77\x78\x79\x7a\x31\x32\x33\x2e\x61\x62\x63\x64\x65\x66"
|
|
"\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76"
|
|
"\x77\x78\x79\x7a\x2d\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b"
|
|
"\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x31"
|
|
"\x32\x33\x34\x35\x36\x37\x38\x39\x30";
|
|
|
|
static pf_lldp_chassis_id_t fake_chassis_id (void)
|
|
{
|
|
pf_lldp_chassis_id_t chassis_id;
|
|
|
|
memset (&chassis_id, 0, sizeof (chassis_id));
|
|
snprintf (
|
|
chassis_id.string,
|
|
sizeof (chassis_id.string),
|
|
"%s",
|
|
"Chassis ID received from remote device");
|
|
chassis_id.len = strlen (chassis_id.string);
|
|
chassis_id.subtype = PF_LLDP_SUBTYPE_LOCALLY_ASSIGNED;
|
|
chassis_id.is_valid = true;
|
|
return chassis_id;
|
|
}
|
|
|
|
static pf_lldp_port_id_t fake_port_id (void)
|
|
{
|
|
pf_lldp_port_id_t port_id;
|
|
|
|
memset (&port_id, 0, sizeof (port_id));
|
|
snprintf (
|
|
port_id.string,
|
|
sizeof (port_id.string),
|
|
"%s",
|
|
"Port ID received from remote device");
|
|
port_id.len = strlen (port_id.string);
|
|
port_id.subtype = PF_LLDP_SUBTYPE_LOCALLY_ASSIGNED;
|
|
port_id.is_valid = true;
|
|
return port_id;
|
|
}
|
|
|
|
static uint16_t fake_ttl (void)
|
|
{
|
|
return 12345;
|
|
}
|
|
|
|
static pf_lldp_port_description_t fake_port_description (void)
|
|
{
|
|
pf_lldp_port_description_t port_description;
|
|
|
|
memset (&port_description, 0, sizeof (port_description));
|
|
snprintf (
|
|
port_description.string,
|
|
sizeof (port_description.string),
|
|
"%s",
|
|
"Port Description");
|
|
port_description.len = strlen (port_description.string);
|
|
port_description.is_valid = true;
|
|
return port_description;
|
|
}
|
|
|
|
static pf_lldp_management_address_t fake_ipv4_management_address (void)
|
|
{
|
|
pf_lldp_management_address_t management_address;
|
|
|
|
memset (&management_address, 0, sizeof (management_address));
|
|
management_address.subtype = 1; /* IPv4 */
|
|
management_address.value[0] = 192;
|
|
management_address.value[1] = 168;
|
|
management_address.value[2] = 10;
|
|
management_address.value[3] = 102;
|
|
management_address.len = 4;
|
|
management_address.interface_number.subtype = 2; /* ifIndex */
|
|
management_address.interface_number.value = 1;
|
|
management_address.is_valid = true;
|
|
return management_address;
|
|
}
|
|
|
|
static pf_lldp_management_address_t fake_ipv6_management_address (void)
|
|
{
|
|
pf_lldp_management_address_t management_address;
|
|
|
|
memset (&management_address, 0, sizeof (management_address));
|
|
management_address.subtype = 2; /* IPv6 */
|
|
management_address.value[0] = 0x20;
|
|
management_address.value[1] = 0x01;
|
|
management_address.value[2] = 0x0d;
|
|
management_address.value[3] = 0xd8;
|
|
management_address.value[4] = 0x85;
|
|
management_address.value[5] = 0xa3;
|
|
management_address.value[6] = 0x00;
|
|
management_address.value[7] = 0x00;
|
|
management_address.value[8] = 0x00;
|
|
management_address.value[9] = 0x00;
|
|
management_address.value[10] = 0x8a;
|
|
management_address.value[11] = 0x2e;
|
|
management_address.value[12] = 0x03;
|
|
management_address.value[13] = 0x70;
|
|
management_address.value[14] = 0x73;
|
|
management_address.value[15] = 0x34;
|
|
management_address.len = 16;
|
|
management_address.interface_number.subtype = 2; /* ifIndex */
|
|
management_address.interface_number.value = 1;
|
|
management_address.is_valid = true;
|
|
return management_address;
|
|
}
|
|
|
|
static pf_lldp_link_status_t fake_phy_config (void)
|
|
{
|
|
pf_lldp_link_status_t phy_config;
|
|
|
|
memset (&phy_config, 0, sizeof (phy_config));
|
|
phy_config.is_autonegotiation_supported = true;
|
|
phy_config.is_autonegotiation_enabled = true;
|
|
phy_config.autonegotiation_advertised_capabilities =
|
|
PNAL_ETH_AUTONEG_CAP_100BaseTX_HALF_DUPLEX |
|
|
PNAL_ETH_AUTONEG_CAP_100BaseTX_FULL_DUPLEX;
|
|
phy_config.operational_mau_type = PNAL_ETH_MAU_COPPER_100BaseTX_FULL_DUPLEX;
|
|
phy_config.is_valid = true;
|
|
return phy_config;
|
|
}
|
|
|
|
static pnet_ethaddr_t fake_mac_address (void)
|
|
{
|
|
pnet_ethaddr_t mac_address;
|
|
|
|
memset (&mac_address, 0, sizeof (mac_address));
|
|
mac_address.addr[0] = 0xab;
|
|
mac_address.addr[0] = 0xcd;
|
|
mac_address.addr[0] = 0xef;
|
|
mac_address.addr[0] = 0x01;
|
|
mac_address.addr[0] = 0x23;
|
|
mac_address.addr[0] = 0x45;
|
|
return mac_address;
|
|
}
|
|
|
|
static pf_lldp_signal_delay_t fake_port_delay (void)
|
|
{
|
|
pf_lldp_signal_delay_t port_delay;
|
|
|
|
memset (&port_delay, 0, sizeof (port_delay));
|
|
port_delay.cable_delay_local = 1;
|
|
port_delay.rx_delay_local = 2;
|
|
port_delay.tx_delay_local = 3;
|
|
port_delay.rx_delay_remote = 4;
|
|
port_delay.tx_delay_remote = 5;
|
|
port_delay.is_valid = true;
|
|
return port_delay;
|
|
}
|
|
|
|
static pf_lldp_peer_info_t fake_peer_info (void)
|
|
{
|
|
pf_lldp_peer_info_t peer;
|
|
|
|
memset (&peer, 0, sizeof (peer));
|
|
peer.chassis_id = fake_chassis_id();
|
|
peer.port_id = fake_port_id();
|
|
peer.ttl = fake_ttl();
|
|
peer.port_description = fake_port_description();
|
|
peer.management_address = fake_ipv4_management_address();
|
|
peer.phy_config = fake_phy_config();
|
|
peer.mac_address = fake_mac_address();
|
|
peer.port_delay = fake_port_delay();
|
|
return peer;
|
|
}
|
|
|
|
static size_t construct_packet_chassis_id (
|
|
uint8_t packet[],
|
|
const pf_lldp_chassis_id_t * id)
|
|
{
|
|
size_t size = 0;
|
|
|
|
if (id->is_valid)
|
|
{
|
|
packet[0] = TLV_BYTE_0 (1 + id->len, LLDP_TYPE_CHASSIS_ID);
|
|
packet[1] = TLV_BYTE_1 (1 + id->len);
|
|
packet[2] = id->subtype;
|
|
memcpy (&packet[3], id->string, id->len);
|
|
size = 3 + id->len;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static size_t construct_packet_port_id (
|
|
uint8_t packet[],
|
|
const pf_lldp_port_id_t * id)
|
|
{
|
|
size_t size = 0;
|
|
|
|
if (id->is_valid)
|
|
{
|
|
packet[0] = TLV_BYTE_0 (1 + id->len, LLDP_TYPE_PORT_ID);
|
|
packet[1] = TLV_BYTE_1 (1 + id->len);
|
|
packet[2] = id->subtype;
|
|
memcpy (&packet[3], id->string, id->len);
|
|
size = 3 + id->len;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static size_t construct_packet_ttl (uint8_t packet[], uint16_t ttl)
|
|
{
|
|
size_t size = 0;
|
|
|
|
packet[0] = TLV_BYTE_0 (sizeof (ttl), LLDP_TYPE_TTL);
|
|
packet[1] = TLV_BYTE_1 (sizeof (ttl));
|
|
packet[2] = ttl >> 8;
|
|
packet[3] = ttl >> 0;
|
|
size = 4;
|
|
|
|
return size;
|
|
}
|
|
|
|
static size_t construct_packet_port_description (
|
|
uint8_t packet[],
|
|
const pf_lldp_port_description_t * description)
|
|
{
|
|
size_t size = 0;
|
|
|
|
if (description->is_valid)
|
|
{
|
|
packet[0] = TLV_BYTE_0 (description->len, LLDP_TYPE_PORT_DESCRIPTION);
|
|
packet[1] = TLV_BYTE_1 (description->len);
|
|
memcpy (&packet[2], description->string, description->len);
|
|
size = 2 + description->len;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static size_t construct_packet_management_address (
|
|
uint8_t packet[],
|
|
const pf_lldp_management_address_t * address)
|
|
{
|
|
size_t size = 0;
|
|
|
|
if (address->is_valid)
|
|
{
|
|
uint32_t big_endian;
|
|
|
|
packet[0] =
|
|
TLV_BYTE_0 (2 + address->len + 6, LLDP_TYPE_MANAGEMENT_ADDRESS);
|
|
packet[1] = TLV_BYTE_1 (2 + address->len + 6);
|
|
packet[2] = 1 + address->len;
|
|
packet[3] = address->subtype;
|
|
memcpy (&packet[4], address->value, address->len);
|
|
size += 4 + address->len;
|
|
|
|
big_endian = CC_TO_BE32 (address->interface_number.value);
|
|
packet[0 + size] = address->interface_number.subtype;
|
|
memcpy (&packet[1 + size], &big_endian, 4);
|
|
packet[5 + size] = 0; /* OID string length */
|
|
size += 6;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static size_t construct_packet_link_status (
|
|
uint8_t packet[],
|
|
const pf_lldp_link_status_t * status)
|
|
{
|
|
size_t size = 0;
|
|
|
|
if (status->is_valid)
|
|
{
|
|
packet[0] = TLV_BYTE_0 (9, LLDP_TYPE_ORG_SPEC);
|
|
packet[1] = TLV_BYTE_1 (9);
|
|
packet[2] = 0x00; /* 802.3 OUI */
|
|
packet[3] = 0x12; /* 802.3 OUI */
|
|
packet[4] = 0x0F; /* 802.3 OUI */
|
|
packet[5] = 1; /* subtype */
|
|
packet[6] = ((uint8_t)status->is_autonegotiation_supported << 0) |
|
|
((uint8_t)status->is_autonegotiation_enabled << 1);
|
|
packet[7] = status->autonegotiation_advertised_capabilities >> 8;
|
|
packet[8] = status->autonegotiation_advertised_capabilities >> 0;
|
|
packet[9] = status->operational_mau_type >> 8;
|
|
packet[10] = status->operational_mau_type >> 0;
|
|
size = 11;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static size_t construct_packet_signal_delay (
|
|
uint8_t packet[],
|
|
const pf_lldp_signal_delay_t * delay)
|
|
{
|
|
size_t size = 0;
|
|
uint32_t bigendian;
|
|
|
|
if (delay->is_valid)
|
|
{
|
|
packet[0] = TLV_BYTE_0 (24, LLDP_TYPE_ORG_SPEC);
|
|
packet[1] = TLV_BYTE_1 (24);
|
|
packet[2] = 0x00; /* Profinet OUI */
|
|
packet[3] = 0x0E; /* Profinet OUI */
|
|
packet[4] = 0xCF; /* Profinet OUI */
|
|
packet[5] = 1; /* subtype */
|
|
bigendian = CC_TO_BE32 (delay->rx_delay_local);
|
|
memcpy (&packet[6], &bigendian, 4);
|
|
bigendian = CC_TO_BE32 (delay->rx_delay_remote);
|
|
memcpy (&packet[10], &bigendian, 4);
|
|
bigendian = CC_TO_BE32 (delay->tx_delay_local);
|
|
memcpy (&packet[14], &bigendian, 4);
|
|
bigendian = CC_TO_BE32 (delay->tx_delay_remote);
|
|
memcpy (&packet[18], &bigendian, 4);
|
|
bigendian = CC_TO_BE32 (delay->cable_delay_local);
|
|
memcpy (&packet[22], &bigendian, 4);
|
|
size = 26;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static size_t construct_packet_chassis_mac (
|
|
uint8_t packet[],
|
|
const pnet_ethaddr_t * mac_address)
|
|
{
|
|
size_t size = 0;
|
|
|
|
packet[0] = TLV_BYTE_0 (10, LLDP_TYPE_ORG_SPEC);
|
|
packet[1] = TLV_BYTE_1 (10);
|
|
packet[2] = 0x00; /* Profinet OUI */
|
|
packet[3] = 0x0E; /* Profinet OUI */
|
|
packet[4] = 0xCF; /* Profinet OUI */
|
|
packet[5] = 5; /* subtype */
|
|
memcpy (&packet[6], mac_address->addr, 6);
|
|
size = 12;
|
|
|
|
return size;
|
|
}
|
|
|
|
static size_t construct_packet_end_marker (uint8_t packet[])
|
|
{
|
|
size_t size;
|
|
|
|
packet[0] = TLV_BYTE_0 (0, LLDP_TYPE_END);
|
|
packet[1] = TLV_BYTE_1 (0);
|
|
size = 2;
|
|
|
|
return size;
|
|
}
|
|
|
|
static size_t construct_packet (
|
|
uint8_t packet[MAX_ETH_PAYLOAD_SIZE],
|
|
const pf_lldp_peer_info_t * data)
|
|
{
|
|
memset (packet, 0xff, MAX_ETH_PAYLOAD_SIZE);
|
|
size_t size = 0;
|
|
|
|
size += construct_packet_chassis_id (&packet[size], &data->chassis_id);
|
|
size += construct_packet_port_id (&packet[size], &data->port_id);
|
|
size += construct_packet_ttl (&packet[size], data->ttl);
|
|
size += construct_packet_port_description (
|
|
&packet[size],
|
|
&data->port_description);
|
|
size += construct_packet_management_address (
|
|
&packet[size],
|
|
&data->management_address);
|
|
size += construct_packet_link_status (&packet[size], &data->phy_config);
|
|
size += construct_packet_signal_delay (&packet[size], &data->port_delay);
|
|
size += construct_packet_chassis_mac (&packet[size], &data->mac_address);
|
|
size += construct_packet_end_marker (&packet[size]);
|
|
|
|
return size;
|
|
}
|
|
|
|
class LldpTest : public PnetIntegrationTestBase
|
|
{
|
|
protected:
|
|
virtual void SetUp() override
|
|
{
|
|
mock_init();
|
|
cfg_init();
|
|
appdata_init();
|
|
available_modules_and_submodules_init();
|
|
|
|
callcounter_reset();
|
|
|
|
pnet_init_only (net, &pnet_default_cfg);
|
|
|
|
/* Do not clear mock or callcounters here - we need to verify send at init
|
|
* from LLDP */
|
|
};
|
|
};
|
|
|
|
TEST_F (LldpTest, LldpInitTest)
|
|
{
|
|
/* Verify that LLDP has sent a frame at init */
|
|
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);
|
|
EXPECT_EQ (mock_os_data.eth_send_count, PNET_MAX_PHYSICAL_PORTS);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGenerateAliasName)
|
|
{
|
|
char alias[256]; /** Terminated string */
|
|
int err;
|
|
|
|
err = pf_lldp_generate_alias_name (NULL, "dut", alias, 96);
|
|
EXPECT_EQ (err, -1);
|
|
|
|
err = pf_lldp_generate_alias_name ("port-001", NULL, alias, 96);
|
|
EXPECT_EQ (err, -1);
|
|
|
|
err = pf_lldp_generate_alias_name ("port-001", "dut", NULL, 96);
|
|
EXPECT_EQ (err, -1);
|
|
|
|
/* Test legacy PN v2.2
|
|
* PortId string does not include a "."
|
|
* Alias = PortId.StationName
|
|
*/
|
|
err = pf_lldp_generate_alias_name ("port-001", "dut", alias, 13);
|
|
EXPECT_EQ (err, 0);
|
|
EXPECT_EQ (strcmp (alias, "port-001.dut"), 0);
|
|
memset (alias, 0, sizeof (alias));
|
|
|
|
err = pf_lldp_generate_alias_name ("port-001", "dut", alias, 12);
|
|
EXPECT_EQ (err, -1);
|
|
|
|
/* Test PN v2.3+
|
|
* PortId string does include a "."
|
|
* Alias = PortId
|
|
*/
|
|
err = pf_lldp_generate_alias_name ("port-001.dut", "tester", alias, 13);
|
|
EXPECT_EQ (err, 0);
|
|
EXPECT_EQ (strcmp (alias, "port-001.dut"), 0);
|
|
memset (alias, 0, sizeof (alias));
|
|
|
|
err = pf_lldp_generate_alias_name ("port-001.dut", "tester", alias, 12);
|
|
EXPECT_EQ (err, -1);
|
|
|
|
/* Test data from rt-tester v2.3 style */
|
|
err = pf_lldp_generate_alias_name (
|
|
port_id_test_sample_1,
|
|
chassis_id_test_sample_1,
|
|
alias,
|
|
256);
|
|
EXPECT_EQ (err, 0);
|
|
EXPECT_EQ (strcmp (alias, port_id_test_sample_1), 0);
|
|
memset (alias, 0, sizeof (alias));
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpParsePacket)
|
|
{
|
|
uint8_t packet[MAX_ETH_PAYLOAD_SIZE];
|
|
int error;
|
|
size_t size;
|
|
pf_lldp_peer_info_t actual;
|
|
const pf_lldp_peer_info_t expected = fake_peer_info();
|
|
|
|
size = construct_packet (packet, &expected);
|
|
memset (&actual, 0xff, sizeof (actual));
|
|
|
|
error = pf_lldp_parse_packet (packet, size, &actual);
|
|
|
|
EXPECT_EQ (error, 0);
|
|
|
|
EXPECT_EQ (actual.chassis_id.is_valid, expected.chassis_id.is_valid);
|
|
EXPECT_EQ (actual.chassis_id.subtype, expected.chassis_id.subtype);
|
|
EXPECT_EQ (actual.chassis_id.len, expected.chassis_id.len);
|
|
EXPECT_STREQ (actual.chassis_id.string, expected.chassis_id.string);
|
|
|
|
EXPECT_EQ (actual.port_id.is_valid, expected.port_id.is_valid);
|
|
EXPECT_EQ (actual.port_id.subtype, expected.port_id.subtype);
|
|
EXPECT_EQ (actual.port_id.len, expected.port_id.len);
|
|
EXPECT_STREQ (actual.port_id.string, expected.port_id.string);
|
|
|
|
EXPECT_EQ (actual.ttl, expected.ttl);
|
|
|
|
EXPECT_EQ (
|
|
actual.port_description.is_valid,
|
|
expected.port_description.is_valid);
|
|
EXPECT_EQ (actual.port_description.len, expected.port_description.len);
|
|
EXPECT_STREQ (
|
|
actual.port_description.string,
|
|
expected.port_description.string);
|
|
|
|
EXPECT_EQ (
|
|
actual.management_address.is_valid,
|
|
expected.management_address.is_valid);
|
|
EXPECT_EQ (
|
|
actual.management_address.subtype,
|
|
expected.management_address.subtype);
|
|
EXPECT_EQ (actual.management_address.len, expected.management_address.len);
|
|
EXPECT_EQ (
|
|
memcmp (
|
|
actual.management_address.value,
|
|
expected.management_address.value,
|
|
4),
|
|
0);
|
|
EXPECT_EQ (
|
|
actual.management_address.interface_number.subtype,
|
|
expected.management_address.interface_number.subtype);
|
|
EXPECT_EQ (
|
|
actual.management_address.interface_number.value,
|
|
expected.management_address.interface_number.value);
|
|
|
|
EXPECT_EQ (actual.phy_config.is_valid, expected.phy_config.is_valid);
|
|
EXPECT_EQ (
|
|
actual.phy_config.is_autonegotiation_supported,
|
|
expected.phy_config.is_autonegotiation_supported);
|
|
EXPECT_EQ (
|
|
actual.phy_config.is_autonegotiation_enabled,
|
|
expected.phy_config.is_autonegotiation_enabled);
|
|
EXPECT_EQ (
|
|
actual.phy_config.autonegotiation_advertised_capabilities,
|
|
expected.phy_config.autonegotiation_advertised_capabilities);
|
|
EXPECT_EQ (
|
|
actual.phy_config.operational_mau_type,
|
|
expected.phy_config.operational_mau_type);
|
|
|
|
EXPECT_EQ (actual.port_delay.is_valid, expected.port_delay.is_valid);
|
|
EXPECT_EQ (
|
|
actual.port_delay.rx_delay_local,
|
|
expected.port_delay.rx_delay_local);
|
|
EXPECT_EQ (
|
|
actual.port_delay.rx_delay_remote,
|
|
expected.port_delay.rx_delay_remote);
|
|
EXPECT_EQ (
|
|
actual.port_delay.tx_delay_local,
|
|
expected.port_delay.tx_delay_local);
|
|
EXPECT_EQ (
|
|
actual.port_delay.tx_delay_remote,
|
|
expected.port_delay.tx_delay_remote);
|
|
EXPECT_EQ (
|
|
actual.port_delay.cable_delay_local,
|
|
expected.port_delay.cable_delay_local);
|
|
|
|
EXPECT_EQ (memcmp (actual.mac_address.addr, expected.mac_address.addr, 6), 0);
|
|
|
|
/* TODO: Add check for port status */
|
|
|
|
/* Finally check that everything is as expected.
|
|
* While this is the only check really needed, the checks above will make
|
|
* it easier to find out exactly what went wrong.
|
|
*/
|
|
EXPECT_EQ (memcmp (&actual, &expected, sizeof (expected)), 0);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpParsePacketWithTooBigChassisId)
|
|
{
|
|
uint8_t packet[MAX_ETH_PAYLOAD_SIZE];
|
|
int error;
|
|
size_t size;
|
|
pf_lldp_peer_info_t actual;
|
|
pf_lldp_peer_info_t peer = fake_peer_info();
|
|
const size_t max_len = sizeof (peer.chassis_id.string) - 1;
|
|
|
|
peer.chassis_id.len = max_len + 1;
|
|
size = construct_packet (packet, &peer);
|
|
memset (&actual, 0xff, sizeof (actual));
|
|
|
|
error = pf_lldp_parse_packet (packet, size, &actual);
|
|
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (actual.chassis_id.is_valid, false);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpParsePacketWithTooBigPortId)
|
|
{
|
|
uint8_t packet[MAX_ETH_PAYLOAD_SIZE];
|
|
int error;
|
|
size_t size;
|
|
pf_lldp_peer_info_t actual;
|
|
pf_lldp_peer_info_t peer = fake_peer_info();
|
|
const size_t max_len = sizeof (peer.port_id.string) - 1;
|
|
|
|
peer.port_id.len = max_len + 1;
|
|
size = construct_packet (packet, &peer);
|
|
memset (&actual, 0xff, sizeof (actual));
|
|
|
|
error = pf_lldp_parse_packet (packet, size, &actual);
|
|
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (actual.port_id.is_valid, false);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpParsePacketWithTooBigPortDescription)
|
|
{
|
|
uint8_t packet[MAX_ETH_PAYLOAD_SIZE];
|
|
int error;
|
|
size_t size;
|
|
pf_lldp_peer_info_t actual;
|
|
pf_lldp_peer_info_t peer = fake_peer_info();
|
|
const size_t max_len = sizeof (peer.port_description.string) - 1;
|
|
|
|
peer.port_description.len = max_len + 1;
|
|
size = construct_packet (packet, &peer);
|
|
memset (&actual, 0xff, sizeof (actual));
|
|
|
|
error = pf_lldp_parse_packet (packet, size, &actual);
|
|
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (actual.port_description.is_valid, false);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpParsePacketWithTooBigManagementAddress)
|
|
{
|
|
uint8_t packet[MAX_ETH_PAYLOAD_SIZE];
|
|
int error;
|
|
size_t size;
|
|
pf_lldp_peer_info_t actual;
|
|
pf_lldp_peer_info_t peer = fake_peer_info();
|
|
const size_t max_len = sizeof (peer.management_address.value);
|
|
|
|
peer.management_address.len = max_len + 1;
|
|
size = construct_packet (packet, &peer);
|
|
memset (&actual, 0xff, sizeof (actual));
|
|
|
|
error = pf_lldp_parse_packet (packet, size, &actual);
|
|
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (actual.management_address.is_valid, false);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpParsePacketWithMultipleManagementAddresses)
|
|
{
|
|
uint8_t packet[MAX_ETH_PAYLOAD_SIZE];
|
|
int error;
|
|
size_t size;
|
|
pf_lldp_peer_info_t actual;
|
|
const pf_lldp_chassis_id_t chassis_id = fake_chassis_id();
|
|
const pf_lldp_port_id_t port_id = fake_port_id();
|
|
const uint16_t ttl = fake_ttl();
|
|
const pf_lldp_management_address_t ipv4 = fake_ipv4_management_address();
|
|
const pf_lldp_management_address_t ipv6 = fake_ipv6_management_address();
|
|
|
|
/* Construct LLDP packet with IPv4 and IPv6 addresses (in that order) */
|
|
memset (packet, 0xff, MAX_ETH_PAYLOAD_SIZE);
|
|
size = 0;
|
|
size += construct_packet_chassis_id (&packet[size], &chassis_id);
|
|
size += construct_packet_port_id (&packet[size], &port_id);
|
|
size += construct_packet_ttl (&packet[size], ttl);
|
|
size += construct_packet_management_address (&packet[size], &ipv4);
|
|
size += construct_packet_management_address (&packet[size], &ipv6);
|
|
size += construct_packet_end_marker (&packet[size]);
|
|
|
|
memset (&actual, 0xff, sizeof (actual));
|
|
|
|
error = pf_lldp_parse_packet (packet, size, &actual);
|
|
|
|
/* Note that only the IPv4 address should be saved, as IPv6 addresses are
|
|
* of no use for the p-net stack.
|
|
*/
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (actual.management_address.is_valid, true);
|
|
EXPECT_EQ (actual.management_address.subtype, ipv4.subtype);
|
|
EXPECT_EQ (actual.management_address.len, 4u);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpParsePacketWithInvalidManagementAddresses)
|
|
{
|
|
uint8_t packet[MAX_ETH_PAYLOAD_SIZE];
|
|
int error;
|
|
size_t size;
|
|
pf_lldp_peer_info_t actual;
|
|
const pf_lldp_chassis_id_t chassis_id = fake_chassis_id();
|
|
const pf_lldp_port_id_t port_id = fake_port_id();
|
|
const uint16_t ttl = fake_ttl();
|
|
pf_lldp_management_address_t address;
|
|
|
|
address = fake_ipv4_management_address();
|
|
address.len = 5;
|
|
|
|
/* Construct LLDP packet */
|
|
memset (packet, 0xff, MAX_ETH_PAYLOAD_SIZE);
|
|
size = 0;
|
|
size += construct_packet_chassis_id (&packet[size], &chassis_id);
|
|
size += construct_packet_port_id (&packet[size], &port_id);
|
|
size += construct_packet_ttl (&packet[size], ttl);
|
|
size += construct_packet_management_address (&packet[size], &address);
|
|
size += construct_packet_end_marker (&packet[size]);
|
|
|
|
memset (&actual, 0xff, sizeof (actual));
|
|
|
|
error = pf_lldp_parse_packet (packet, size, &actual);
|
|
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (actual.management_address.is_valid, false);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetChassisId)
|
|
{
|
|
pf_lldp_chassis_id_t chassis_id;
|
|
|
|
memset (&chassis_id, 0xff, sizeof (chassis_id));
|
|
|
|
pf_lldp_get_chassis_id (net, &chassis_id);
|
|
EXPECT_EQ (chassis_id.subtype, PF_LLDP_SUBTYPE_LOCALLY_ASSIGNED);
|
|
EXPECT_STREQ (
|
|
chassis_id.string,
|
|
"PNET unit tests <orderid> <serial nbr> 1 P "
|
|
" 0 0 0");
|
|
EXPECT_EQ (
|
|
chassis_id.len,
|
|
strlen ("PNET unit tests <orderid> <serial nbr> "
|
|
" 1 P 0 0 0"));
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetPortId)
|
|
{
|
|
pf_lldp_port_id_t port_id;
|
|
|
|
memset (&port_id, 0xff, sizeof (port_id));
|
|
|
|
pf_lldp_get_port_id (net, LOCAL_PORT, &port_id);
|
|
EXPECT_EQ (port_id.subtype, PF_LLDP_SUBTYPE_LOCALLY_ASSIGNED);
|
|
EXPECT_STREQ (port_id.string, "port-001.12-34-00-78-90-AB");
|
|
EXPECT_EQ (port_id.len, strlen ("port-001.12-34-00-78-90-AB"));
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetPortDescription)
|
|
{
|
|
pf_lldp_port_description_t port_desc;
|
|
|
|
memset (&port_desc, 0xff, sizeof (port_desc));
|
|
|
|
pf_lldp_get_port_description (net, LOCAL_PORT, &port_desc);
|
|
EXPECT_STREQ (port_desc.string, TEST_INTERFACE_NAME);
|
|
EXPECT_EQ (port_desc.len, strlen (TEST_INTERFACE_NAME));
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetManagementAddress)
|
|
{
|
|
pf_lldp_management_address_t man_address;
|
|
|
|
mock_os_data.interface_index = 3;
|
|
memset (&man_address, 0xff, sizeof (man_address));
|
|
|
|
pf_lldp_get_management_address (net, &man_address);
|
|
EXPECT_EQ (man_address.subtype, 1); /* IPv4 */
|
|
EXPECT_EQ (man_address.value[0], 192);
|
|
EXPECT_EQ (man_address.value[1], 168);
|
|
EXPECT_EQ (man_address.value[2], 1);
|
|
EXPECT_EQ (man_address.value[3], 171);
|
|
EXPECT_EQ (man_address.len, 4u);
|
|
EXPECT_EQ (man_address.interface_number.subtype, 2); /* ifIndex */
|
|
EXPECT_EQ (man_address.interface_number.value, 3);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetSignalDelays)
|
|
{
|
|
pf_lldp_signal_delay_t delays;
|
|
|
|
memset (&delays, 0xff, sizeof (delays));
|
|
|
|
pf_lldp_get_signal_delays (net, LOCAL_PORT, &delays);
|
|
EXPECT_EQ (delays.tx_delay_local, 0u); /* Not measured */
|
|
EXPECT_EQ (delays.rx_delay_local, 0u); /* Not measured */
|
|
EXPECT_EQ (delays.cable_delay_local, 0u); /* Not measured */
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetLinkStatus)
|
|
{
|
|
pf_lldp_link_status_t link_status;
|
|
|
|
mock_os_data.eth_status[LOCAL_PORT].is_autonegotiation_supported = true;
|
|
mock_os_data.eth_status[LOCAL_PORT].is_autonegotiation_enabled = true;
|
|
mock_os_data.eth_status[LOCAL_PORT].autonegotiation_advertised_capabilities =
|
|
PNAL_ETH_AUTONEG_CAP_100BaseTX_HALF_DUPLEX |
|
|
PNAL_ETH_AUTONEG_CAP_100BaseTX_FULL_DUPLEX;
|
|
mock_os_data.eth_status[LOCAL_PORT].operational_mau_type =
|
|
PNAL_ETH_MAU_COPPER_100BaseTX_FULL_DUPLEX;
|
|
memset (&link_status, 0xff, sizeof (link_status));
|
|
|
|
/* The ethernet status is updated by the background worker */
|
|
pf_pdport_update_eth_status (net);
|
|
|
|
pf_lldp_get_link_status (net, LOCAL_PORT, &link_status);
|
|
EXPECT_EQ (link_status.is_autonegotiation_supported, true);
|
|
EXPECT_EQ (link_status.is_autonegotiation_enabled, true);
|
|
EXPECT_EQ (
|
|
link_status.autonegotiation_advertised_capabilities,
|
|
PNAL_ETH_AUTONEG_CAP_100BaseTX_HALF_DUPLEX |
|
|
PNAL_ETH_AUTONEG_CAP_100BaseTX_FULL_DUPLEX);
|
|
EXPECT_EQ (
|
|
link_status.operational_mau_type,
|
|
PNAL_ETH_MAU_COPPER_100BaseTX_FULL_DUPLEX);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetLinkStatusGivenAutonegotiationDisabled)
|
|
{
|
|
pf_lldp_link_status_t link_status;
|
|
|
|
mock_os_data.eth_status[LOCAL_PORT].is_autonegotiation_supported = false;
|
|
mock_os_data.eth_status[LOCAL_PORT].is_autonegotiation_enabled = false;
|
|
mock_os_data.eth_status[LOCAL_PORT].autonegotiation_advertised_capabilities =
|
|
0x0000;
|
|
mock_os_data.eth_status[LOCAL_PORT].operational_mau_type =
|
|
PNAL_ETH_MAU_COPPER_100BaseTX_HALF_DUPLEX;
|
|
memset (&link_status, 0xff, sizeof (link_status));
|
|
|
|
pf_pdport_update_eth_status (net);
|
|
|
|
pf_lldp_get_link_status (net, LOCAL_PORT, &link_status);
|
|
EXPECT_EQ (link_status.is_autonegotiation_supported, false);
|
|
EXPECT_EQ (link_status.is_autonegotiation_enabled, false);
|
|
EXPECT_EQ (link_status.autonegotiation_advertised_capabilities, 0x0000);
|
|
EXPECT_EQ (
|
|
link_status.operational_mau_type,
|
|
PNAL_ETH_MAU_COPPER_100BaseTX_HALF_DUPLEX);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetPeerTimestamp)
|
|
{
|
|
uint32_t actual;
|
|
const uint32_t expected = 0x87654321;
|
|
int error;
|
|
pf_lldp_peer_info_t received_data;
|
|
|
|
/* Nothing received */
|
|
error = pf_lldp_get_peer_timestamp (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, -1);
|
|
|
|
/* Receive fake data at fake timestamp */
|
|
mock_os_data.system_uptime_10ms = expected;
|
|
received_data = fake_peer_info();
|
|
pf_lldp_store_peer_info (net, LOCAL_PORT, &received_data);
|
|
|
|
error = pf_lldp_get_peer_timestamp (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (actual, expected);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetPeerChassisId)
|
|
{
|
|
const pf_lldp_peer_info_t received = fake_peer_info();
|
|
const pf_lldp_chassis_id_t expected = received.chassis_id;
|
|
pf_lldp_chassis_id_t actual;
|
|
int error;
|
|
|
|
/* Nothing received */
|
|
error = pf_lldp_get_peer_chassis_id (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, -1);
|
|
|
|
/* Receive fake data */
|
|
pf_lldp_store_peer_info (net, LOCAL_PORT, &received);
|
|
|
|
error = pf_lldp_get_peer_chassis_id (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (memcmp (&actual, &expected, sizeof (actual)), 0);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetPeerPortId)
|
|
{
|
|
const pf_lldp_peer_info_t received = fake_peer_info();
|
|
const pf_lldp_port_id_t expected = received.port_id;
|
|
pf_lldp_port_id_t actual;
|
|
int error;
|
|
|
|
/* Nothing received */
|
|
error = pf_lldp_get_peer_port_id (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, -1);
|
|
|
|
/* Receive fake data */
|
|
pf_lldp_store_peer_info (net, LOCAL_PORT, &received);
|
|
|
|
error = pf_lldp_get_peer_port_id (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (memcmp (&actual, &expected, sizeof (actual)), 0);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetPeerPortDescription)
|
|
{
|
|
const pf_lldp_peer_info_t received = fake_peer_info();
|
|
const pf_lldp_port_description_t expected = received.port_description;
|
|
pf_lldp_port_description_t actual;
|
|
int error;
|
|
|
|
/* Nothing received */
|
|
error = pf_lldp_get_peer_port_description (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, -1);
|
|
|
|
/* Receive fake data */
|
|
pf_lldp_store_peer_info (net, LOCAL_PORT, &received);
|
|
|
|
error = pf_lldp_get_peer_port_description (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (memcmp (&actual, &expected, sizeof (actual)), 0);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetPeerManagementAddress)
|
|
{
|
|
const pf_lldp_peer_info_t received = fake_peer_info();
|
|
const pf_lldp_management_address_t expected = received.management_address;
|
|
pf_lldp_management_address_t actual;
|
|
int error;
|
|
|
|
/* Nothing received */
|
|
error = pf_lldp_get_peer_management_address (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, -1);
|
|
|
|
/* Receive fake data */
|
|
pf_lldp_store_peer_info (net, LOCAL_PORT, &received);
|
|
|
|
error = pf_lldp_get_peer_management_address (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (memcmp (&actual, &expected, sizeof (actual)), 0);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetPeerStationName)
|
|
{
|
|
pf_lldp_station_name_t station_name;
|
|
int error;
|
|
|
|
/* Nothing received */
|
|
error = pf_lldp_get_peer_station_name (net, LOCAL_PORT, &station_name);
|
|
EXPECT_EQ (error, -1);
|
|
|
|
/* TODO: Add test case for scenario where LLDP packet has been received */
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetPeerSignalDelays)
|
|
{
|
|
const pf_lldp_peer_info_t received = fake_peer_info();
|
|
const pf_lldp_signal_delay_t expected = received.port_delay;
|
|
pf_lldp_signal_delay_t actual;
|
|
int error;
|
|
|
|
/* Nothing received */
|
|
error = pf_lldp_get_peer_signal_delays (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, -1);
|
|
|
|
/* Receive fake data */
|
|
pf_lldp_store_peer_info (net, LOCAL_PORT, &received);
|
|
|
|
error = pf_lldp_get_peer_signal_delays (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (memcmp (&actual, &expected, sizeof (actual)), 0);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpGetPeerLinkStatus)
|
|
{
|
|
const pf_lldp_peer_info_t received = fake_peer_info();
|
|
const pf_lldp_link_status_t expected = received.phy_config;
|
|
pf_lldp_link_status_t actual;
|
|
int error;
|
|
|
|
/* Nothing received */
|
|
error = pf_lldp_get_peer_link_status (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, -1);
|
|
|
|
/* Receive fake data */
|
|
pf_lldp_store_peer_info (net, LOCAL_PORT, &received);
|
|
|
|
error = pf_lldp_get_peer_link_status (net, LOCAL_PORT, &actual);
|
|
EXPECT_EQ (error, 0);
|
|
EXPECT_EQ (memcmp (&actual, &expected, sizeof (actual)), 0);
|
|
}
|
|
|
|
TEST_F (LldpTest, LldpConstructFrame)
|
|
{
|
|
uint8_t frame[MAX_ETH_FRAME_SIZE];
|
|
const uint8_t * p;
|
|
const uint8_t * tlv;
|
|
size_t returned_size;
|
|
size_t size;
|
|
|
|
mock_os_data.interface_index = 3;
|
|
|
|
returned_size = pf_lldp_construct_frame (net, LOCAL_PORT, frame);
|
|
|
|
EXPECT_GT (returned_size, 14u);
|
|
EXPECT_LE (returned_size, MAX_ETH_FRAME_SIZE);
|
|
|
|
size = 0;
|
|
|
|
/* Check destination MAC address (from LLDP standard) */
|
|
p = &frame[size];
|
|
EXPECT_EQ (p[0], 0x01);
|
|
EXPECT_EQ (p[1], 0x80);
|
|
EXPECT_EQ (p[2], 0xC2);
|
|
EXPECT_EQ (p[3], 0x00);
|
|
EXPECT_EQ (p[4], 0x00);
|
|
EXPECT_EQ (p[5], 0x0E);
|
|
size += 6;
|
|
|
|
/* Check source MAC address (from app configuration) */
|
|
p = &frame[size];
|
|
EXPECT_EQ (p[0], 0x12);
|
|
EXPECT_EQ (p[1], 0x34);
|
|
EXPECT_EQ (p[2], 0x00);
|
|
EXPECT_EQ (p[3], 0x78);
|
|
EXPECT_EQ (p[4], 0x90);
|
|
EXPECT_EQ (p[5], 0xab);
|
|
size += 6;
|
|
|
|
/* Check EtherType (from LLDP standard) */
|
|
p = &frame[size];
|
|
EXPECT_EQ (p[0], 0x88);
|
|
EXPECT_EQ (p[1], 0xCC);
|
|
size += 2;
|
|
|
|
/* Check Chassis ID TLV */
|
|
tlv = &frame[size];
|
|
EXPECT_EQ (TLV_TYPE (tlv), LLDP_TYPE_CHASSIS_ID);
|
|
EXPECT_GE (TLV_LEN (tlv), 2u);
|
|
EXPECT_LE (TLV_LEN (tlv), 256u);
|
|
size += 2 + TLV_LEN (tlv);
|
|
|
|
/* Check Port ID TLV */
|
|
tlv = &frame[size];
|
|
EXPECT_EQ (TLV_TYPE (tlv), LLDP_TYPE_PORT_ID);
|
|
EXPECT_GE (TLV_LEN (tlv), 2u);
|
|
EXPECT_LE (TLV_LEN (tlv), 256u);
|
|
EXPECT_EQ (tlv[2], 7u); /* Subtype */
|
|
size += 2 + TLV_LEN (tlv);
|
|
|
|
/* Check Time To Live TLV */
|
|
tlv = &frame[size];
|
|
EXPECT_EQ (TLV_TYPE (tlv), LLDP_TYPE_TTL);
|
|
EXPECT_EQ (TLV_LEN (tlv), 2u);
|
|
EXPECT_EQ (tlv[2], 0u); /* MSB of TTL */
|
|
EXPECT_EQ (tlv[3], 20u); /* LSB of TTL */
|
|
size += 2 + TLV_LEN (tlv);
|
|
|
|
/* Note that the order in which TLVs below are placed in the packet
|
|
* is not specified by LLDP or Profinet (except for the End TTL).
|
|
*/
|
|
|
|
/* Check LLDP_PNIO_PORTSTATUS TLV */
|
|
tlv = &frame[size];
|
|
EXPECT_EQ (TLV_TYPE (tlv), LLDP_TYPE_ORG_SPEC);
|
|
EXPECT_EQ (TLV_LEN (tlv), 3 + 1 + 4u);
|
|
EXPECT_EQ (tlv[2], 0x00); /* Profinet OUI */
|
|
EXPECT_EQ (tlv[3], 0x0E); /* Profinet OUI */
|
|
EXPECT_EQ (tlv[4], 0xCF); /* Profinet OUI */
|
|
EXPECT_EQ (tlv[5], 0x02); /* Subtype */
|
|
size += 2 + TLV_LEN (tlv);
|
|
|
|
/* Check LLDP_PNIO_CHASSIS_MAC TLV */
|
|
tlv = &frame[size];
|
|
EXPECT_EQ (TLV_TYPE (tlv), LLDP_TYPE_ORG_SPEC);
|
|
EXPECT_EQ (TLV_LEN (tlv), 3 + 1 + 6u);
|
|
EXPECT_EQ (tlv[2], 0x00); /* Profinet OUI */
|
|
EXPECT_EQ (tlv[3], 0x0E); /* Profinet OUI */
|
|
EXPECT_EQ (tlv[4], 0xCF); /* Profinet OUI */
|
|
EXPECT_EQ (tlv[5], 0x05); /* Subtype */
|
|
EXPECT_EQ (tlv[6], 0x12); /* MAC address */
|
|
EXPECT_EQ (tlv[7], 0x34); /* MAC address */
|
|
EXPECT_EQ (tlv[8], 0x00); /* MAC address */
|
|
EXPECT_EQ (tlv[9], 0x78); /* MAC address */
|
|
EXPECT_EQ (tlv[10], 0x90); /* MAC address */
|
|
EXPECT_EQ (tlv[11], 0xab); /* MAC address */
|
|
size += 2 + TLV_LEN (tlv);
|
|
|
|
/* Check 802.3 MAC/PHY Configuration/Status TLV */
|
|
tlv = &frame[size];
|
|
EXPECT_EQ (TLV_TYPE (tlv), LLDP_TYPE_ORG_SPEC);
|
|
EXPECT_EQ (TLV_LEN (tlv), 3 + 1 + 5u);
|
|
EXPECT_EQ (tlv[2], 0x00); /* 802.3 OUI */
|
|
EXPECT_EQ (tlv[3], 0x12); /* 802.3 OUI */
|
|
EXPECT_EQ (tlv[4], 0x0F); /* 802.3 OUI */
|
|
EXPECT_EQ (tlv[5], 0x01); /* Subtype */
|
|
size += 2 + TLV_LEN (tlv);
|
|
|
|
/* Check Management Address TLV */
|
|
tlv = &frame[size];
|
|
EXPECT_EQ (TLV_TYPE (tlv), LLDP_TYPE_MANAGEMENT_ADDRESS);
|
|
EXPECT_EQ (TLV_LEN (tlv), 1 + 5 + 5 + 1u);
|
|
EXPECT_EQ (tlv[2], 1u + 4u); /* Size of Subtype+Address */
|
|
EXPECT_EQ (tlv[3], 1u); /* Subtype IPv4 */
|
|
EXPECT_EQ (tlv[4], 192u);
|
|
EXPECT_EQ (tlv[5], 168u);
|
|
EXPECT_EQ (tlv[6], 1u);
|
|
EXPECT_EQ (tlv[7], 171u);
|
|
EXPECT_EQ (tlv[8], 2u); /* Subtype ifIndex */
|
|
EXPECT_EQ (tlv[9], 0u); /* ifIndex MSB */
|
|
EXPECT_EQ (tlv[10], 0u); /* ifIndex */
|
|
EXPECT_EQ (tlv[11], 0u); /* ifIndex */
|
|
EXPECT_EQ (tlv[12], 3u); /* ifIndex LSB */
|
|
EXPECT_EQ (tlv[13], 0u); /* Size of OID */
|
|
size += 2 + TLV_LEN (tlv);
|
|
|
|
/* Check End Of LLDPPDU TLV */
|
|
tlv = &frame[size];
|
|
EXPECT_EQ (TLV_TYPE (tlv), LLDP_TYPE_END);
|
|
EXPECT_EQ (TLV_LEN (tlv), 0u);
|
|
size += 2 + TLV_LEN (tlv);
|
|
|
|
EXPECT_EQ (size, returned_size);
|
|
}
|