diff --git a/CMakeLists.txt b/CMakeLists.txt index f581b2c..9a9e45f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,3 +27,5 @@ else() target_sources(app PRIVATE src/dom_cfg/${BOARD}.c) endif() endif() + +target_sources_ifdef(CONFIG_VCHAN_SHELL_CMDS app PRIVATE src/vchan_cmds.c) diff --git a/Kconfig b/Kconfig index 9066531..039ace4 100644 --- a/Kconfig +++ b/Kconfig @@ -111,4 +111,29 @@ config DOM_COVERAGE_ENABLE Enable code coverage with GCOV and enable shell command to print GCOV dump "gcov dump" in console. +config VCHAN_SHELL_CMDS + depends on SHELL + bool "Enable VCHAN echo server shell commands" + help + Enable set of VCHAN echo server shell commands. All data incoming to + channel created by this server will be send back. This is for test + purposes. Server introduces 2 commands: + vchan start [domid] + Start echo server. domid - The peer domain that will be connecting + (0 by default) + vchan stop + Stop server + +if VCHAN_SHELL_CMDS + +config VCHAN_ECHO_BUFFER_SIZE + int "Buffer size for echo server" + default 10 + +config VCHAN_THREAD_STACK_SIZE + int "vchan echo server thread size" + default 2048 + +endif #VCHAN_SHELL_CMDS + source "Kconfig.zephyr" diff --git a/README.rst b/README.rst index 28d3a34..4f17c36 100644 --- a/README.rst +++ b/README.rst @@ -448,3 +448,33 @@ and execute the following command: .. code-block:: console ~ # ping -c 3 192.168.0.2 +RPI5 vchan simple echo server +***************************** + +vchan echo server should be build with Kconfig configuration: + +.. code-block:: text + CONFIG_VCHAN_SHELL_CMDS=y + +Start echo server in zephyr console: + +.. code-block:: console + uart:~$ vchan start 1 + Echo server openad at /local/domain/1/echo + Thread started + +On domd side vchan-node1 tool can be used to communicate with echo server. Send +data to echo server: + +.. code-block:: console + root@raspberrypi5-domd:~# vchan-node1 client write 0 /local/domain/1/echo + seed=1709064173 + +Enter data using keyboard. Stop this utility using Ctrl+C. Read data from +server: + +.. code-block:: console + root@raspberrypi5-domd:~# vchan-node1 client read 0 /local/domain/1/echo + seed=1709068644 + +Received (actually - entered early) symbols will be shown on console. diff --git a/src/vchan_cmds.c b/src/vchan_cmds.c new file mode 100644 index 0000000..c620d67 --- /dev/null +++ b/src/vchan_cmds.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2024 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(vchan_cmd); + +#define ECHO_SERVER_THREAD_PRIO 7 +#define PATH_TEMPLATE "/local/domain/%d/echo" +#define THREAD_NAME "vchan_echo_server" + +static struct k_thread echo_thread; +static struct k_thread *pecho_thread = NULL; +static struct vch_handle handle; + +static K_THREAD_STACK_DEFINE(echo_thread_stack, CONFIG_VCHAN_THREAD_STACK_SIZE); +static volatile int vchan_server_stop = 0; + +static void vchan_echo_server(void *p1, void *p2, void *p3) +{ + struct vch_handle *h = (struct vch_handle *)p1; + int size; + static char buf[CONFIG_VCHAN_ECHO_BUFFER_SIZE]; + + ARG_UNUSED(p2); + ARG_UNUSED(p3); + LOG_DBG("Server started\n"); + while (!vchan_server_stop) { + size = vch_read(h, buf, sizeof(buf)); + if (size > 0) { + vch_write(h, buf, size); + } else { + if (size < 0 && size != -ENOTCONN) { + LOG_ERR("vch_read returned %d\r", size); + } + k_sleep(K_MSEC(500)); + } + } + LOG_DBG("Server stopped\n"); + vch_close(h); +} + +static int vchan_shell_start(const struct shell *sh, size_t argc, char **argv) +{ + int ret; + domid_t domid = 0; + static char path[PATH_MAX]; + + if (pecho_thread) { + shell_warn(sh, "Server already started"); + return 1; + } + if (argv[1]) { + domid = atoi(argv[1]); + } + snprintf(path, PATH_MAX-1, PATH_TEMPLATE, domid); + ret = vch_open(domid, path, 10, 10, &handle); + if (ret) { + shell_error(sh, "vchan open error %d", ret); + goto exit; + } + shell_print(sh, "Echo server openad at %s", path); + vchan_server_stop = 0; + k_thread_create(&echo_thread, echo_thread_stack, K_THREAD_STACK_SIZEOF(echo_thread_stack), + vchan_echo_server, (void *)&handle, NULL, NULL, + ECHO_SERVER_THREAD_PRIO, 0, K_NO_WAIT); + pecho_thread = &echo_thread; + k_thread_name_set(pecho_thread, THREAD_NAME); + +exit: + return ret; +} + +static int vchan_shell_stop(const struct shell *sh, size_t argc, char **argv) +{ + if (!pecho_thread) { + shell_warn(sh, "Server not started"); + return 0; + } + vchan_server_stop = 1; + if (k_thread_join(pecho_thread, K_MSEC(1000))) { + shell_error(sh, "Killing thread"); + k_thread_abort(pecho_thread); + } + pecho_thread = NULL; + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE( + subcmd_vchan, + SHELL_CMD_ARG(start, NULL, + "start echo server.\n" + "\tUsage:\n" + "\tvchan start [domid]\n", + vchan_shell_start, 0, 1), + SHELL_CMD_ARG(stop, NULL, + "stop server.\n", + vchan_shell_stop, 0, 0), + SHELL_SUBCMD_SET_END); + +SHELL_CMD_ARG_REGISTER(vchan, &subcmd_vchan, "VCHAN commands", NULL, 2, 0);