14
14
* - SOCK_DGRAM
15
15
* - SOCK_RAW
16
16
*
17
+ * PF_RDS
18
+ * - SOCK_SEQPACKET
19
+ *
17
20
* Start this program on two connected hosts, one in send mode and
18
21
* the other with option '-r' to put it in receiver mode.
19
22
*
53
56
#include <sys/types.h>
54
57
#include <sys/wait.h>
55
58
#include <unistd.h>
59
+ #include <linux/rds.h>
56
60
57
61
#ifndef SO_EE_ORIGIN_ZEROCOPY
58
62
#define SO_EE_ORIGIN_ZEROCOPY 5
@@ -300,10 +304,15 @@ static int do_setup_tx(int domain, int type, int protocol)
300
304
if (cfg_zerocopy )
301
305
do_setsockopt (fd , SOL_SOCKET , SO_ZEROCOPY , 1 );
302
306
303
- if (domain != PF_PACKET )
307
+ if (domain != PF_PACKET && domain != PF_RDS )
304
308
if (connect (fd , (void * ) & cfg_dst_addr , cfg_alen ))
305
309
error (1 , errno , "connect" );
306
310
311
+ if (domain == PF_RDS ) {
312
+ if (bind (fd , (void * ) & cfg_src_addr , cfg_alen ))
313
+ error (1 , errno , "bind" );
314
+ }
315
+
307
316
return fd ;
308
317
}
309
318
@@ -444,6 +453,13 @@ static void do_tx(int domain, int type, int protocol)
444
453
msg .msg_iovlen ++ ;
445
454
}
446
455
456
+ if (domain == PF_RDS ) {
457
+ msg .msg_name = & cfg_dst_addr ;
458
+ msg .msg_namelen = (cfg_dst_addr .ss_family == AF_INET ?
459
+ sizeof (struct sockaddr_in ) :
460
+ sizeof (struct sockaddr_in6 ));
461
+ }
462
+
447
463
iov [2 ].iov_base = payload ;
448
464
iov [2 ].iov_len = cfg_payload_len ;
449
465
msg .msg_iovlen ++ ;
@@ -555,6 +571,40 @@ static void do_flush_datagram(int fd, int type)
555
571
bytes += cfg_payload_len ;
556
572
}
557
573
574
+
575
+ static void do_recvmsg (int fd )
576
+ {
577
+ int ret , off = 0 ;
578
+ char * buf ;
579
+ struct iovec iov ;
580
+ struct msghdr msg ;
581
+ struct sockaddr_storage din ;
582
+
583
+ buf = calloc (cfg_payload_len , sizeof (char ));
584
+ iov .iov_base = buf ;
585
+ iov .iov_len = cfg_payload_len ;
586
+
587
+ memset (& msg , 0 , sizeof (msg ));
588
+ msg .msg_name = & din ;
589
+ msg .msg_namelen = sizeof (din );
590
+ msg .msg_iov = & iov ;
591
+ msg .msg_iovlen = 1 ;
592
+
593
+ ret = recvmsg (fd , & msg , MSG_TRUNC );
594
+
595
+ if (ret == -1 )
596
+ error (1 , errno , "recv" );
597
+ if (ret != cfg_payload_len )
598
+ error (1 , 0 , "recv: ret=%u != %u" , ret , cfg_payload_len );
599
+
600
+ if (memcmp (buf + off , payload , ret ))
601
+ error (1 , 0 , "recv: data mismatch" );
602
+
603
+ free (buf );
604
+ packets ++ ;
605
+ bytes += cfg_payload_len ;
606
+ }
607
+
558
608
static void do_rx (int domain , int type , int protocol )
559
609
{
560
610
uint64_t tstop ;
@@ -566,6 +616,8 @@ static void do_rx(int domain, int type, int protocol)
566
616
do {
567
617
if (type == SOCK_STREAM )
568
618
do_flush_tcp (fd );
619
+ else if (domain == PF_RDS )
620
+ do_recvmsg (fd );
569
621
else
570
622
do_flush_datagram (fd , type );
571
623
@@ -610,6 +662,7 @@ static void parse_opts(int argc, char **argv)
610
662
40 /* max tcp options */ ;
611
663
int c ;
612
664
char * daddr = NULL , * saddr = NULL ;
665
+ char * cfg_test ;
613
666
614
667
cfg_payload_len = max_payload_len ;
615
668
@@ -667,6 +720,14 @@ static void parse_opts(int argc, char **argv)
667
720
break ;
668
721
}
669
722
}
723
+
724
+ cfg_test = argv [argc - 1 ];
725
+ if (strcmp (cfg_test , "rds" ) == 0 ) {
726
+ if (!daddr )
727
+ error (1 , 0 , "-D <server addr> required for PF_RDS\n" );
728
+ if (!cfg_rx && !saddr )
729
+ error (1 , 0 , "-S <client addr> required for PF_RDS\n" );
730
+ }
670
731
setup_sockaddr (cfg_family , daddr , & cfg_dst_addr );
671
732
setup_sockaddr (cfg_family , saddr , & cfg_src_addr );
672
733
@@ -699,6 +760,8 @@ int main(int argc, char **argv)
699
760
do_test (cfg_family , SOCK_STREAM , 0 );
700
761
else if (!strcmp (cfg_test , "udp" ))
701
762
do_test (cfg_family , SOCK_DGRAM , 0 );
763
+ else if (!strcmp (cfg_test , "rds" ))
764
+ do_test (PF_RDS , SOCK_SEQPACKET , 0 );
702
765
else
703
766
error (1 , 0 , "unknown cfg_test %s" , cfg_test );
704
767
0 commit comments