]>
git.proxmox.com Git - ceph.git/blob - ceph/src/msg/async/net_handler.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2014 UnitedStack <haomai@unitedstack.com>
8 * Author: Haomai Wang <haomaiwang@gmail.com>
10 * This is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License version 2.1, as published by the Free Software
13 * Foundation. See file COPYING.
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <netinet/ip.h>
21 #include <netinet/tcp.h>
22 #include <arpa/inet.h>
24 #include "net_handler.h"
25 #include "common/errno.h"
26 #include "common/debug.h"
28 #define dout_subsys ceph_subsys_ms
30 #define dout_prefix *_dout << "NetHandler "
34 int NetHandler::create_socket(int domain
, bool reuse_addr
)
39 if ((s
= ::socket(domain
, SOCK_STREAM
, 0)) == -1) {
41 lderr(cct
) << __func__
<< " couldn't create socket " << cpp_strerror(r
) << dendl
;
45 #if !defined(__FreeBSD__)
46 /* Make sure connection-intensive things like the benchmark
47 * will be able to close/open sockets a zillion of times */
50 if (::setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, &on
, sizeof(on
)) == -1) {
52 lderr(cct
) << __func__
<< " setsockopt SO_REUSEADDR failed: "
53 << strerror(r
) << dendl
;
63 int NetHandler::set_nonblock(int sd
)
68 /* Set the socket nonblocking.
69 * Note that fcntl(2) for F_GETFL and F_SETFL can't be
70 * interrupted by a signal. */
71 if ((flags
= fcntl(sd
, F_GETFL
)) < 0 ) {
73 lderr(cct
) << __func__
<< " fcntl(F_GETFL) failed: " << cpp_strerror(r
) << dendl
;
76 if (fcntl(sd
, F_SETFL
, flags
| O_NONBLOCK
) < 0) {
78 lderr(cct
) << __func__
<< " fcntl(F_SETFL,O_NONBLOCK): " << cpp_strerror(r
) << dendl
;
85 void NetHandler::set_close_on_exec(int sd
)
87 int flags
= fcntl(sd
, F_GETFD
, 0);
90 lderr(cct
) << __func__
<< " fcntl(F_GETFD): "
91 << cpp_strerror(r
) << dendl
;
94 if (fcntl(sd
, F_SETFD
, flags
| FD_CLOEXEC
)) {
96 lderr(cct
) << __func__
<< " fcntl(F_SETFD): "
97 << cpp_strerror(r
) << dendl
;
101 int NetHandler::set_socket_options(int sd
, bool nodelay
, int size
)
104 // disable Nagle algorithm?
107 r
= ::setsockopt(sd
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&flag
, sizeof(flag
));
110 ldout(cct
, 0) << "couldn't set TCP_NODELAY: " << cpp_strerror(r
) << dendl
;
114 r
= ::setsockopt(sd
, SOL_SOCKET
, SO_RCVBUF
, (void*)&size
, sizeof(size
));
117 ldout(cct
, 0) << "couldn't set SO_RCVBUF to " << size
<< ": " << cpp_strerror(r
) << dendl
;
122 #ifdef CEPH_USE_SO_NOSIGPIPE
124 r
= ::setsockopt(sd
, SOL_SOCKET
, SO_NOSIGPIPE
, (void*)&val
, sizeof(val
));
127 ldout(cct
,0) << "couldn't set SO_NOSIGPIPE: " << cpp_strerror(r
) << dendl
;
133 void NetHandler::set_priority(int sd
, int prio
, int domain
)
139 #ifdef IPTOS_CLASS_CS6
140 int iptos
= IPTOS_CLASS_CS6
;
144 r
= ::setsockopt(sd
, IPPROTO_IP
, IP_TOS
, &iptos
, sizeof(iptos
));
147 r
= ::setsockopt(sd
, IPPROTO_IPV6
, IPV6_TCLASS
, &iptos
, sizeof(iptos
));
150 lderr(cct
) << "couldn't set ToS of unknown family (" << domain
<< ")"
151 << " to " << iptos
<< dendl
;
156 ldout(cct
,0) << "couldn't set TOS to " << iptos
157 << ": " << cpp_strerror(r
) << dendl
;
160 #endif // IPTOS_CLASS_CS6
161 // setsockopt(IPTOS_CLASS_CS6) sets the priority of the socket as 0.
162 // See http://goo.gl/QWhvsD and http://goo.gl/laTbjT
163 // We need to call setsockopt(SO_PRIORITY) after it.
164 r
= ::setsockopt(sd
, SOL_SOCKET
, SO_PRIORITY
, &prio
, sizeof(prio
));
167 ldout(cct
, 0) << __func__
<< " couldn't set SO_PRIORITY to " << prio
168 << ": " << cpp_strerror(r
) << dendl
;
172 #endif // SO_PRIORITY
175 int NetHandler::generic_connect(const entity_addr_t
& addr
, const entity_addr_t
&bind_addr
, bool nonblock
)
178 int s
= create_socket(addr
.get_family());
183 ret
= set_nonblock(s
);
190 set_socket_options(s
, cct
->_conf
->ms_tcp_nodelay
, cct
->_conf
->ms_tcp_rcvbuf
);
193 entity_addr_t addr
= bind_addr
;
194 if (cct
->_conf
->ms_bind_before_connect
&& (!addr
.is_blank_ip())) {
196 ret
= ::bind(s
, addr
.get_sockaddr(), addr
.get_sockaddr_len());
199 ldout(cct
, 2) << __func__
<< " client bind error " << ", " << cpp_strerror(ret
) << dendl
;
206 ret
= ::connect(s
, addr
.get_sockaddr(), addr
.get_sockaddr_len());
209 if (errno
== EINPROGRESS
&& nonblock
)
212 ldout(cct
, 10) << __func__
<< " connect: " << cpp_strerror(ret
) << dendl
;
220 int NetHandler::reconnect(const entity_addr_t
&addr
, int sd
)
223 int ret
= ::connect(sd
, addr
.get_sockaddr(), addr
.get_sockaddr_len());
225 if (ret
< 0 && errno
!= EISCONN
) {
227 ldout(cct
, 10) << __func__
<< " reconnect: " << strerror(r
) << dendl
;
228 if (r
== EINPROGRESS
|| r
== EALREADY
)
236 int NetHandler::connect(const entity_addr_t
&addr
, const entity_addr_t
& bind_addr
)
238 return generic_connect(addr
, bind_addr
, false);
241 int NetHandler::nonblock_connect(const entity_addr_t
&addr
, const entity_addr_t
& bind_addr
)
243 return generic_connect(addr
, bind_addr
, true);