Skip to contentSkip to conversation

lib/tst_test.c: add 'needs_drivers' option with tst_check_drivers cmd

RFC PATCH Superseded Alexey Kodanev 3 participants 18 messages Aug 9, 2018 – Aug 16, 2018 Library code

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/4 lib/tst_test.c: add 'needs_drivers' option with tst_check_drivers cmd

The drivers are checked with modprobe. If modrpobe is not available on the system, the checks are silently skipped.

---
 include/tst_test.h                |    5 +++++
 lib/tst_test.c                    |   26 ++++++++++++++++++++++++++
 testcases/lib/.gitignore          |    1 +
 testcases/lib/Makefile            |    2 +-
 testcases/lib/tst_check_drivers.c |   24 ++++++++++++++++++++++++
 5 files changed, 57 insertions(+), 1 deletions(-)
 create mode 100644 testcases/lib/tst_check_drivers.c
include/tst_test.h +5 -0
index 98dacf3..221796d 100644
@@ -170,6 +170,9 @@ struct tst_test {
 
 	/* NULL terminated array of resource file names */
 	const char *const *resource_files;
+
+	/* NULL terminated array of needed kernel drivers */
+	const char * const *needs_drivers;
 };
 
 /*
@@ -219,6 +222,8 @@ const char *tst_strstatus(int status);
 
 void tst_set_timeout(int timeout);
 
+int tst_check_drivers(void);
+
 #ifndef TST_NO_DEFAULT_MAIN
 
 static struct tst_test test;
lib/tst_test.c +26 -0
index 2f3d357..6cb74cf 100644
@@ -645,6 +645,29 @@ static int needs_tmpdir(void)
 	       tst_test->needs_checkpoints;
 }
 
+int tst_check_drivers(void)
+{
+	const char *name;
+	int i, res;
+
+	for (i = 0; (name = tst_test->needs_drivers[i]); ++i) {
+		const char * const argv[] = { "modprobe", name, NULL };
+
+		res = tst_run_cmd_(NULL, argv, "/dev/null", "/dev/null", 1);
+		if (res == 255)
+			return res; /* it looks like modprobe not available */
+		if (res) {
+			if (tst_test->test || tst_test->test_all) {
+				tst_brk(TCONF, "%s driver not available", name);
+			} else {
+				fprintf(stderr, "%s", name);
+				return res;
+			}
+		}
+	}
+	return 0;
+}
+
 static void copy_resources(void)
 {
 	unsigned int i;
@@ -767,6 +790,9 @@ static void do_setup(int argc, char *argv[])
 	if (tst_test->min_kver)
 		check_kver();
 
+	if (tst_test->needs_drivers)
+		tst_check_drivers();
+
 	if (tst_test->format_device)
 		tst_test->needs_device = 1;
 
testcases/lib/.gitignore +1 -0
index a9034e4..d83a48e 100644
@@ -1,5 +1,6 @@
 /tst_sleep
 /tst_random
+/tst_check_drivers
 /tst_checkpoint
 /tst_rod
 /tst_kvcmp
testcases/lib/Makefile +1 -1
index 3547e16..e1dea3b 100644
@@ -28,6 +28,6 @@ INSTALL_TARGETS		:= *.sh
 
 MAKE_TARGETS		:= tst_sleep tst_random tst_checkpoint tst_rod tst_kvcmp\
 			   tst_device tst_net_iface_prefix tst_net_ip_prefix tst_net_vars\
-			   tst_getconf tst_supported_fs
+			   tst_getconf tst_supported_fs tst_check_drivers
 
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
testcases/lib/tst_check_drivers.c new file +24 -0
new file mode 100644
index 0000000..3f722f2
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright (c) 2018 Oracle and/or its affiliates. All Rights Reserved.
+ */
+
+#include <stdio.h>
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+
+struct tst_test *tst_test;
+
+int main(int argc, const char *argv[])
+{
+	if (argc < 2) {
+		fprintf(stderr, "Please provide kernel driver list\n");
+		return 1;
+	}
+
+	struct tst_test test = {
+		.needs_drivers = &argv[1]
+	};
+
+	tst_test = &test;
+	return tst_check_drivers();
+}
Signature · 1 line
1.7.1
#1 lore raw

RFC PATCH 2/4 lib/tst_test.sh: add TST_NEEDS_DRIVERS parameter

The drivers are checked with tst_check_drivers.

---
 testcases/lib/tst_test.sh |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
testcases/lib/tst_test.sh +11 -0
index e553b49..30f75b5 100644
@@ -285,6 +285,15 @@ tst_check_cmds()
 	return 0
 }
 
