Skip to content

Commit 0e21a47

Browse files
author
Paolo Abeni
committed
Merge branch 'vsock-test-fix-wrong-setsockopt-parameters'
Konstantin Shkolnyy says: ==================== vsock/test: fix wrong setsockopt() parameters Parameters were created using wrong C types, which caused them to be of wrong size on some architectures, causing problems. The problem with SO_RCVLOWAT was found on s390 (big endian), while x86-64 didn't show it. After the fix, all tests pass on s390. Then Stefano Garzarella pointed out that SO_VM_SOCKETS_* calls might have a similar problem, which turned out to be true, hence, the second patch. Changes for v8: - Fix whitespace warnings from "checkpatch.pl --strict" - Add maintainers to Cc: Changes for v7: - Rebase on top of https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git - Add the "net" tags to the subjects Changes for v6: - rework the patch #3 to avoid creating a new file for new functions, and exclude vsock_perf from calling the new functions. - add "Reviewed-by:" to the patch #2. Changes for v5: - in the patch #2 replace the introduced uint64_t with unsigned long long to match documentation - add a patch #3 that verifies every setsockopt() call. Changes for v4: - add "Reviewed-by:" to the first patch, and add a second patch fixing SO_VM_SOCKETS_* calls, which depends on the first one (hence, it's now a patch series.) Changes for v3: - fix the same problem in vsock_perf and update commit message Changes for v2: - add "Fixes:" lines to the commit message ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 4615855 + 86814d8 commit 0e21a47

9 files changed

+204
-64
lines changed

tools/testing/vsock/control.c

+3-6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
#include "timeout.h"
2929
#include "control.h"
30+
#include "util.h"
3031

3132
static int control_fd = -1;
3233

@@ -50,7 +51,6 @@ void control_init(const char *control_host,
5051

5152
for (ai = result; ai; ai = ai->ai_next) {
5253
int fd;
53-
int val = 1;
5454

5555
fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
5656
if (fd < 0)
@@ -65,11 +65,8 @@ void control_init(const char *control_host,
6565
break;
6666
}
6767

68-
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
69-
&val, sizeof(val)) < 0) {
70-
perror("setsockopt");
71-
exit(EXIT_FAILURE);
72-
}
68+
setsockopt_int_check(fd, SOL_SOCKET, SO_REUSEADDR, 1,
69+
"setsockopt SO_REUSEADDR");
7370

7471
if (bind(fd, ai->ai_addr, ai->ai_addrlen) < 0)
7572
goto next;

tools/testing/vsock/msg_zerocopy_common.c

-10
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,6 @@
1414

1515
#include "msg_zerocopy_common.h"
1616

