1#!/bin/sh 2 3# Based on https://gist.github.com/zonque/7d03568eab14a2bb57cb by 4# Daniel Mack github@zonque.org 5 6# Modified version of sctp.sh by Michael Tuexen <tuexen@freebsd.org>: 7# * Use loopback as the address of the server on both side initialized using 8# htonl(INADDR_LOOPBACK). 9# * Negotiate only 1 stream in both directions since only one stream is used. 10# * Don't use initmsg.sinit_max_instreams as an argument in listen(), which 11# does not make sense. 12# Use an arbitrary positive integer, 5 in this case. 13# * Initialize flags before calling sctp_recvmsg(). 14 15# "panic: Don't own TCB lock" seen: 16# https://people.freebsd.org/~pho/stress/log/sctp2.txt 17 18# "panic: soclose: SS_NOFDREF on enter" seen: 19# https://people.freebsd.org/~pho/stress/log/sctp2-2.txt 20 21kldstat -v | grep -q sctp || kldload sctp.ko 22cat > /tmp/sctp2.c <<EOF 23#include <sys/types.h> 24#include <sys/socket.h> 25#include <unistd.h> 26#include <arpa/inet.h> 27#include <libgen.h> 28#include <netinet/in.h> 29#include <netinet/sctp.h> 30#include <stdio.h> 31#include <stdlib.h> 32#include <string.h> 33 34static int my_port_num; 35 36static void 37die(const char *s) 38{ 39 perror(s); 40 exit(1); 41} 42 43static void 44server(void) 45{ 46 struct sctp_sndrcvinfo sndrcvinfo; 47 struct sockaddr_in servaddr = { 48 .sin_family = AF_INET, 49 .sin_addr.s_addr = htonl(INADDR_LOOPBACK), 50 .sin_port = htons(my_port_num), 51 }; 52 struct sctp_initmsg initmsg = { 53 .sinit_num_ostreams = 1, 54 .sinit_max_instreams = 1, 55 .sinit_max_attempts = 4, 56 }; 57 int listen_fd, conn_fd, flags, ret, in; 58 59 listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); 60 if (listen_fd < 0) 61 die("socket"); 62 63 ret = bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr)); 64 if (ret < 0) 65 die("bind"); 66 67 ret = setsockopt(listen_fd, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, 68 sizeof(initmsg)); 69 if (ret < 0) 70 die("setsockopt"); 71 72 ret = listen(listen_fd, 5); 73 if (ret < 0) 74 die("listen"); 75 76 for (;;) { 77 char buffer[1024]; 78 79 printf("Waiting for connection\n"); 80 fflush(stdout); 81 82 conn_fd = accept(listen_fd, (struct sockaddr *) NULL, NULL); 83 if(conn_fd < 0) 84 die("accept()"); 85 86 printf("New client connected\n"); 87 fflush(stdout); 88 89 flags = 0; 90 in = sctp_recvmsg(conn_fd, buffer, sizeof(buffer), NULL, 0, 91 &sndrcvinfo, &flags); 92 if (in > 0) { 93 printf("Received data: %s\n", buffer); 94 fflush(stdout); 95 } 96 97 close(conn_fd); 98 } 99} 100 101static void 102client(void) 103{ 104 struct sockaddr_in servaddr = { 105 .sin_family = AF_INET, 106 .sin_port = htons(my_port_num), 107 .sin_addr.s_addr = htonl(INADDR_LOOPBACK), 108 }; 109 int conn_fd, ret; 110 const char *msg = "Hello, Server!"; 111 112 conn_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); 113 if (conn_fd < 0) 114 die("socket()"); 115 116 ret = connect(conn_fd, (struct sockaddr *) &servaddr, sizeof(servaddr)); 117 if (ret < 0) 118 die("connect()"); 119 120 ret = sctp_sendmsg(conn_fd, (void *) msg, strlen(msg) + 1, NULL, 0, 0, 0, 0, 0, 0 ); 121 if (ret < 0) 122 die("sctp_sendmsg"); 123 124 close(conn_fd); 125} 126 127int 128main(int argc __unused, char *argv[]) 129{ 130 131 my_port_num = atoi(argv[1]); 132 if (strstr(basename(argv[0]), "server")) 133 server(); 134 else 135 client(); 136 137 return (0); 138} 139EOF 140 141cc -o /tmp/server -Wall -Wextra -O2 /tmp/sctp2.c || exit 142ln -sf /tmp/server /tmp/client 143 144parallel=100 145for i in `jot $parallel 62324`; do 146 /tmp/server $i > /dev/null & 147done 148(cd ../testcases/swap; ./swap -t 1m -i 20 -l 100) & 149sleep 2 150 151start=`date +%s` 152while [ $((`date +%s` - start)) -lt 60 ]; do 153 pids= 154 for i in `jot 50`; do 155 for j in `jot $parallel 62324`; do 156 /tmp/client $j & 157 pids="$pids $!" 158 done 159 done 160 for i in $pids; do 161 wait $i 162 done 163done 164pkill server 165wait 166while pkill swap; do :; done 167wait 168rm -f /tmp/sctp2.c /tmp/server /tmp/client 169exit 0 170