+tst_test_drivers()
+{
+	local drv="$(tst_check_drivers $@ 2>&1)"
+
+	if [ -n "$drv" ]; then
+		tst_brk TCONF "'$drv' driver not found"
+	fi
+}
+
 tst_is_int()
 {
 	[ "$1" -eq "$1" ] 2>/dev/null
@@ -332,6 +341,7 @@ tst_run()
 			OPTS|USAGE|PARSE_ARGS|POS_ARGS);;
 			NEEDS_ROOT|NEEDS_TMPDIR|NEEDS_DEVICE|DEVICE);;
 			NEEDS_CMDS|NEEDS_MODULE|MODPATH|DATAROOT);;
+			NEEDS_DRIVERS);;
 			IPV6|IPVER|TEST_DATA|TEST_DATA_IFS);;
 			RETRY_FUNC|RETRY_FN_EXP_BACKOFF);;
 			*) tst_res TWARN "Reserved variable TST_$_tst_i used!";;
@@ -369,6 +379,7 @@ tst_run()
 	fi
 
 	tst_test_cmds $TST_NEEDS_CMDS
+	tst_test_drivers $TST_NEEDS_DRIVERS
 
 	if [ -n "$TST_MIN_KVER" ]; then
 		tst_kvcmp -lt "$TST_MIN_KVER" && \
Signature · 1 line
1.7.1
#2 lore raw

RFC PATCH 2/4 lib/tst_test.sh: add TST_NEEDS_DRIVERS parameter

Hi Alexey,

Quoted 3 lines

The drivers are checked with tst_check_drivers.

Quoted 4 lines

---

 testcases/lib/tst_test.sh |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

Again, some docs in doc/test-writing-guidelines.txt would be nice.

Kind regards,
Petr

#3 lore raw

RFC PATCH 2/4 lib/tst_test.sh: add TST_NEEDS_DRIVERS parameter

In reply to Alexey Kodanev

Hi Alexey,

testcases/lib/tst_test.sh tst_run() · line 382

Quoted 7 lines

The drivers are checked with tst_check_drivers.

---

testcases/lib/tst_test.sh +1 -0
 	tst_test_cmds $TST_NEEDS_CMDS
+	tst_test_drivers $TST_NEEDS_DRIVERS

I'm sorry here must be some fix:
+ if [ -n "$TST_NEEDS_DRIVERS" ]; then
+ tst_test_drivers $TST_NEEDS_DRIVERS
+ fi

Otherwise tests without $TST_NEEDS_DRIVERS TCONF:
tcp_ipsec_vti 1 TCONF: 'Please provide kernel driver list' driver not found

Kind regards,
Petr

#4 lore raw

RFC PATCH 2/4 lib/tst_test.sh: add TST_NEEDS_DRIVERS parameter

Quoted 15 lines · Petr Vorel

Hi Alexey,

testcases/lib/tst_test.sh tst_run() · line 382

Quoted 7 lines

The drivers are checked with tst_check_drivers.

---

testcases/lib/tst_test.sh +1 -0
 	tst_test_cmds $TST_NEEDS_CMDS
+	tst_test_drivers $TST_NEEDS_DRIVERS

I'm sorry here must be some fix:

(quoted diff) +3 -0
+	if [ -n "$TST_NEEDS_DRIVERS" ]; then
+		tst_test_drivers $TST_NEEDS_DRIVERS
+	fi
Quoted 2 lines

Otherwise tests without $TST_NEEDS_DRIVERS TCONF:
tcp_ipsec_vti 1 TCONF: 'Please provide kernel driver list' driver not found

Hi Petr,

Yeah, noticed that too, so I've added the check to tst_test_drivers(), it should just return if there are no arguments passed.

Thanks,
Alexey

#5 lore raw

RFC PATCH 3/4 lib/tst_test.sh: add TST_RTNL_CHK() helper function

In reply to Alexey Kodanev

It should parse iproute commands output and exit the test with TCONF if there are certain messages returned from iproute/RTNETLINK.

---
 testcases/lib/tst_test.sh |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)
testcases/lib/tst_test.sh +16 -0
index 30f75b5..73dcdfb 100644
@@ -202,6 +202,22 @@ TST_RETRY_FUNC()
 	return $2
 }
 
+TST_RTNL_CHK()
+{
+	local msg1="RTNETLINK answers: Function not implemented"
+	local msg2="RTNETLINK answers: Operation not supported"
+	local output="$($@ 2>&1 || echo 'LTP_ERR')"
+	local msg
+
+	echo "$output" | grep -q "LTP_ERR" || return 0
+
+	for msg in "$msg1" "$msg2"; do
+		echo "$output" | grep -q "$msg" && tst_brk TCONF "'$@': $msg"
+	done
+
+	tst_brk TBROK "$@ failed: $output"
+}
+
 tst_umount()
 {
 	local device="$1"
Signature · 1 line
1.7.1
#6 lore raw

RFC PATCH 3/4 lib/tst_test.sh: add TST_RTNL_CHK() helper function

Hi Alexey,

Quoted 4 lines

It should parse iproute commands output and exit the test with TCONF if there are certain messages returned from iproute/RTNETLINK.

Quoted 3 lines
---
 testcases/lib/tst_test.sh |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

Kind regards,
Petr

#7 lore raw

RFC PATCH 4/4 network/ipsec: replace ipsec_try() with TST_RTNL_CHK()

In reply to Alexey Kodanev
---
 testcases/network/stress/ipsec/ipsec_lib.sh |   21 +++------------------
 1 files changed, 3 insertions(+), 18 deletions(-)
testcases/network/stress/ipsec/ipsec_lib.sh +3 -18
index aedba9b..f850166 100644
@@ -157,21 +157,6 @@ ipsec_set_algoline()
 	esac
 }
 
-ipsec_try()
-{
-	local output="$($@ 2>&1 || echo 'TERR')"
-
-	if echo "$output" | grep -q "TERR"; then
-		echo "$output" | grep -q \
-			'RTNETLINK answers: Function not implemented' && \
-			tst_brk TCONF "'$@': not implemented"
-		echo "$output" | grep -q \
-			'RTNETLINK answers: Operation not supported' && \
-			tst_brk TCONF "'$@': not supported (maybe missing 'ip${TST_IPV6}_vti' kernel module)"
-		tst_brk TBROK "$@ failed: $output"
-	fi
-}
-
 # tst_ipsec target src_addr dst_addr: config ipsec
 #
 # target: target of the configuration host ( lhost / rhost )
@@ -195,7 +180,7 @@ tst_ipsec()
 	if [ $target = lhost ]; then
 		local spi_1="0x$SPI"
 		local spi_2="0x$(( $SPI + 1 ))"
-		ipsec_try ip xfrm state add src $src dst $dst spi $spi_1 \
+		TST_RTNL_CHK xfrm state add src $src dst $dst spi $spi_1 \
 			$p $ALG mode $mode sel src $src dst $dst
 		ROD ip xfrm state add src $dst dst $src spi $spi_2 \
 			$p $ALG mode $mode sel src $dst dst $src
