/* * Use defaults on failure. */ void set_rsocket_options(int rsocket) { if (sq_size) rsetsockopt(rsocket, SOL_RDMA, RDMA_SQSIZE, &sq_size, sizeof sq_size); if (rq_size) rsetsockopt(rsocket, SOL_RDMA, RDMA_RQSIZE, &rq_size, sizeof rq_size); if (sq_inline) rsetsockopt(rsocket, SOL_RDMA, RDMA_INLINE, &sq_inline, sizeof sq_inline); }
static void set_options(int rs) { int val; if (buffer_size) { rsetsockopt(rs, SOL_SOCKET, SO_SNDBUF, (void *) &buffer_size, sizeof buffer_size); rsetsockopt(rs, SOL_SOCKET, SO_RCVBUF, (void *) &buffer_size, sizeof buffer_size); } else { val = 1 << 19; rsetsockopt(rs, SOL_SOCKET, SO_SNDBUF, (void *) &val, sizeof val); rsetsockopt(rs, SOL_SOCKET, SO_RCVBUF, (void *) &val, sizeof val); } val = 1; rsetsockopt(rs, IPPROTO_TCP, TCP_NODELAY, (void *) &val, sizeof(val)); rsetsockopt(rs, SOL_RDMA, RDMA_IOMAPSIZE, (void *) &val, sizeof val); if (flags & MSG_DONTWAIT) rfcntl(rs, F_SETFL, O_NONBLOCK); /* Inline size based on experimental data */ if (optimization == opt_latency) { val = 384; rsetsockopt(rs, SOL_RDMA, RDMA_INLINE, &val, sizeof val); } else if (optimization == opt_bandwidth) { val = 0; rsetsockopt(rs, SOL_RDMA, RDMA_INLINE, &val, sizeof val); } }
int setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen) { int fd; return (fd_get(socket, &fd) == fd_rsocket) ? rsetsockopt(fd, level, optname, optval, optlen) : real.setsockopt(fd, level, optname, optval, optlen); }
static int server_listen(void) { struct addrinfo hints, *res; int val, ret; memset(&hints, 0, sizeof hints); hints.ai_flags = AI_PASSIVE; ret = getaddrinfo(src_addr, port, &hints, &res); if (ret) { perror("getaddrinfo"); return ret; } lrs = rsocket(res->ai_family, res->ai_socktype, res->ai_protocol); if (lrs < 0) { perror("rsocket"); ret = lrs; goto free; } val = 1; ret = rsetsockopt(lrs, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val); if (ret) { perror("rsetsockopt SO_REUSEADDR"); goto close; } ret = rbind(lrs, res->ai_addr, res->ai_addrlen); if (ret) { perror("rbind"); goto close; } ret = rlisten(lrs, 1); if (ret) perror("rlisten"); close: if (ret) rclose(lrs); free: freeaddrinfo(res); return ret; }
/* * The server will start listening for the new connection, then send a * message to the active side when the listen is ready. This does leave * fork unsupported in the following case: the server is nonblocking and * calls select/poll waiting to receive data from the client. */ static void fork_passive(int socket) { struct sockaddr_in6 sin6; sem_t *sem; int lfd, sfd, dfd, ret, param; socklen_t len; uint32_t msg; sfd = fd_getd(socket); len = sizeof sin6; ret = real.getsockname(sfd, (struct sockaddr *) &sin6, &len); if (ret) goto out; sin6.sin6_flowinfo = sin6.sin6_scope_id = 0; memset(&sin6.sin6_addr, 0, sizeof sin6.sin6_addr); sem = sem_open("/rsocket_fork", O_CREAT | O_RDWR, S_IRWXU | S_IRWXG, 1); if (sem == SEM_FAILED) { ret = -1; goto out; } lfd = rsocket(sin6.sin6_family, SOCK_STREAM, 0); if (lfd < 0) { ret = lfd; goto sclose; } param = 1; rsetsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, ¶m, sizeof param); sem_wait(sem); ret = rbind(lfd, (struct sockaddr *) &sin6, sizeof sin6); if (ret) goto lclose; ret = rlisten(lfd, 1); if (ret) goto lclose; msg = 0; len = real.write(sfd, &msg, sizeof msg); if (len != sizeof msg) goto lclose; dfd = raccept(lfd, NULL, NULL); if (dfd < 0) { ret = dfd; goto lclose; } set_rsocket_options(dfd); copysockopts(dfd, sfd, &rs, &real); real.shutdown(sfd, SHUT_RDWR); real.close(sfd); fd_store(socket, dfd, fd_rsocket, fd_ready); lclose: rclose(lfd); sem_post(sem); sclose: sem_close(sem); out: if (ret) fd_store(socket, sfd, fd_normal, fd_ready); }