All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.