net: l2: ieee802154: ensure L2/L3 recv package handover
Issue #53630 proved that we didn't have sufficient test coverage for L2/L3 package handover on the RX side. This commit creates additional test coverage to reproduce the problem found in #53630 and avoid future regressions. Signed-off-by: Florian Grandel <jerico.dev@gmail.com>
This commit is contained in:
parent
fadb1fd168
commit
79adc524cd
2 changed files with 123 additions and 23 deletions
|
@ -16,6 +16,7 @@ CONFIG_NET_L2_IEEE802154_ACK_REPLY=y
|
||||||
CONFIG_NET_SOCKETS=y
|
CONFIG_NET_SOCKETS=y
|
||||||
CONFIG_NET_SOCKETS_PACKET=y
|
CONFIG_NET_SOCKETS_PACKET=y
|
||||||
CONFIG_NET_SOCKETS_PACKET_DGRAM=y
|
CONFIG_NET_SOCKETS_PACKET_DGRAM=y
|
||||||
|
CONFIG_NET_CONTEXT_RCVTIMEO=y
|
||||||
|
|
||||||
CONFIG_MBEDTLS=y
|
CONFIG_MBEDTLS=y
|
||||||
CONFIG_MBEDTLS_BUILTIN=y
|
CONFIG_MBEDTLS_BUILTIN=y
|
||||||
|
|
|
@ -444,36 +444,128 @@ out:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_ack_reply(struct ieee802154_pkt_test *t)
|
static bool test_recv_and_ack_reply(struct ieee802154_pkt_test *t)
|
||||||
{
|
{
|
||||||
|
/* Incoming IEEE 802.15.4 packet with payload header compression. */
|
||||||
static uint8_t data_pkt[] = {
|
static uint8_t data_pkt[] = {
|
||||||
0x61, 0xdc, 0x16, 0xcd, 0xab, 0xc2, 0xa3, 0x9e, 0x00, 0x00, 0x4b,
|
/* IEEE 802.15.4 MHR */
|
||||||
0x12, 0x00, 0x26, 0x18, 0x32, 0x00, 0x00, 0x4b, 0x12, 0x00, 0x7b,
|
0x61, 0xd8, /* FCF with AR bit set */
|
||||||
0x00, 0x3a, 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x16, /* Sequence */
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x01, 0x0d, 0xb8,
|
0xcd, 0xab, /* Destination PAN */
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0xff, 0xff, /* Destination Address */
|
||||||
0x02, 0x87, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01,
|
0xc2, 0xa3, 0x9e, 0x00, 0x00, 0x4b, 0x12, 0x00, /* Source Address */
|
||||||
0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
/* IEEE 802.15.4 MAC Payload */
|
||||||
0x16, 0xf0, 0x02, 0xff, 0x16, 0xf0, 0x12, 0xff, 0x16, 0xf0, 0x32,
|
0x7b, 0x39, /* IPHC header, SAM: compressed, DAM: 48-bits inline */
|
||||||
0xff, 0x16, 0xf0, 0x00, 0xff, 0x16, 0xf0, 0x00, 0xff, 0x16
|
0x3a, /* Next header: ICMPv6 */
|
||||||
|
0x02, 0x01, 0xff, 0x4b, 0x12, 0x00, /* IPv6 Destination */
|
||||||
|
0x87, /* Type: NS */
|
||||||
|
0x00, /* Code*/
|
||||||
|
0xb7, 0x45, /* Checksum */
|
||||||
|
0x00, 0x00, 0x00, 0x00, /* Reserved */
|
||||||
|
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x14, 0xa6, 0x1c, 0x00, 0x4b,
|
||||||
|
0x12, 0x00, /* Target Address */
|
||||||
|
0x01, /* ICMPv6 Option: Source LL address */
|
||||||
|
0x02, /* Length */
|
||||||
|
0xe5, 0xac, 0xa1, 0x1c, 0x00, 0x4b, 0x12, 0x00, /* LL address */
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */
|
||||||
|
};
|
||||||
|
/* Expected uncompressed IPv6 payload. */
|
||||||
|
static uint8_t expected_rx_pkt[] = {
|
||||||
|
0x60, 0x00, 0x00, 0x00, /* IPv6, Traffic Class, Flow Label */
|
||||||
|
0x00, 0x28, /* Payload Length */
|
||||||
|
0x3a, /* Next header: ICMPv6 */
|
||||||
|
0xff, /* Hop Limit */
|
||||||
|
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x02, 0x12, 0x4b, 0x00, 0x00, 0x9e, 0xa3, 0xc2, /* Source */
|
||||||
|
0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x01, 0xff, 0x4b, 0x12, 0x00, /* Destination */
|
||||||
|
0x87, /* Type: NS */
|
||||||
|
0x00, /* Code*/
|
||||||
|
0xb7, 0x45, /* Checksum */
|
||||||
|
0x00, 0x00, 0x00, 0x00, /* Reserved */
|
||||||
|
0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x70, 0x14, 0xa6, 0x1c, 0x00, 0x4b, 0x12, 0x00, /* Target Address */
|
||||||
|
0x01, /* ICMPv6 Option: Source LL address */
|
||||||
|
0x02, /* Length */
|
||||||
|
0xe5, 0xac, 0xa1, 0x1c, 0x00, 0x4b, 0x12, 0x00, /* LL address */
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */
|
||||||
|
};
|
||||||
|
struct ieee802154_context *ctx = net_if_l2_data(iface);
|
||||||
|
struct sockaddr_ll recv_src_sll = {0};
|
||||||
|
struct sockaddr_ll socket_sll = {
|
||||||
|
.sll_ifindex = net_if_get_by_iface(iface),
|
||||||
|
.sll_family = AF_PACKET,
|
||||||
|
.sll_protocol = ETH_P_IEEE802154,
|
||||||
|
};
|
||||||
|
uint8_t received_payload[80] = {0};
|
||||||
|
struct timeval timeo_optval = {
|
||||||
|
.tv_sec = 1,
|
||||||
|
.tv_usec = 0,
|
||||||
};
|
};
|
||||||
struct ieee802154_mpdu mpdu;
|
struct ieee802154_mpdu mpdu;
|
||||||
struct net_pkt *pkt;
|
socklen_t recv_src_sll_len;
|
||||||
struct net_buf *frag;
|
struct net_buf *frag;
|
||||||
|
struct net_pkt *rx_pkt;
|
||||||
|
bool result = false;
|
||||||
|
uint8_t mac_be[8];
|
||||||
|
int received_len;
|
||||||
|
int fd;
|
||||||
|
|
||||||
NET_INFO("- Sending ACK reply to a data packet\n");
|
NET_INFO("- Sending ACK reply to a data packet\n");
|
||||||
|
|
||||||
pkt = net_pkt_rx_alloc(K_FOREVER);
|
fd = socket(AF_PACKET, SOCK_DGRAM, ETH_P_IEEE802154);
|
||||||
frag = net_pkt_get_frag(pkt, sizeof(data_pkt), K_FOREVER);
|
if (fd < 0) {
|
||||||
|
NET_ERR("*** Failed to create DGRAM socket : %d\n", errno);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bind(fd, (const struct sockaddr *)&socket_sll, sizeof(struct sockaddr_ll))) {
|
||||||
|
NET_ERR("*** Failed to bind packet socket : %d\n", errno);
|
||||||
|
goto release_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo_optval, sizeof(timeo_optval))) {
|
||||||
|
NET_ERR("*** Failed to set reception timeout on packet socket : %d\n", errno);
|
||||||
|
goto release_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
rx_pkt = net_pkt_rx_alloc(K_FOREVER);
|
||||||
|
frag = net_pkt_get_frag(rx_pkt, sizeof(data_pkt), K_FOREVER);
|
||||||
|
|
||||||
memcpy(frag->data, data_pkt, sizeof(data_pkt));
|
memcpy(frag->data, data_pkt, sizeof(data_pkt));
|
||||||
frag->len = sizeof(data_pkt);
|
frag->len = sizeof(data_pkt);
|
||||||
|
|
||||||
net_pkt_frag_add(pkt, frag);
|
net_pkt_frag_add(rx_pkt, frag);
|
||||||
|
|
||||||
if (net_recv_data(iface, pkt) < 0) {
|
if (net_recv_data(iface, rx_pkt) < 0) {
|
||||||
NET_ERR("Recv data failed");
|
NET_ERR("Recv data failed");
|
||||||
return false;
|
goto release_rx_pkt;
|
||||||
|
}
|
||||||
|
|
||||||
|
recv_src_sll_len = sizeof(recv_src_sll);
|
||||||
|
received_len = recvfrom(fd, received_payload, sizeof(received_payload), 0,
|
||||||
|
(struct sockaddr *)&recv_src_sll, &recv_src_sll_len);
|
||||||
|
if (received_len < 0) {
|
||||||
|
NET_ERR("*** Failed to receive packet, errno %d\n", errno);
|
||||||
|
goto release_rx_pkt;
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_memcpy_swap(mac_be, ctx->ext_addr, IEEE802154_EXT_ADDR_LENGTH);
|
||||||
|
if (recv_src_sll_len != sizeof(struct sockaddr_ll) ||
|
||||||
|
recv_src_sll.sll_ifindex != net_if_get_by_iface(iface) ||
|
||||||
|
recv_src_sll.sll_family != AF_PACKET || recv_src_sll.sll_protocol != ETH_P_IEEE802154 ||
|
||||||
|
recv_src_sll.sll_halen != IEEE802154_EXT_ADDR_LENGTH ||
|
||||||
|
memcmp(recv_src_sll.sll_addr, mac_be, IEEE802154_EXT_ADDR_LENGTH)) {
|
||||||
|
NET_ERR("*** Received socket address does not compare\n", errno);
|
||||||
|
goto release_rx_pkt;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkt_hexdump(received_payload, received_len);
|
||||||
|
|
||||||
|
if (memcmp(expected_rx_pkt, received_payload,
|
||||||
|
sizeof(expected_rx_pkt))) {
|
||||||
|
NET_ERR("*** Received uncompressed IPv6 payload does not compare\n");
|
||||||
|
goto release_rx_pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
k_yield();
|
k_yield();
|
||||||
|
@ -482,7 +574,7 @@ static bool test_ack_reply(struct ieee802154_pkt_test *t)
|
||||||
/* an ACK packet should be in current_pkt */
|
/* an ACK packet should be in current_pkt */
|
||||||
if (!current_pkt->frags) {
|
if (!current_pkt->frags) {
|
||||||
NET_ERR("*** No ACK reply sent\n");
|
NET_ERR("*** No ACK reply sent\n");
|
||||||
return false;
|
goto release_rx_pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt_hexdump(net_pkt_data(current_pkt), net_pkt_get_len(current_pkt));
|
pkt_hexdump(net_pkt_data(current_pkt), net_pkt_get_len(current_pkt));
|
||||||
|
@ -490,19 +582,26 @@ static bool test_ack_reply(struct ieee802154_pkt_test *t)
|
||||||
if (!ieee802154_validate_frame(net_pkt_data(current_pkt),
|
if (!ieee802154_validate_frame(net_pkt_data(current_pkt),
|
||||||
net_pkt_get_len(current_pkt), &mpdu)) {
|
net_pkt_get_len(current_pkt), &mpdu)) {
|
||||||
NET_ERR("*** ACK Reply is invalid\n");
|
NET_ERR("*** ACK Reply is invalid\n");
|
||||||
return false;
|
goto release_tx_frag;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(mpdu.mhr.fs, t->mhr_check.fc_seq,
|
if (memcmp(mpdu.mhr.fs, t->mhr_check.fc_seq,
|
||||||
sizeof(struct ieee802154_fcf_seq))) {
|
sizeof(struct ieee802154_fcf_seq))) {
|
||||||
NET_ERR("*** ACK Reply does not compare\n");
|
NET_ERR("*** ACK Reply does not compare\n");
|
||||||
return false;
|
goto release_tx_frag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
|
||||||
|
release_tx_frag:
|
||||||
net_pkt_frag_unref(current_pkt->frags);
|
net_pkt_frag_unref(current_pkt->frags);
|
||||||
current_pkt->frags = NULL;
|
current_pkt->frags = NULL;
|
||||||
|
release_rx_pkt:
|
||||||
return true;
|
net_pkt_unref(rx_pkt);
|
||||||
|
release_fd:
|
||||||
|
close(fd);
|
||||||
|
out:
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool test_packet_cloning_with_cb(void)
|
static bool test_packet_cloning_with_cb(void)
|
||||||
|
@ -609,11 +708,11 @@ ZTEST(ieee802154_l2, test_parsing_ack_pkt)
|
||||||
zassert_true(ret, "ACK parsed");
|
zassert_true(ret, "ACK parsed");
|
||||||
}
|
}
|
||||||
|
|
||||||
ZTEST(ieee802154_l2, test_replying_ack_pkt)
|
ZTEST(ieee802154_l2, test_receiving_pkt_and_replying_ack_pkt)
|
||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
ret = test_ack_reply(&test_ack_pkt);
|
ret = test_recv_and_ack_reply(&test_ack_pkt);
|
||||||
|
|
||||||
zassert_true(ret, "ACK replied");
|
zassert_true(ret, "ACK replied");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue