blob: 53c65e39e16ffabdfa1eedcde6dddfabaa2b037e [file] [log] [blame]
/*
* Copyright (c) 2023 Enphase Energy
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/ztest.h>
#include "eth_ivshmem_priv.h"
#define SHMEM_SECTION_SIZE KB(4)
#define VRING_DESC_LEN 32
#define VRING_HEADER_SIZE 1792
#define VRING_DATA_MAX_LEN 2304
static struct eth_ivshmem_queue q1, q2;
static uint8_t shmem_buff[SHMEM_SECTION_SIZE * 2];
static const void *rx_message;
static size_t rx_len;
static void test_init_queues(void)
{
int res = eth_ivshmem_queue_init(&q1, (uintptr_t)shmem_buff, SHMEM_SECTION_SIZE, true);
zassert_ok(res);
res = eth_ivshmem_queue_init(&q2, (uintptr_t)shmem_buff, SHMEM_SECTION_SIZE, false);
zassert_ok(res);
}
static inline int queue_tx(struct eth_ivshmem_queue *q, const void *data, size_t len)
{
void *dest;
int res = eth_ivshmem_queue_tx_get_buff(q, &dest, len);
if (res == 0) {
memcpy(dest, data, len);
res = eth_ivshmem_queue_tx_commit_buff(q);
}
return res;
}
static void test_setup(void *fixture)
{
ARG_UNUSED(fixture);
rx_message = NULL;
rx_len = 0;
test_init_queues();
}
ZTEST(eth_ivshmem_queue_tests, test_init)
{
zassert_equal(q1.desc_max_len, VRING_DESC_LEN);
zassert_equal(q1.vring_header_size, VRING_HEADER_SIZE);
zassert_equal(q1.vring_data_max_len, VRING_DATA_MAX_LEN);
zassert_equal_ptr(q1.tx.shmem, shmem_buff);
zassert_equal_ptr(q1.rx.shmem, shmem_buff + SHMEM_SECTION_SIZE);
zassert_equal_ptr(q2.tx.shmem, shmem_buff + SHMEM_SECTION_SIZE);
zassert_equal_ptr(q2.rx.shmem, shmem_buff);
}
ZTEST(eth_ivshmem_queue_tests, test_simple_send_receive)
{
/* Send */
int x = 42;
zassert_ok(queue_tx(&q1, &x, sizeof(x)));
/* Receive */
zassert_ok(eth_ivshmem_queue_rx(&q2, &rx_message, &rx_len));
zassert_equal(rx_len, sizeof(x));
zassert_equal(*(int *)rx_message, x);
zassert_ok(eth_ivshmem_queue_rx_complete(&q2));
}
ZTEST(eth_ivshmem_queue_tests, test_send_receive_both_directions)
{
/* Send q1 */
int q1_tx_data = 42;
zassert_ok(queue_tx(&q1, &q1_tx_data, sizeof(q1_tx_data)));
/* Send q2 */
int q2_tx_data = 21;
zassert_ok(queue_tx(&q2, &q2_tx_data, sizeof(q2_tx_data)));
/* Receive q2 */
zassert_ok(eth_ivshmem_queue_rx(&q2, &rx_message, &rx_len));
zassert_equal(rx_len, sizeof(q1_tx_data));
zassert_equal(*(int *)rx_message, q1_tx_data);
zassert_ok(eth_ivshmem_queue_rx_complete(&q2));
/* Receive q1 */
zassert_ok(eth_ivshmem_queue_rx(&q1, &rx_message, &rx_len));
zassert_equal(rx_len, sizeof(q2_tx_data));
zassert_equal(*(int *)rx_message, q2_tx_data);
zassert_ok(eth_ivshmem_queue_rx_complete(&q1));
}
ZTEST(eth_ivshmem_queue_tests, test_queue_empty)
{
/* Read with empty queue */
zassert_equal(eth_ivshmem_queue_rx(&q1, &rx_message, &rx_len), -EWOULDBLOCK);
/* Complete with empty queue */
zassert_equal(eth_ivshmem_queue_rx_complete(&q1), -EWOULDBLOCK);
/* TX commit without getting buffer */
zassert_equal(eth_ivshmem_queue_tx_commit_buff(&q1), -EINVAL);
/* Getting a buffer (without committing) should not modify/overflow the queue */
for (int i = 0; i < 100; i++) {
void *data;
zassert_ok(eth_ivshmem_queue_tx_get_buff(&q1, &data, KB(1)));
}
}
ZTEST(eth_ivshmem_queue_tests, test_queue_descriptors_full)
{
/* Fill queue descriptors */
for (int i = 0; i < VRING_DESC_LEN; i++) {
zassert_ok(queue_tx(&q1, &i, sizeof(i)));
}
/* Fail to add another */
int x = 0;
zassert_equal(queue_tx(&q1, &x, sizeof(x)), -ENOBUFS);
/* Read 3 */
for (int i = 0; i < 3; i++) {
zassert_ok(eth_ivshmem_queue_rx(&q2, &rx_message, &rx_len));
zassert_equal(rx_len, sizeof(i));
zassert_equal(*(int *)rx_message, i);
zassert_ok(eth_ivshmem_queue_rx_complete(&q2));
}
/* Can now add 3 more */
for (int i = 0; i < 3; i++) {
zassert_ok(queue_tx(&q1, &i, sizeof(i)));
}
/* Fail to add another */
zassert_equal(queue_tx(&q1, &x, sizeof(x)), -ENOBUFS);
}
ZTEST(eth_ivshmem_queue_tests, test_queue_shmem_full)
{
static uint8_t large_message[KB(1)];
/* Fill queue shmem */
for (int i = 0; i < VRING_DATA_MAX_LEN / sizeof(large_message); i++) {
zassert_ok(queue_tx(&q1, large_message, sizeof(large_message)));
}
/* Fail to add another */
zassert_equal(queue_tx(&q1, large_message, sizeof(large_message)), -ENOBUFS);
/* Read 1 */
zassert_ok(eth_ivshmem_queue_rx(&q2, &rx_message, &rx_len));
zassert_equal(rx_len, sizeof(large_message));
zassert_ok(eth_ivshmem_queue_rx_complete(&q2));
/* Can now add 1 more */
zassert_ok(queue_tx(&q1, large_message, sizeof(large_message)));
/* Fail to add another */
zassert_equal(queue_tx(&q1, large_message, sizeof(large_message)), -ENOBUFS);
}
ZTEST_SUITE(eth_ivshmem_queue_tests, NULL, NULL, test_setup, NULL, NULL);