17-
void enable_so_zerocopy(int fd)
18-
{
19-
int val = 1;
20-
21-
if (setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &val, sizeof(val))) {
22-
perror("setsockopt");
23-
exit(EXIT_FAILURE);
24-
}
25-
}
26-
2717
void vsock_recv_completion(int fd, const bool *zerocopied)
2818
{
2919
struct sock_extended_err *serr;

tools/testing/vsock/msg_zerocopy_common.h

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#define VSOCK_RECVERR 1
1313
#endif
1414

15-
void enable_so_zerocopy(int fd);
1615
void vsock_recv_completion(int fd, const bool *zerocopied);
1716

1817
#endif /* MSG_ZEROCOPY_COMMON_H */

tools/testing/vsock/util.c

+142
Original file line numberDiff line numberDiff line change
@@ -651,3 +651,145 @@ void free_test_iovec(const struct iovec *test_iovec,
651651

652652
free(iovec);
653653
}
654+
655+
/* Set "unsigned long long" socket option and check that it's indeed set */
656+
void setsockopt_ull_check(int fd, int level, int optname,
657+
unsigned long long val, char const *errmsg)
658+
{
659+
unsigned long long chkval;
660+
socklen_t chklen;
661+
int err;
662+
663+
err = setsockopt(fd, level, optname, &val, sizeof(val));
664+
if (err) {
665+
fprintf(stderr, "setsockopt err: %s (%d)\n",
666+
strerror(errno), errno);
667+
goto fail;
668+
}
669+
670+
chkval = ~val; /* just make storage != val */
671+
chklen = sizeof(chkval);
672+
673+
err = getsockopt(fd, level, optname, &chkval, &chklen);
674+
if (err) {
675+
fprintf(stderr, "getsockopt err: %s (%d)\n",
676+
strerror(errno), errno);
677+
goto fail;
678+
}
679+
680+
if (chklen != sizeof(chkval)) {
681+
fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val),
682+
chklen);
683+
goto fail;
684+
}
685+
686+
if (chkval != val) {
687+
fprintf(stderr, "value mismatch: set %llu got %llu\n", val,
688+
chkval);
689+
goto fail;
690+
}
691+
return;
692+
fail:
693+
fprintf(stderr, "%s val %llu\n", errmsg, val);
694+
exit(EXIT_FAILURE);
695+
;
696+
}
697+
698+
/* Set "int" socket option and check that it's indeed set */
699+
void setsockopt_int_check(int fd, int level, int optname, int val,
700+
char const *errmsg)
701+
{
702+
int chkval;
703+
socklen_t chklen;
704+
int err;
705+
706+
err = setsockopt(fd, level, optname, &val, sizeof(val));
707+
if (err) {
708+
fprintf(stderr, "setsockopt err: %s (%d)\n",
709+
strerror(errno), errno);
710+
goto fail;
711+
}
712+
713+
chkval = ~val; /* just make storage != val */
714+
chklen = sizeof(chkval);
715+
716+
err = getsockopt(fd, level, optname, &chkval, &chklen);
717+
if (err) {
718+
fprintf(stderr, "getsockopt err: %s (%d)\n",
719+
strerror(errno), errno);
720+
goto fail;
721+
}
722+
723+
if (chklen != sizeof(chkval)) {
724+
fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val),
725+
chklen);
726+
goto fail;
727+
}
728+
729+
if (chkval != val) {
730+
fprintf(stderr, "value mismatch: set %d got %d\n", val, chkval);
731+
goto fail;
732+
}
733+
return;
734+
fail:
735+
fprintf(stderr, "%s val %d\n", errmsg, val);
736+
exit(EXIT_FAILURE);
737+
}
738+
739+
static void mem_invert(unsigned char *mem, size_t size)
740+
{
741+
size_t i;
742+
743+
for (i = 0; i < size; i++)
744+
mem[i] = ~mem[i];
745+
}
746+
747+
/* Set "timeval" socket option and check that it's indeed set */
748+
void setsockopt_timeval_check(int fd, int level, int optname,
749+
struct timeval val, char const *errmsg)
750+
{
751+
struct timeval chkval;
752+
socklen_t chklen;
753+
int err;
754+
755+
err = setsockopt(fd, level, optname, &val, sizeof(val));
756+
if (err) {
757+
fprintf(stderr, "setsockopt err: %s (%d)\n",
758+
strerror(errno), errno);
759+
goto fail;
760+
}
761+
762+
/* just make storage != val */
763+
chkval = val;
764+
mem_invert((unsigned char *)&chkval, sizeof(chkval));
765+
chklen = sizeof(chkval);
766+
767+
err = getsockopt(fd, level, optname, &chkval, &chklen);
768+
if (err) {
769+
fprintf(stderr, "getsockopt err: %s (%d)\n",
770+
strerror(errno), errno);
771+
goto fail;
772+
}
773+
774+
if (chklen != sizeof(chkval)) {
775+
fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val),
776+
chklen);
777+
goto fail;
778+
}
779+
780+
if (memcmp(&chkval, &val, sizeof(val)) != 0) {
781+
fprintf(stderr, "value mismatch: set %ld:%ld got %ld:%ld\n",
782+
val.tv_sec, val.tv_usec, chkval.tv_sec, chkval.tv_usec);
783+
goto fail;
784+
}
785+
return;
786+
fail:
787+
fprintf(stderr, "%s val %ld:%ld\n", errmsg, val.tv_sec, val.tv_usec);
788+
exit(EXIT_FAILURE);
789+
}
790+
791+
void enable_so_zerocopy_check(int fd)
792+
{
793+
setsockopt_int_check(fd, SOL_SOCKET, SO_ZEROCOPY, 1,
794+
"setsockopt SO_ZEROCOPY");
795+
}

