xref: /freebsd/tools/test/stress2/misc/socketpair2.sh (revision 8a272653d9fbd9fc37691c9aad6a05089b4ecb4d)
1*8a272653SPeter Holm#!/bin/sh
2*8a272653SPeter Holm
3*8a272653SPeter Holm#
4*8a272653SPeter Holm# Copyright (c) 2014 EMC Corp.
5*8a272653SPeter Holm# All rights reserved.
6*8a272653SPeter Holm#
7*8a272653SPeter Holm# Redistribution and use in source and binary forms, with or without
8*8a272653SPeter Holm# modification, are permitted provided that the following conditions
9*8a272653SPeter Holm# are met:
10*8a272653SPeter Holm# 1. Redistributions of source code must retain the above copyright
11*8a272653SPeter Holm#    notice, this list of conditions and the following disclaimer.
12*8a272653SPeter Holm# 2. Redistributions in binary form must reproduce the above copyright
13*8a272653SPeter Holm#    notice, this list of conditions and the following disclaimer in the
14*8a272653SPeter Holm#    documentation and/or other materials provided with the distribution.
15*8a272653SPeter Holm#
16*8a272653SPeter Holm# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*8a272653SPeter Holm# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*8a272653SPeter Holm# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*8a272653SPeter Holm# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*8a272653SPeter Holm# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*8a272653SPeter Holm# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*8a272653SPeter Holm# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*8a272653SPeter Holm# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*8a272653SPeter Holm# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*8a272653SPeter Holm# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*8a272653SPeter Holm# SUCH DAMAGE.
27*8a272653SPeter Holm#
28*8a272653SPeter Holm
29*8a272653SPeter Holm# Default unix domain socket limits causes hang:
30*8a272653SPeter Holm# 1001 880  871 0 52 0 5780 1524 keglimit D+ 0 0:00.35 /tmp/socketpair2
31*8a272653SPeter Holm
32*8a272653SPeter Holm# Test scenario by peter@
33*8a272653SPeter Holm
34*8a272653SPeter Holm# Fixed in r269489.
35*8a272653SPeter Holm
36*8a272653SPeter Holm. ../default.cfg
37*8a272653SPeter Holm
38*8a272653SPeter Holmhere=`pwd`
39*8a272653SPeter Holmcd /tmp
40*8a272653SPeter Holmsed '1,/^EOF/d' < $here/$0 > socketpair2.c
41*8a272653SPeter Holmmycc -o socketpair2 -Wall -Wextra -O2 socketpair2.c || exit
42*8a272653SPeter Holmrm -f socketpair2.c
43*8a272653SPeter Holm
44*8a272653SPeter Holm/tmp/socketpair2 > /dev/null 2>&1
45*8a272653SPeter Holm
46*8a272653SPeter Holmrm -f /tmp/socketpair2
47*8a272653SPeter Holmexit 0
48*8a272653SPeter HolmEOF
49*8a272653SPeter Holm/*
50*8a272653SPeter Holm Peter Wemm <peter wemm org>
51*8a272653SPeter Holm
52*8a272653SPeter Holm Some systems seem to base how much can be written to the pipe based
53*8a272653SPeter Holm on the size of the socket receive buffer (read-side), while others
54*8a272653SPeter Holm on the size of the socket send buffer (send-side).
55*8a272653SPeter Holm
56*8a272653SPeter Holm This little hack tries to make an educated guess as to what is the
57*8a272653SPeter Holm case on this particular system.
58*8a272653SPeter Holm*/
59*8a272653SPeter Holm
60*8a272653SPeter Holm#include <sys/types.h>
61*8a272653SPeter Holm#include <sys/socket.h>
62*8a272653SPeter Holm
63*8a272653SPeter Holm#include <stdio.h>
64*8a272653SPeter Holm#include <stdlib.h>
65*8a272653SPeter Holm#include <string.h>
66*8a272653SPeter Holm#include <unistd.h>
67*8a272653SPeter Holm#include <fcntl.h>
68*8a272653SPeter Holm#include <errno.h>
69*8a272653SPeter Holm
70*8a272653SPeter Holm#ifndef MIN
71*8a272653SPeter Holm#define MIN(a,b) ((a) < (b) ? (a) : (b))
72*8a272653SPeter Holm#endif /* !MIN */
73*8a272653SPeter Holm
74*8a272653SPeter Holm#ifndef MAX
75*8a272653SPeter Holm#define MAX(a,b) ((a) > (b) ? (a) : (b))
76*8a272653SPeter Holm#endif /* !MAX */
77*8a272653SPeter Holm
78*8a272653SPeter Holm#if NEED_AF_LOCAL
79*8a272653SPeter Holm#define AF_LOCAL AF_UNIX
80*8a272653SPeter Holm#endif /* NEED_AF_LOCAL */
81*8a272653SPeter Holm
82*8a272653SPeter Holm#define PACKETSIZE  (1024)
83*8a272653SPeter Holm
84*8a272653SPeter Holm#define SEND_PIPE   (0)
85*8a272653SPeter Holm#define RECV_PIPE   (1)
86*8a272653SPeter Holm
87*8a272653SPeter Holm#define EXIT_SENDSIDE    (1)
88*8a272653SPeter Holm#define EXIT_READSIDE    (0) /* looking for readside - exit 0 */
89*8a272653SPeter Holm#define EXIT_UNKNOWN     (1)
90*8a272653SPeter Holm
91*8a272653SPeter Holmstatic void
92*8a272653SPeter Holmsetsockets(const int doreverse, const size_t packetsize,
93*8a272653SPeter Holm           const int s, const int r,
94*8a272653SPeter Holm           size_t *sndbuf, size_t *sndbuf_set,
95*8a272653SPeter Holm           size_t *rcvbuf, size_t *rcvbuf_set);
96*8a272653SPeter Holm
97*8a272653SPeter Holmstatic size_t
98*8a272653SPeter Holmsendtest(const int s, const char *buf, const size_t buflen);
99*8a272653SPeter Holm
100*8a272653SPeter Holmint
101*8a272653SPeter Holmmain(void)
102*8a272653SPeter Holm{
103*8a272653SPeter Holm   size_t sent, packetcount, sndbuf, sndbuf_set, rcvbuf, rcvbuf_set;
104*8a272653SPeter Holm   char buf[PACKETSIZE - 64]; /* allow for some padding between messages. */
105*8a272653SPeter Holm   int datapipev[2];
106*8a272653SPeter Holm
107*8a272653SPeter Holm   if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, datapipev) != 0) {
108*8a272653SPeter Holm      perror("socketpair()");
109*8a272653SPeter Holm      exit(EXIT_UNKNOWN);
110*8a272653SPeter Holm   }
111*8a272653SPeter Holm
112*8a272653SPeter Holm   setsockets(0,
113*8a272653SPeter Holm              PACKETSIZE,
114*8a272653SPeter Holm              datapipev[SEND_PIPE],
115*8a272653SPeter Holm              datapipev[RECV_PIPE],
116*8a272653SPeter Holm              &sndbuf, &sndbuf_set,
117*8a272653SPeter Holm              &rcvbuf, &rcvbuf_set);
118*8a272653SPeter Holm
119*8a272653SPeter Holm   packetcount = MIN(sndbuf, sndbuf_set) / PACKETSIZE;
120*8a272653SPeter Holm   fprintf(stderr, "Requested sndbuf to be %ld, is %ld.  "
121*8a272653SPeter Holm          "Requested rcvbuf to be %ld, is %ld.\n"
122*8a272653SPeter Holm          "Calculated packetcount is %lu\n",
123*8a272653SPeter Holm          (long)sndbuf, (long)sndbuf_set,
124*8a272653SPeter Holm          (long)rcvbuf, (long)rcvbuf_set, (unsigned long)packetcount);
125*8a272653SPeter Holm
126*8a272653SPeter Holm   sent = sendtest(datapipev[SEND_PIPE], buf, sizeof(buf));
127*8a272653SPeter Holm   if (sent >= (size_t)sndbuf) {
128*8a272653SPeter Holm      fprintf(stderr, "status determined by send-side\n");
129*8a272653SPeter Holm      return EXIT_SENDSIDE;
130*8a272653SPeter Holm   }
131*8a272653SPeter Holm
132*8a272653SPeter Holm   /*
133*8a272653SPeter Holm    * Try the reverse.  Perhaps this system wants a large rcvbuf rather than
134*8a272653SPeter Holm    * a large sndbuf.
135*8a272653SPeter Holm    */
136*8a272653SPeter Holm   close(datapipev[SEND_PIPE]);
137*8a272653SPeter Holm   close(datapipev[RECV_PIPE]);
138*8a272653SPeter Holm
139*8a272653SPeter Holm   if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, datapipev) != 0) {
140*8a272653SPeter Holm      perror("socketpair()");
141*8a272653SPeter Holm      exit(EXIT_UNKNOWN);
142*8a272653SPeter Holm   }
143*8a272653SPeter Holm
144*8a272653SPeter Holm   setsockets(1,
145*8a272653SPeter Holm              PACKETSIZE,
146*8a272653SPeter Holm              datapipev[SEND_PIPE],
147*8a272653SPeter Holm              datapipev[RECV_PIPE],
148*8a272653SPeter Holm              &sndbuf, &sndbuf_set,
149*8a272653SPeter Holm              &rcvbuf, &rcvbuf_set);
150*8a272653SPeter Holm
151*8a272653SPeter Holm   packetcount = MIN(rcvbuf, rcvbuf_set) / PACKETSIZE;
152*8a272653SPeter Holm   fprintf(stderr, "Requested sndbuf to be %ld, is %ld.  "
153*8a272653SPeter Holm          "Requested rcvbuf to be %ld, is %ld.\n"
154*8a272653SPeter Holm          "Calculated packetcount is %lu\n",
155*8a272653SPeter Holm          (long)sndbuf, (long)sndbuf_set,
156*8a272653SPeter Holm          (long)rcvbuf, (long)rcvbuf_set, (unsigned long)packetcount);
157*8a272653SPeter Holm
158*8a272653SPeter Holm   sent = sendtest(datapipev[SEND_PIPE], buf, sizeof(buf));
159*8a272653SPeter Holm   if (sent >= (size_t)rcvbuf) {
160*8a272653SPeter Holm      fprintf(stderr, "status determined by read-side\n");
161*8a272653SPeter Holm      return EXIT_READSIDE;
162*8a272653SPeter Holm   }
163*8a272653SPeter Holm
164*8a272653SPeter Holm   fprintf(stderr, "status is unknown\n");
165*8a272653SPeter Holm   return EXIT_UNKNOWN;
166*8a272653SPeter Holm}
167*8a272653SPeter Holm
168*8a272653SPeter Holmstatic void
169*8a272653SPeter Holmsetsockets(doreverse, packetsize, s, r, sndbuf, sndbuf_set, rcvbuf, rcvbuf_set)
170*8a272653SPeter Holm   const int doreverse;
171*8a272653SPeter Holm   const size_t packetsize;
172*8a272653SPeter Holm   const int s;
173*8a272653SPeter Holm   const int r;
174*8a272653SPeter Holm   size_t *sndbuf, *sndbuf_set;
175*8a272653SPeter Holm   size_t *rcvbuf, *rcvbuf_set;
176*8a272653SPeter Holm{
177*8a272653SPeter Holm   socklen_t len;
178*8a272653SPeter Holm   int p;
179*8a272653SPeter Holm
180*8a272653SPeter Holm   if ((p = fcntl(s, F_GETFL, 0))        == -1
181*8a272653SPeter Holm   ||  fcntl(s, F_SETFL, p | O_NONBLOCK) == -1
182*8a272653SPeter Holm   ||  fcntl(r, F_SETFL, p | O_NONBLOCK) == -1) {
183*8a272653SPeter Holm      perror("fcntl(F_SETFL/F_GETFL, O_NONBLOCK) failed");
184*8a272653SPeter Holm      exit(EXIT_UNKNOWN);
185*8a272653SPeter Holm   }
186*8a272653SPeter Holm
187*8a272653SPeter Holm   len = sizeof(*sndbuf_set);
188*8a272653SPeter Holm
189*8a272653SPeter Holm   if (doreverse) {
190*8a272653SPeter Holm      *sndbuf = packetsize;
191*8a272653SPeter Holm      if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, sndbuf, sizeof(*sndbuf)) != 0) {
192*8a272653SPeter Holm         perror("setsockopt(SO_SNDBUF)");
193*8a272653SPeter Holm         exit(EXIT_UNKNOWN);
194*8a272653SPeter Holm      }
195*8a272653SPeter Holm
196*8a272653SPeter Holm      if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, sndbuf_set, &len) != 0) {
197*8a272653SPeter Holm         perror("getsockopt(SO_SNDBUF)");
198*8a272653SPeter Holm         exit(EXIT_UNKNOWN);
199*8a272653SPeter Holm      }
200*8a272653SPeter Holm
201*8a272653SPeter Holm      *rcvbuf = *sndbuf_set * 10;
202*8a272653SPeter Holm      if (setsockopt(r, SOL_SOCKET, SO_RCVBUF, rcvbuf, sizeof(*rcvbuf)) != 0) {
203*8a272653SPeter Holm         perror("setsockopt(SO_RCVBUF)");
204*8a272653SPeter Holm         exit(EXIT_UNKNOWN);
205*8a272653SPeter Holm      }
206*8a272653SPeter Holm   }
207*8a272653SPeter Holm   else {
208*8a272653SPeter Holm      *rcvbuf = packetsize;
209*8a272653SPeter Holm      if (setsockopt(r, SOL_SOCKET, SO_RCVBUF, rcvbuf, sizeof(*rcvbuf)) != 0) {
210*8a272653SPeter Holm         perror("setsockopt(SO_RCVBUF)");
211*8a272653SPeter Holm         exit(EXIT_UNKNOWN);
212*8a272653SPeter Holm      }
213*8a272653SPeter Holm
214*8a272653SPeter Holm      if (getsockopt(r, SOL_SOCKET, SO_RCVBUF, rcvbuf_set, &len) != 0) {
215*8a272653SPeter Holm         perror("getsockopt(SO_RCVBUF)");
216*8a272653SPeter Holm         exit(EXIT_UNKNOWN);
217*8a272653SPeter Holm      }
218*8a272653SPeter Holm
219*8a272653SPeter Holm      *sndbuf = *rcvbuf_set * 10;
220*8a272653SPeter Holm      if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, sndbuf, sizeof(*sndbuf)) != 0) {
221*8a272653SPeter Holm         perror("setsockopt(SO_SNDBUF)");
222*8a272653SPeter Holm         exit(EXIT_UNKNOWN);
223*8a272653SPeter Holm      }
224*8a272653SPeter Holm   }
225*8a272653SPeter Holm
226*8a272653SPeter Holm   if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, sndbuf_set, &len) != 0
227*8a272653SPeter Holm   ||  getsockopt(r, SOL_SOCKET, SO_RCVBUF, rcvbuf_set, &len) != 0) {
228*8a272653SPeter Holm      perror("getsockopt(SO_SNDBUF/SO_RCVBUF)");
229*8a272653SPeter Holm      exit(EXIT_UNKNOWN);
230*8a272653SPeter Holm   }
231*8a272653SPeter Holm
232*8a272653SPeter Holm   fprintf(stderr, "sndbuf is %lu, rcvbuf is %lu\n",
233*8a272653SPeter Holm          (unsigned long)*sndbuf_set, (unsigned long)*rcvbuf_set);
234*8a272653SPeter Holm
235*8a272653SPeter Holm   if (doreverse) {
236*8a272653SPeter Holm      if (*rcvbuf_set < *rcvbuf) {
237*8a272653SPeter Holm         fprintf(stderr, "failed to set rcvbuf to %lu.  Is %lu\n",
238*8a272653SPeter Holm                 (unsigned long)*rcvbuf, (unsigned long)*rcvbuf_set);
239*8a272653SPeter Holm         exit(EXIT_UNKNOWN);
240*8a272653SPeter Holm      }
241*8a272653SPeter Holm   }
242*8a272653SPeter Holm   else {
243*8a272653SPeter Holm      if (*sndbuf_set < *sndbuf) {
244*8a272653SPeter Holm         fprintf(stderr, "failed to set sndbuf to %lu (is %lu)\n",
245*8a272653SPeter Holm                 (unsigned long)*sndbuf, (unsigned long)*sndbuf_set);
246*8a272653SPeter Holm         exit(EXIT_UNKNOWN);
247*8a272653SPeter Holm      }
248*8a272653SPeter Holm   }
249*8a272653SPeter Holm}
250*8a272653SPeter Holm
251*8a272653SPeter Holmstatic size_t
252*8a272653SPeter Holmsendtest(s, buf, buflen)
253*8a272653SPeter Holm   const int s;
254*8a272653SPeter Holm   const char *buf;
255*8a272653SPeter Holm   const size_t buflen;
256*8a272653SPeter Holm{
257*8a272653SPeter Holm   ssize_t rc;
258*8a272653SPeter Holm   int i;
259*8a272653SPeter Holm
260*8a272653SPeter Holm   i     = 1;
261*8a272653SPeter Holm   errno = 0;
262*8a272653SPeter Holm   while (errno == 0) {
263*8a272653SPeter Holm      if ((rc = sendto(s, buf, buflen, 0, NULL, 0)) != (ssize_t)buflen)
264*8a272653SPeter Holm         fprintf(stderr, "sendto(2) failed on iteration %d, sent %ld/%lu.  "
265*8a272653SPeter Holm                "Total bytes sent: %lu.  Error on last packet: %s\n",
266*8a272653SPeter Holm                i, (long)rc, (unsigned long)buflen,
267*8a272653SPeter Holm                (unsigned long)(i * buflen + MAX(rc, 0)), strerror(errno));
268*8a272653SPeter Holm      else
269*8a272653SPeter Holm         ++i;
270*8a272653SPeter Holm   }
271*8a272653SPeter Holm
272*8a272653SPeter Holm   return (size_t)(i * buflen + MAX(rc, 0));
273*8a272653SPeter Holm}
274