@@ -257,12 +242,12 @@ tst_ipsec_vti()
 	cleanup_vti=$vti
 
 	if [ $target = lhost ]; then
-		ipsec_try ip li add $vti $type local $src remote $dst $key $d
+		TST_RTNL_CHK ip li add $vti $type local $src remote $dst $key $d
 		ROD ip li set $vti up
 
 		local spi_1="spi 0x$SPI"
 		local spi_2="spi 0x$(( $SPI + 1 ))"
-		ipsec_try $ipx st add $o_dir $p $spi_1 $ALG $m
+		TST_RTNL_CHK $ipx st add $o_dir $p $spi_1 $ALG $m
 		ROD $ipx st add $i_dir $p $spi_2 $ALG $m
 		ROD $ipx po add dir out tmpl $o_dir $p $m $mrk
 		ROD $ipx po add dir in tmpl $i_dir $p $m $mrk
Signature · 1 line
1.7.1
#9 lore raw

RFC PATCH 2/2 netstress: Update help for -m behavior

In reply to Alexey Kodanev

Hi Alexey,

Quoted 7 lines
Quoted 6 lines
Quoted 6 lines

Hi Petr,

Since the server waits for requests from the client, the timeout value for UDP/DCCP is the same as for the other protocols. Also the server starts earlier than the client, so it should wait some time to get the client requests.

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

I've changed the client side only because either request from the client or reply from the server might be lost.

Thanks for your explanation.
I mean: UDP itself is the only protocol which don't support listen() so netstress server using UDP timeouts after some time. The default is 100ms.

Hmm, for the server the default should be 60 sec. Does it timeout earlier?

Yes. The timeout is affected by value of -m. Thats' what I meant by my previous:

$ date +"%T.%3N"; testcases/network/netstress/netstress -m 1 -T udp; date +"%T.%3N"
15:52:34.501
tst_test.c:1015: INFO: Timeout per run is 0h 05m 00s
The timeout is actually 1ms. Try it with -m 1000 and it'll be indeed 1s
netstress.c:917: INFO: max requests '3'
netstress.c:944: INFO: using UDP
netstress.c:676: INFO: assigning a name to the server socket...
netstress.c:683: INFO: bind to port 47728
netstress.c:575: FAIL: recv failed, sock '3'
netstress.c:642: BROK: Server closed
...
15:52:34.516

This is caused by udp/udp_lite not using listen(), but maybe is should be at least mentioned in help (if wanted behavior).

Kind regards,
Petr

#10 lore raw

RFC PATCH 2/2 netstress: Update help for -m behavior

Quoted 32 lines · Petr Vorel

Hi Alexey,

Quoted 7 lines
Quoted 6 lines
Quoted 6 lines

Hi Petr,

Since the server waits for requests from the client, the timeout value for UDP/DCCP is the same as for the other protocols. Also the server starts earlier than the client, so it should wait some time to get the client requests.

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

I've changed the client side only because either request from the client or reply from the server might be lost.

Thanks for your explanation.
I mean: UDP itself is the only protocol which don't support listen() so netstress server using UDP timeouts after some time. The default is 100ms.

Hmm, for the server the default should be 60 sec. Does it timeout earlier?

Yes. The timeout is affected by value of -m. Thats' what I meant by my previous:

$ date +"%T.%3N"; testcases/network/netstress/netstress -m 1 -T udp; date +"%T.%3N"
15:52:34.501
tst_test.c:1015: INFO: Timeout per run is 0h 05m 00s
The timeout is actually 1ms. Try it with -m 1000 and it'll be indeed 1s
netstress.c:917: INFO: max requests '3'
netstress.c:944: INFO: using UDP
netstress.c:676: INFO: assigning a name to the server socket...
netstress.c:683: INFO: bind to port 47728
netstress.c:575: FAIL: recv failed, sock '3'
netstress.c:642: BROK: Server closed
...
15:52:34.516
Quoted 2 lines

