1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 #include <sys/socket.h>
7 #include <netinet/tcp.h>
12 #include <sys/ioctl.h>
14 #include <asm/byteorder.h>
19 #include <portals/api-support.h>
20 #include <portals/list.h>
21 #include <portals/lib-types.h>
23 /* should get this from autoconf somehow */
25 #define PIDFILE_DIR "/var/run"
28 #define PROGNAME "acceptor"
30 void create_pidfile(char *name, int port)
35 snprintf(pidfile, sizeof(pidfile), "%s/%s-%d.pid",
36 PIDFILE_DIR, name, port);
38 if ((fp = fopen(pidfile, "w"))) {
39 fprintf(fp, "%d\n", getpid());
42 syslog(LOG_ERR, "%s: %s\n", pidfile,
47 int pidfile_exists(char *name, int port)
51 snprintf(pidfile, sizeof(pidfile), "%s/%s-%d.pid",
52 PIDFILE_DIR, name, port);
54 if (!access(pidfile, F_OK)) {
55 fprintf(stderr, "%s: exists, acceptor already running.\n",
63 parse_size (int *sizep, char *str)
68 switch (sscanf (str, "%d%1[gGmMkK]", &size, mod))
103 show_connection (int fd, __u32 net_ip, ptl_nid_t nid)
105 struct hostent *h = gethostbyaddr ((char *)&net_ip, sizeof net_ip, AF_INET);
106 __u32 host_ip = ntohl (net_ip);
113 len = sizeof (txmem);
114 if (getsockopt (fd, SOL_SOCKET, SO_SNDBUF, &txmem, &len) != 0)
115 perror ("Cannot get write buffer size");
117 len = sizeof (rxmem);
118 if (getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rxmem, &len) != 0)
119 perror ("Cannot get read buffer size");
121 len = sizeof (nonagle);
122 if (getsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &nonagle, &len) != 0)
123 perror ("Cannot get nagle");
126 snprintf (host, sizeof(host), "%d.%d.%d.%d", (host_ip >> 24) & 0xff,
127 (host_ip >> 16) & 0xff, (host_ip >> 8) & 0xff, host_ip & 0xff);
129 snprintf (host, sizeof(host), "%s", h->h_name);
131 syslog (LOG_INFO, "Accepted host: %s NID: "LPX64" snd: %d rcv %d nagle: %s\n",
132 host, nid, txmem, rxmem, nonagle ? "disabled" : "enabled");
136 sock_write (int cfd, void *buffer, int nob)
140 int rc = write (cfd, buffer, nob);
152 fprintf (stderr, "Unexpected zero sock_write\n");
157 buffer = (char *)buffer + nob;
164 sock_read (int cfd, void *buffer, int nob)
168 int rc = read (cfd, buffer, nob);
178 if (rc == 0) /* EOF */
180 errno = ECONNABORTED;
185 buffer = (char *)buffer + nob;
192 exchange_nids (int cfd, ptl_nid_t my_nid, ptl_nid_t *peer_nid)
196 ptl_magicversion_t *hmv = (ptl_magicversion_t *)&hdr.dest_nid;
198 LASSERT (sizeof (*hmv) == sizeof (hdr.dest_nid));
200 memset (&hdr, 0, sizeof (hdr));
202 hmv->magic = __cpu_to_le32 (PORTALS_PROTO_MAGIC);
203 hmv->version_major = __cpu_to_le16 (PORTALS_PROTO_VERSION_MAJOR);
204 hmv->version_minor = __cpu_to_le16 (PORTALS_PROTO_VERSION_MINOR);
206 hdr.src_nid = __cpu_to_le64 (my_nid);
207 hdr.type = __cpu_to_le32 (PTL_MSG_HELLO);
209 /* Assume there's sufficient socket buffering for a portals HELLO header */
210 rc = sock_write (cfd, &hdr, sizeof (hdr));
212 perror ("Can't send initial HELLO");
216 /* First few bytes down the wire are the portals protocol magic and
217 * version, no matter what protocol version we're running. */
219 rc = sock_read (cfd, hmv, sizeof (*hmv));
221 perror ("Can't read from peer");
225 if (__cpu_to_le32 (hmv->magic) != PORTALS_PROTO_MAGIC) {
226 fprintf (stderr, "Bad magic %#08x (%#08x expected)\n",
227 __cpu_to_le32 (hmv->magic), PORTALS_PROTO_MAGIC);
231 if (__cpu_to_le16 (hmv->version_major) != PORTALS_PROTO_VERSION_MAJOR ||
232 __cpu_to_le16 (hmv->version_minor) != PORTALS_PROTO_VERSION_MINOR) {
233 fprintf (stderr, "Incompatible protocol version %d.%d (%d.%d expected)\n",
234 __cpu_to_le16 (hmv->version_major),
235 __cpu_to_le16 (hmv->version_minor),
236 PORTALS_PROTO_VERSION_MAJOR,
237 PORTALS_PROTO_VERSION_MINOR);
240 /* version 0 sends magic/version as the dest_nid of a 'hello' header,
241 * so read the rest of it in now... */
242 LASSERT (PORTALS_PROTO_VERSION_MAJOR == 0);
243 rc = sock_read (cfd, hmv + 1, sizeof (hdr) - sizeof (*hmv));
245 perror ("Can't read rest of HELLO hdr");
249 /* ...and check we got what we expected */
250 if (__cpu_to_le32 (hdr.type) != PTL_MSG_HELLO ||
251 __cpu_to_le32 (PTL_HDR_LENGTH (&hdr)) != 0) {
252 fprintf (stderr, "Expecting a HELLO hdr with 0 payload,"
253 " but got type %d with %d payload\n",
254 __cpu_to_le32 (hdr.type),
255 __cpu_to_le32 (PTL_HDR_LENGTH (&hdr)));
259 *peer_nid = __le64_to_cpu (hdr.src_nid);
266 fprintf (stderr, "Usage: %s [-r recv_mem] [-s send_mem] [-n] [-N nal_id] port\n", myname);
270 int main(int argc, char **argv)
272 int o, fd, rc, port, pfd;
273 struct sockaddr_in srvaddr;
283 while ((c = getopt (argc, argv, "N:r:s:nlxi")) != -1)
287 if (parse_size (&rxmem, optarg) != 0 || rxmem < 0)
292 if (parse_size (&txmem, optarg) != 0 || txmem < 0)
313 if (parse_size(&nal, optarg) != 0 ||
314 nal < 0 || nal > NAL_MAX_NR)
326 port = atol(argv[optind++]);
328 if (pidfile_exists(PROGNAME, port))
331 memset(&srvaddr, 0, sizeof(srvaddr));
332 srvaddr.sin_family = AF_INET;
333 srvaddr.sin_port = htons(port);
334 srvaddr.sin_addr.s_addr = INADDR_ANY;
336 fd = socket(PF_INET, SOCK_STREAM, 0);
338 perror("opening socket");
343 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &o, sizeof(o))) {
344 perror("Cannot set REUSEADDR socket opt");
351 rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &o, sizeof (o));
354 perror ("Cannot disable nagle");
361 rc = setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &txmem, sizeof (txmem));
364 perror ("Cannot set write buffer size");
371 rc = setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &rxmem, sizeof (rxmem));
374 perror ("Cannot set read buffer size");
379 rc = bind(fd, (struct sockaddr *)&srvaddr, sizeof(srvaddr));
385 if (listen(fd, 127)) {
389 fprintf(stderr, "listening on port %d\n", port);
391 pfd = open("/dev/portals", O_RDWR);
393 perror("opening portals device");
397 rc = daemon(1, noclose);
399 perror("daemon(): ");
403 openlog(PROGNAME, LOG_PID, LOG_DAEMON);
404 syslog(LOG_INFO, "started, listening on port %d\n", port);
405 create_pidfile(PROGNAME, port);
408 struct sockaddr_in clntaddr;
409 int len = sizeof(clntaddr);
411 struct portal_ioctl_data data;
414 cfd = accept(fd, (struct sockaddr *)&clntaddr, &len);
422 peer_nid = ntohl (clntaddr.sin_addr.s_addr); /* HOST byte order */
425 PORTAL_IOC_INIT (data);
427 rc = ioctl (pfd, IOC_PORTAL_GET_NID, &data);
430 perror ("Can't get my NID");
435 rc = exchange_nids (cfd, data.ioc_nid, &peer_nid);
443 show_connection (cfd, clntaddr.sin_addr.s_addr, peer_nid);
445 PORTAL_IOC_INIT(data);
448 data.ioc_nal_cmd = NAL_CMD_REGISTER_PEER_FD;
449 data.ioc_nid = peer_nid;
450 data.ioc_flags = bind_irq;
452 if (ioctl(pfd, IOC_PORTAL_NAL_CMD, &data) < 0) {
453 perror("ioctl failed");
456 printf("client registered\n");
460 perror ("close failed");