tools/testing/vsock/util.h

+7
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,11 @@ unsigned long iovec_hash_djb2(const struct iovec *iov, size_t iovnum);
6868
struct iovec *alloc_test_iovec(const struct iovec *test_iovec, int iovnum);
6969
void free_test_iovec(const struct iovec *test_iovec,
7070
struct iovec *iovec, int iovnum);
71+
void setsockopt_ull_check(int fd, int level, int optname,
72+
unsigned long long val, char const *errmsg);
73+
void setsockopt_int_check(int fd, int level, int optname, int val,
74+
char const *errmsg);
75+
void setsockopt_timeval_check(int fd, int level, int optname,
76+
struct timeval val, char const *errmsg);
77+
void enable_so_zerocopy_check(int fd);
7178
#endif /* UTIL_H */

tools/testing/vsock/vsock_perf.c

+15-5
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
static unsigned int port = DEFAULT_PORT;
3535
static unsigned long buf_size_bytes = DEFAULT_BUF_SIZE_BYTES;
36-
static unsigned long vsock_buf_bytes = DEFAULT_VSOCK_BUF_BYTES;
36+
static unsigned long long vsock_buf_bytes = DEFAULT_VSOCK_BUF_BYTES;
3737
static bool zerocopy;
3838

3939
static void error(const char *s)
@@ -133,7 +133,7 @@ static float get_gbps(unsigned long bits, time_t ns_delta)
133133
((float)ns_delta / NSEC_PER_SEC);
134134
}
135135

136-
static void run_receiver(unsigned long rcvlowat_bytes)
136+
static void run_receiver(int rcvlowat_bytes)
137137
{
138138
unsigned int read_cnt;
139139
time_t rx_begin_ns;
@@ -162,8 +162,8 @@ static void run_receiver(unsigned long rcvlowat_bytes)
162162
printf("Run as receiver\n");
163163
printf("Listen port %u\n", port);
164164
printf("RX buffer %lu bytes\n", buf_size_bytes);
165-
printf("vsock buffer %lu bytes\n", vsock_buf_bytes);
166-
printf("SO_RCVLOWAT %lu bytes\n", rcvlowat_bytes);
165+
printf("vsock buffer %llu bytes\n", vsock_buf_bytes);
166+
printf("SO_RCVLOWAT %d bytes\n", rcvlowat_bytes);
167167

168168
fd = socket(AF_VSOCK, SOCK_STREAM, 0);
169169

@@ -251,6 +251,16 @@ static void run_receiver(unsigned long rcvlowat_bytes)
251251
close(fd);
252252
}
253253

254+
static void enable_so_zerocopy(int fd)
255+
{
256+
int val = 1;
257+
258+
if (setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &val, sizeof(val))) {
259+
perror("setsockopt");
260+
exit(EXIT_FAILURE);
261+
}
262+
}
263+
254264
static void run_sender(int peer_cid, unsigned long to_send_bytes)
255265
{
256266
time_t tx_begin_ns;
@@ -439,7 +449,7 @@ static long strtolx(const char *arg)
439449
int main(int argc, char **argv)
440450
{
441451
unsigned long to_send_bytes = DEFAULT_TO_SEND_BYTES;
442-
unsigned long rcvlowat_bytes = DEFAULT_RCVLOWAT_BYTES;
452+
int rcvlowat_bytes = DEFAULT_RCVLOWAT_BYTES;
443453
int peer_cid = -1;
444454
bool sender = false;
445455

0 commit comments

Comments
 (0)