This is caused by udp/udp_lite not using listen(), but maybe is should be at least mentioned in help (if wanted behavior).

Agree.

Thanks,
Alexey

#11 lore raw

PATCH v2 1/1 network/route: Rewrite route-change-dst into new API

In reply to Alexey Kodanev

Hi Alexey,

Quoted 14 lines · Alexey Kodanev

...

Quoted 11 lines

Review

Quoted 1 line
(quoted diff) +1 -0
+	tst_netload -T udp -r 1 -a 1 -H $addr

Unfortunately, it won't work this way. tst_netload is using requests/response model for UDP. You have to make sure the server can send responses.

Also, netstress UDP/DCCP client allows to pass 'max_etime_cnt' (12) failed requests after which it will double receive timeout, starting from 100ms up to 3.2s. This is about 30 sec if there is no connection. With a single request or below max_etime_cnt + 1 value it will always pass. I guess we need to set the proper request parameter limit for UDP/DCCP protocol or check whether the number of timeout errors is equal or greater than the number of requests.

Quoted 2 lines

Applied the fix for this bug:
4ceb442b56ad ("netstress: handle timeout errors for a small number of requests")

Thanks for your explanation and netstress fix.

I'll try to implement it in C, using rtnetlink as we've been talking about in the past. That should stress the system more than using user space tools. Maybe for the start with just changing interfaces (without checking by sending packets).

Kind regards,
Petr

#12 lore raw

RFC PATCH 1/4 lib/tst_test.c: add 'needs_drivers' option with tst_check_drivers cmd

In reply to Alexey Kodanev

Hi Alexey,

Quoted 1 line

The drivers are checked with modprobe. If modrpobe is not available

^ typo modrpobe

Quoted 3 lines

on the system, the checks are silently skipped.

Quoted 8 lines
---
 include/tst_test.h                |    5 +++++
 lib/tst_test.c                    |   26 ++++++++++++++++++++++++++
 testcases/lib/.gitignore          |    1 +
 testcases/lib/Makefile            |    2 +-
 testcases/lib/tst_check_drivers.c |   24 ++++++++++++++++++++++++
 5 files changed, 57 insertions(+), 1 deletions(-)
 create mode 100644 testcases/lib/tst_check_drivers.c

It'd be nice to add some docs into doc/test-writing-guidelines.txt.

Kind regards,
Petr

#13 lore raw

RFC PATCH 1/4 lib/tst_test.c: add 'needs_drivers' option with tst_check_drivers cmd

Quoted 17 lines · Petr Vorel

Hi Alexey,

Quoted 1 line

The drivers are checked with modprobe. If modrpobe is not available

^ typo modrpobe>> on the system, the checks are silently skipped.

Quoted 1 line
Quoted 8 lines
---
 include/tst_test.h                |    5 +++++
 lib/tst_test.c                    |   26 ++++++++++++++++++++++++++
 testcases/lib/.gitignore          |    1 +
 testcases/lib/Makefile            |    2 +-
 testcases/lib/tst_check_drivers.c |   24 ++++++++++++++++++++++++
 5 files changed, 57 insertions(+), 1 deletions(-)
 create mode 100644 testcases/lib/tst_check_drivers.c
Quoted 2 lines

It'd be nice to add some docs into doc/test-writing-guidelines.txt.

Hi Petr,

Sure, thanks for review!

BTW, it feels like tst_kernel.h is the better place for tst_check_drivers().

Thanks,
Alexey

#14 lore raw

RFC PATCH 1/4 lib/tst_test.c: add 'needs_drivers' option with tst_check_drivers cmd

In reply to Alexey Kodanev

Hi!

