* [PATCH] iddp-sendrecv: Make it configurable
@ 2024-08-18 11:12 Richard Weinberger
2024-08-22 9:22 ` Jan Kiszka
0 siblings, 1 reply; 3+ messages in thread
From: Richard Weinberger @ 2024-08-18 11:12 UTC (permalink / raw)
To: xenomai; +Cc: upstream+xenomai, Richard Weinberger
By making it configurable, iddp-sendrecv can act as a powerful
tool to debug IDDP related issues in Xenomai.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
demo/posix/cobalt/iddp-sendrecv.c | 193 +++++++++++++++++++++++++-----
1 file changed, 164 insertions(+), 29 deletions(-)
diff --git a/demo/posix/cobalt/iddp-sendrecv.c b/demo/posix/cobalt/iddp-sendrecv.c
index 6cec083a4..e2ee9ce15 100644
--- a/demo/posix/cobalt/iddp-sendrecv.c
+++ b/demo/posix/cobalt/iddp-sendrecv.c
@@ -26,6 +26,7 @@
* optional.
*/
+#include <argp.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -37,7 +38,15 @@
#include <rtdm/ipc.h>
#include <boilerplate/ancillaries.h>
-pthread_t svtid, cltid;
+#define MODE_SERVER 0x1
+#define MODE_CLIENT 0x2
+
+static pthread_t svtid, cltid;
+static int mode;
+static int send_delay_ms;
+static int send_timeout_ms;
+static int max_messages;
+static size_t poolsz = SIZE_MAX;
#define IDDP_SVPORT 12
#define IDDP_CLPORT 13
@@ -71,24 +80,26 @@ static void *server(void *arg)
{
struct sockaddr_ipc saddr, claddr;
socklen_t addrlen;
+ unsigned int i;
char buf[128];
- size_t poolsz;
int ret, s;
s = socket(AF_RTIPC, SOCK_DGRAM, IPCPROTO_IDDP);
if (s < 0)
fail("socket");
- /*
- * Set a local 32k pool for the server endpoint. Memory needed
- * to convey datagrams will be pulled from this pool, instead
- * of Xenomai's system pool.
- */
- poolsz = 32768; /* bytes */
- ret = setsockopt(s, SOL_IDDP, IDDP_POOLSZ,
- &poolsz, sizeof(poolsz));
- if (ret)
- fail("setsockopt");
+ if (poolsz) {
+ /*
+ * Set a local pool for the server endpoint. Memory needed
+ * to convey datagrams will be pulled from this pool, instead
+ * of Xenomai's system pool.
+ */
+ poolsz *= 1024; /* bytes */
+ ret = setsockopt(s, SOL_IDDP, IDDP_POOLSZ,
+ &poolsz, sizeof(poolsz));
+ if (ret)
+ fail("setsockopt");
+ }
saddr.sipc_family = AF_RTIPC;
saddr.sipc_port = IDDP_SVPORT;
@@ -96,7 +107,7 @@ static void *server(void *arg)
if (ret)
fail("bind");
- for (;;) {
+ for (i = 0;;) {
addrlen = sizeof(saddr);
ret = recvfrom(s, buf, sizeof(buf), 0,
(struct sockaddr *)&claddr, &addrlen);
@@ -106,8 +117,15 @@ static void *server(void *arg)
}
printf("%s: received %d bytes, \"%.*s\" from port %d\n",
__FUNCTION__, ret, ret, buf, claddr.sipc_port);
+
+ if (max_messages && ++i >= max_messages) {
+ printf("%s: stop receiving after %u messages\n",
+ __FUNCTION__, i);
+ goto out;
+ }
}
+out:
return NULL;
}
@@ -121,6 +139,16 @@ static void *client(void *arg)
if (s < 0)
fail("socket");
+ if (send_timeout_ms) {
+ struct timeval tv;
+
+ tv.tv_sec = send_timeout_ms / 1000;
+ tv.tv_usec = (send_timeout_ms % 1000) * 1000;
+ ret = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+ if (ret)
+ fail("setsockopt");
+ }
+
clsaddr.sipc_family = AF_RTIPC;
clsaddr.sipc_port = IDDP_CLPORT;
ret = bind(s, (struct sockaddr *)&clsaddr, sizeof(clsaddr));
@@ -146,26 +174,19 @@ static void *client(void *arg)
* iterations.
*/
ts.tv_sec = 0;
- ts.tv_nsec = 500000000; /* 500 ms */
+ if (!send_delay_ms)
+ send_delay_ms = 500;
+ ts.tv_nsec = send_delay_ms * 1000000UL;
clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL);
}
return NULL;
}
-int main(int argc, char **argv)
+static void run_server(void)
{
struct sched_param svparam = {.sched_priority = 71 };
- struct sched_param clparam = {.sched_priority = 70 };
- pthread_attr_t svattr, clattr;
- sigset_t set;
- int sig;
-
- sigemptyset(&set);
- sigaddset(&set, SIGINT);
- sigaddset(&set, SIGTERM);
- sigaddset(&set, SIGHUP);
- pthread_sigmask(SIG_BLOCK, &set, NULL);
+ pthread_attr_t svattr;
pthread_attr_init(&svattr);
pthread_attr_setdetachstate(&svattr, PTHREAD_CREATE_JOINABLE);
@@ -176,6 +197,12 @@ int main(int argc, char **argv)
errno = pthread_create(&svtid, &svattr, &server, NULL);
if (errno)
fail("pthread_create");
+}
+
+static void run_client(void)
+{
+ struct sched_param clparam = {.sched_priority = 70 };
+ pthread_attr_t clattr;
pthread_attr_init(&clattr);
pthread_attr_setdetachstate(&clattr, PTHREAD_CREATE_JOINABLE);
@@ -186,12 +213,120 @@ int main(int argc, char **argv)
errno = pthread_create(&cltid, &clattr, &client, NULL);
if (errno)
fail("pthread_create");
+}
+
+static error_t parse_opt (int key, char *arg, struct argp_state *state)
+{
+ switch (key) {
+ case 's':
+ mode |= MODE_SERVER;
+ break;
+ case 'c':
+ mode |= MODE_CLIENT;
+ break;
+ case 'd':
+ send_delay_ms = atoi(arg);
+ if (send_delay_ms < 0)
+ argp_usage(state);
+ break;
+ case 't':
+ send_timeout_ms = atoi(arg);
+ if (send_timeout_ms < 0)
+ argp_usage(state);
+ break;
+ case 'm':
+ max_messages = atoi(arg);
+ if (max_messages < 0)
+ argp_usage(state);
+ break;
+ case 'z':
+ poolsz = atoi(arg);
+ if ((int)poolsz < 0)
+ argp_usage(state);
+ break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+
+ return 0;
+}
+
+static struct argp_option options[] = {
+ {"server", 's', 0, 0, "Start an IDDP server" },
+ {"client", 'c', 0, 0, "Start an IDDP client" },
+ {"send-delay", 'd', "DLY", 0, "Delay in ms between messages sent by the client" },
+ {"send-timeout",'t', "STO", 0, "Send timeout in ms in client" },
+ {"max-msg", 'm', "MAX", 0, "Maximum number of messages consumed by the server" },
+ {"pool-size", 'z', "PSZ", 0, "Size of receive pool in KiB, specify 0 to use system pool" },
+ { 0 }
+};
+
+static struct argp argp = {
+ options,
+ parse_opt,
+ NULL,
+ NULL,
+};
+
+int main(int argc, char *argv[])
+{
+ sigset_t set;
+ int sig, ret;
+
+ ret = argp_parse(&argp, argc, argv, 0, 0, NULL);
+ if (ret) {
+ return 1;
+ }
+
+ if (!mode)
+ mode = MODE_SERVER | MODE_CLIENT;
+
+ if (send_delay_ms && !(mode & MODE_CLIENT)) {
+ fprintf(stderr, "--send-delay works only with --client\n");
+ return 1;
+ }
+
+ if (send_timeout_ms && !(mode & MODE_CLIENT)) {
+ fprintf(stderr, "--send-timeout works only with --client\n");
+ return 1;
+ }
+
+ if (max_messages && !(mode & MODE_SERVER)) {
+ fprintf(stderr, "--max-msg works only with --server\n");
+ return 1;
+ }
+
+ if (poolsz != SIZE_MAX) {
+ if (!(mode & MODE_SERVER)) {
+ fprintf(stderr, "--pool-size works only with --server\n");
+ return 1;
+ }
+ } else {
+ poolsz = 32; /* 32KiB default */
+ }
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGTERM);
+ sigaddset(&set, SIGHUP);
+ pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+ if (mode & MODE_SERVER)
+ run_server();
+ if (mode & MODE_CLIENT)
+ run_client();
__STD(sigwait(&set, &sig));
- pthread_cancel(svtid);
- pthread_cancel(cltid);
- pthread_join(svtid, NULL);
- pthread_join(cltid, NULL);
+
+ if (mode & MODE_SERVER) {
+ pthread_cancel(svtid);
+ pthread_join(svtid, NULL);
+ }
+
+ if (mode & MODE_CLIENT) {
+ pthread_cancel(cltid);
+ pthread_join(cltid, NULL);
+ }
return 0;
}
--
2.39.2
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] iddp-sendrecv: Make it configurable
2024-08-18 11:12 [PATCH] iddp-sendrecv: Make it configurable Richard Weinberger
@ 2024-08-22 9:22 ` Jan Kiszka
2024-08-22 9:31 ` Richard Weinberger
0 siblings, 1 reply; 3+ messages in thread
From: Jan Kiszka @ 2024-08-22 9:22 UTC (permalink / raw)
To: Richard Weinberger, xenomai; +Cc: upstream+xenomai
On 18.08.24 13:12, Richard Weinberger wrote:
> By making it configurable, iddp-sendrecv can act as a powerful
> tool to debug IDDP related issues in Xenomai.
>
> Signed-off-by: Richard Weinberger <richard@nod.at>
> ---
> demo/posix/cobalt/iddp-sendrecv.c | 193 +++++++++++++++++++++++++-----
> 1 file changed, 164 insertions(+), 29 deletions(-)
>
> diff --git a/demo/posix/cobalt/iddp-sendrecv.c b/demo/posix/cobalt/iddp-sendrecv.c
> index 6cec083a4..e2ee9ce15 100644
> --- a/demo/posix/cobalt/iddp-sendrecv.c
> +++ b/demo/posix/cobalt/iddp-sendrecv.c
> @@ -26,6 +26,7 @@
> * optional.
> */
>
> +#include <argp.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> @@ -37,7 +38,15 @@
> #include <rtdm/ipc.h>
> #include <boilerplate/ancillaries.h>
>
> -pthread_t svtid, cltid;
> +#define MODE_SERVER 0x1
> +#define MODE_CLIENT 0x2
> +
> +static pthread_t svtid, cltid;
> +static int mode;
> +static int send_delay_ms;
> +static int send_timeout_ms;
> +static int max_messages;
> +static size_t poolsz = SIZE_MAX;
>
> #define IDDP_SVPORT 12
> #define IDDP_CLPORT 13
> @@ -71,24 +80,26 @@ static void *server(void *arg)
> {
> struct sockaddr_ipc saddr, claddr;
> socklen_t addrlen;
> + unsigned int i;
> char buf[128];
> - size_t poolsz;
> int ret, s;
>
> s = socket(AF_RTIPC, SOCK_DGRAM, IPCPROTO_IDDP);
> if (s < 0)
> fail("socket");
>
> - /*
> - * Set a local 32k pool for the server endpoint. Memory needed
> - * to convey datagrams will be pulled from this pool, instead
> - * of Xenomai's system pool.
> - */
> - poolsz = 32768; /* bytes */
> - ret = setsockopt(s, SOL_IDDP, IDDP_POOLSZ,
> - &poolsz, sizeof(poolsz));
> - if (ret)
> - fail("setsockopt");
> + if (poolsz) {
> + /*
> + * Set a local pool for the server endpoint. Memory needed
> + * to convey datagrams will be pulled from this pool, instead
> + * of Xenomai's system pool.
> + */
> + poolsz *= 1024; /* bytes */
> + ret = setsockopt(s, SOL_IDDP, IDDP_POOLSZ,
> + &poolsz, sizeof(poolsz));
> + if (ret)
> + fail("setsockopt");
> + }
>
> saddr.sipc_family = AF_RTIPC;
> saddr.sipc_port = IDDP_SVPORT;
> @@ -96,7 +107,7 @@ static void *server(void *arg)
> if (ret)
> fail("bind");
>
> - for (;;) {
> + for (i = 0;;) {
> addrlen = sizeof(saddr);
> ret = recvfrom(s, buf, sizeof(buf), 0,
> (struct sockaddr *)&claddr, &addrlen);
> @@ -106,8 +117,15 @@ static void *server(void *arg)
> }
> printf("%s: received %d bytes, \"%.*s\" from port %d\n",
> __FUNCTION__, ret, ret, buf, claddr.sipc_port);
> +
> + if (max_messages && ++i >= max_messages) {
> + printf("%s: stop receiving after %u messages\n",
> + __FUNCTION__, i);
> + goto out;
Why using a jump to a plain return statement?
> + }
> }
>
> +out:
> return NULL;
> }
>
> @@ -121,6 +139,16 @@ static void *client(void *arg)
> if (s < 0)
> fail("socket");
>
> + if (send_timeout_ms) {
> + struct timeval tv;
> +
> + tv.tv_sec = send_timeout_ms / 1000;
> + tv.tv_usec = (send_timeout_ms % 1000) * 1000;
> + ret = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
> + if (ret)
> + fail("setsockopt");
> + }
> +
> clsaddr.sipc_family = AF_RTIPC;
> clsaddr.sipc_port = IDDP_CLPORT;
> ret = bind(s, (struct sockaddr *)&clsaddr, sizeof(clsaddr));
> @@ -146,26 +174,19 @@ static void *client(void *arg)
> * iterations.
> */
> ts.tv_sec = 0;
> - ts.tv_nsec = 500000000; /* 500 ms */
> + if (!send_delay_ms)
> + send_delay_ms = 500;
> + ts.tv_nsec = send_delay_ms * 1000000UL;
> clock_nanosleep(CLOCK_REALTIME, 0, &ts, NULL);
> }
>
> return NULL;
> }
>
> -int main(int argc, char **argv)
> +static void run_server(void)
> {
> struct sched_param svparam = {.sched_priority = 71 };
> - struct sched_param clparam = {.sched_priority = 70 };
> - pthread_attr_t svattr, clattr;
> - sigset_t set;
> - int sig;
> -
> - sigemptyset(&set);
> - sigaddset(&set, SIGINT);
> - sigaddset(&set, SIGTERM);
> - sigaddset(&set, SIGHUP);
> - pthread_sigmask(SIG_BLOCK, &set, NULL);
> + pthread_attr_t svattr;
>
> pthread_attr_init(&svattr);
> pthread_attr_setdetachstate(&svattr, PTHREAD_CREATE_JOINABLE);
> @@ -176,6 +197,12 @@ int main(int argc, char **argv)
> errno = pthread_create(&svtid, &svattr, &server, NULL);
> if (errno)
> fail("pthread_create");
> +}
> +
> +static void run_client(void)
> +{
> + struct sched_param clparam = {.sched_priority = 70 };
> + pthread_attr_t clattr;
>
> pthread_attr_init(&clattr);
> pthread_attr_setdetachstate(&clattr, PTHREAD_CREATE_JOINABLE);
> @@ -186,12 +213,120 @@ int main(int argc, char **argv)
> errno = pthread_create(&cltid, &clattr, &client, NULL);
> if (errno)
> fail("pthread_create");
> +}
> +
> +static error_t parse_opt (int key, char *arg, struct argp_state *state)
> +{
> + switch (key) {
> + case 's':
> + mode |= MODE_SERVER;
> + break;
> + case 'c':
> + mode |= MODE_CLIENT;
> + break;
> + case 'd':
> + send_delay_ms = atoi(arg);
> + if (send_delay_ms < 0)
> + argp_usage(state);
> + break;
> + case 't':
> + send_timeout_ms = atoi(arg);
> + if (send_timeout_ms < 0)
> + argp_usage(state);
> + break;
> + case 'm':
> + max_messages = atoi(arg);
> + if (max_messages < 0)
> + argp_usage(state);
> + break;
> + case 'z':
> + poolsz = atoi(arg);
> + if ((int)poolsz < 0)
> + argp_usage(state);
> + break;
> + default:
> + return ARGP_ERR_UNKNOWN;
> + }
> +
> + return 0;
> +}
> +
> +static struct argp_option options[] = {
> + {"server", 's', 0, 0, "Start an IDDP server" },
> + {"client", 'c', 0, 0, "Start an IDDP client" },
> + {"send-delay", 'd', "DLY", 0, "Delay in ms between messages sent by the client" },
> + {"send-timeout",'t', "STO", 0, "Send timeout in ms in client" },
> + {"max-msg", 'm', "MAX", 0, "Maximum number of messages consumed by the server" },
> + {"pool-size", 'z', "PSZ", 0, "Size of receive pool in KiB, specify 0 to use system pool" },
> + { 0 }
> +};
> +
> +static struct argp argp = {
> + options,
> + parse_opt,
> + NULL,
> + NULL,
> +};
> +
> +int main(int argc, char *argv[])
> +{
> + sigset_t set;
> + int sig, ret;
> +
> + ret = argp_parse(&argp, argc, argv, 0, 0, NULL);
> + if (ret) {
> + return 1;
> + }
Braces not really needed here.
> +
> + if (!mode)
> + mode = MODE_SERVER | MODE_CLIENT;
> +
> + if (send_delay_ms && !(mode & MODE_CLIENT)) {
> + fprintf(stderr, "--send-delay works only with --client\n");
> + return 1;
> + }
> +
> + if (send_timeout_ms && !(mode & MODE_CLIENT)) {
> + fprintf(stderr, "--send-timeout works only with --client\n");
> + return 1;
> + }
> +
> + if (max_messages && !(mode & MODE_SERVER)) {
> + fprintf(stderr, "--max-msg works only with --server\n");
> + return 1;
> + }
> +
> + if (poolsz != SIZE_MAX) {
> + if (!(mode & MODE_SERVER)) {
> + fprintf(stderr, "--pool-size works only with --server\n");
> + return 1;
> + }
> + } else {
> + poolsz = 32; /* 32KiB default */
> + }
> +
> + sigemptyset(&set);
> + sigaddset(&set, SIGINT);
> + sigaddset(&set, SIGTERM);
> + sigaddset(&set, SIGHUP);
> + pthread_sigmask(SIG_BLOCK, &set, NULL);
> +
> + if (mode & MODE_SERVER)
> + run_server();
> + if (mode & MODE_CLIENT)
> + run_client();
>
> __STD(sigwait(&set, &sig));
> - pthread_cancel(svtid);
> - pthread_cancel(cltid);
> - pthread_join(svtid, NULL);
> - pthread_join(cltid, NULL);
> +
> + if (mode & MODE_SERVER) {
> + pthread_cancel(svtid);
> + pthread_join(svtid, NULL);
> + }
> +
> + if (mode & MODE_CLIENT) {
> + pthread_cancel(cltid);
> + pthread_join(cltid, NULL);
> + }
>
> return 0;
> }
Thanks for the proposal - but it looks like this tool and
testsuite/smokey/iddp/iddp.c become more similar now. I wonder if they
could be even united so that smokey calls this in specific configuration
for running the tests.
Jan
--
Siemens AG, Technology
Linux Expert Center
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] iddp-sendrecv: Make it configurable
2024-08-22 9:22 ` Jan Kiszka
@ 2024-08-22 9:31 ` Richard Weinberger
0 siblings, 0 replies; 3+ messages in thread
From: Richard Weinberger @ 2024-08-22 9:31 UTC (permalink / raw)
To: Jan Kiszka; +Cc: xenomai, upstream+xenomai
Am Donnerstag, 22. August 2024, 11:22:01 CEST schrieb 'Jan Kiszka' via upstream:
> On 18.08.24 13:12, Richard Weinberger wrote:
> Thanks for the proposal - but it looks like this tool and
> testsuite/smokey/iddp/iddp.c become more similar now. I wonder if they
> could be even united so that smokey calls this in specific configuration
> for running the tests.
Hm, sounds sane.
I can think of a --test option for this.
Thanks,
//richard
--
sigma star gmbh | Eduard-Bodem-Gasse 6, 6020 Innsbruck, AUT
UID/VAT Nr: ATU 66964118 | FN: 374287y
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-08-22 9:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-18 11:12 [PATCH] iddp-sendrecv: Make it configurable Richard Weinberger
2024-08-22 9:22 ` Jan Kiszka
2024-08-22 9:31 ` Richard Weinberger
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.