Quoted 43 lines
include/tst_test.h +5 -0
index 98dacf3..221796d 100644
@@ -170,6 +170,9 @@ struct tst_test {
 
 	/* NULL terminated array of resource file names */
 	const char *const *resource_files;
+
+	/* NULL terminated array of needed kernel drivers */
+	const char * const *needs_drivers;
 };
 
 /*
@@ -219,6 +222,8 @@ const char *tst_strstatus(int status);
 
 void tst_set_timeout(int timeout);
 
+int tst_check_drivers(void);
+
 #ifndef TST_NO_DEFAULT_MAIN
 
 static struct tst_test test;
lib/tst_test.c +12 -0
index 2f3d357..6cb74cf 100644
@@ -645,6 +645,29 @@ static int needs_tmpdir(void)
 	       tst_test->needs_checkpoints;
 }
 
+int tst_check_drivers(void)
+{
+	const char *name;
+	int i, res;
+
+	for (i = 0; (name = tst_test->needs_drivers[i]); ++i) {
+		const char * const argv[] = { "modprobe", name, NULL };
+
+		res = tst_run_cmd_(NULL, argv, "/dev/null", "/dev/null", 1);
+		if (res == 255)
+			return res; /* it looks like modprobe not available */
+		if (res) {

lib/tst_test.c static int needs_tmpdir(void) · line 669

Quoted 10 lines
lib/tst_test.c +10 -0
+			if (tst_test->test || tst_test->test_all) {
+				tst_brk(TCONF, "%s driver not available", name);
+			} else {
+				fprintf(stderr, "%s", name);
+				return res;
+			}
+		}
+	}
+	return 0;
+}

I do not like much that we change the behavir based on tst_test content. Maybe it would be cleaner to define a tst_check_driver(const char *name), then we can do the loop over tst_test->needs_drivers in the tst_test.c library and loop over argv in the shell helper.

Signature · 2 lines
Cyril Hrubis
[email protected]
#15 lore raw

RFC PATCH 1/4 lib/tst_test.c: add 'needs_drivers' option with tst_check_drivers cmd

Quoted 6 lines · Cyril Hrubis

Hi...
I do not like much that we change the behavir based on tst_test content. Maybe it would be cleaner to define a tst_check_driver(const char *name), then we can do the loop over tst_test->needs_drivers in the tst_test.c library and loop over argv in the shell helper.

Hi Cyril,

OK, will send the 2nd version.

Thanks,
Alexey

#16 lore raw

RFC PATCH 1/4 lib/tst_test.c: add 'needs_drivers' option with tst_check_drivers cmd

Hi,

Quoted 6 lines · Cyril Hrubis
Quoted 5 lines

Hi...
I do not like much that we change the behavir based on tst_test content. Maybe it would be cleaner to define a tst_check_driver(const char *name), then we can do the loop over tst_test->needs_drivers in the tst_test.c library and loop over argv in the shell helper.

+1 it makes sense.

Quoted 3 lines

Hi Cyril,

OK, will send the 2nd version.

BTW it'd be nice to have support to load module with parameters.

Quoted 2 lines

Thanks,
Alexey

Kind regards,
Petr

#17 lore raw

RFC PATCH 1/4 lib/tst_test.c: add 'needs_drivers' option with tst_check_drivers cmd

Quoted 8 lines · Petr Vorel

Hi,

Quoted 6 lines · Cyril Hrubis
Quoted 5 lines

Hi...
I do not like much that we change the behavir based on tst_test content. Maybe it would be cleaner to define a tst_check_driver(const char *name), then we can do the loop over tst_test->needs_drivers in the tst_test.c library and loop over argv in the shell helper.

Quoted 7 lines

+1 it makes sense.

Quoted 3 lines

Hi Cyril,

OK, will send the 2nd version.

BTW it'd be nice to have support to load module with parameters.

Hmm, is it really worth to do, have any examples?

Thanks,
Alexey