44 #include <arpa/inet.h> 46 #include <netinet/tcp.h> 47 #include <sys/socket.h> 48 #include <sys/types.h> 57 #include "debug/DistEthernet.hh" 58 #include "debug/DistEthernetCmd.hh" 62 #if defined(__FreeBSD__) 63 #include <netinet/in.h> 68 #if defined(__APPLE__) || defined(__MACH__) 70 #define MSG_NOSIGNAL SO_NOSIGPIPE 82 unsigned dist_rank,
unsigned dist_size,
86 DistIface(dist_rank, dist_size, sync_start, sync_repeat, em, use_pseudo_op,
87 is_switch, num_nodes), serverName(server_name),
88 serverPort(server_port), isSwitch(is_switch), listening(false)
92 DPRINTF(DistEthernet,
"TCPIface(listen): Can't bind port %d\n",
103 for (
int i = 0;
i <
size;
i++) {
105 DPRINTF(DistEthernet,
"First connection, waiting for link info\n");
107 panic(
"Failed to receive link info");
117 panic(
"Socket already listening!");
119 struct sockaddr_in sockaddr;
122 fdStatic = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
125 sockaddr.sin_family = PF_INET;
126 sockaddr.sin_addr.s_addr = INADDR_ANY;
127 sockaddr.sin_port = htons(port);
129 memset(&sockaddr.sin_zero, 0,
sizeof(sockaddr.sin_zero));
130 ret = ::bind(
fdStatic, (
struct sockaddr *)&sockaddr,
sizeof (sockaddr));
133 if (ret == -1 && errno != EADDRINUSE)
134 panic(
"ListenSocket(listen): bind() failed!");
139 if (errno != EADDRINUSE)
140 panic(
"ListenSocket(listen): listen() failed!");
153 static unsigned cur_rank = 0;
154 static unsigned cur_id = 0;
162 return cn.first.rank == cur_rank;
164 assert(iface0 !=
nodes.end());
165 assert(iface0->first.distIfaceId == 0);
166 sock = iface0->second;
170 DPRINTF(DistEthernet,
"Next connection, waiting for link info\n");
172 panic(
"Failed to receive link info");
173 assert(ni.
rank == cur_rank);
176 inform(
"Link okay (iface:%d -> (node:%d, iface:%d))",
195 DPRINTF(DistEthernet,
"Connected, waiting for ack (distIfaceId:%d\n",
198 panic(
"Failed to receive ack");
209 struct sockaddr_in sockaddr;
210 socklen_t slen =
sizeof (sockaddr);
214 if (setsockopt(
sock, IPPROTO_TCP, TCP_NODELAY, (
char *)&i,
216 warn(
"ListenSocket(accept): setsockopt() TCP_NODELAY failed!");
223 struct addrinfo addr_hint, *addr_results;
228 sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
229 panic_if(
sock < 0,
"socket() failed: %s", strerror(errno));
232 if (setsockopt(
sock, IPPROTO_TCP, TCP_NODELAY, (
char *)&fl,
sizeof(fl)) < 0)
233 warn(
"ConnectSocket(connect): setsockopt() TCP_NODELAY failed!");
235 bzero(&addr_hint,
sizeof(addr_hint));
236 addr_hint.ai_family = AF_INET;
237 addr_hint.ai_socktype = SOCK_STREAM;
238 addr_hint.ai_protocol = IPPROTO_TCP;
240 ret = getaddrinfo(
serverName.c_str(), port_str.c_str(),
241 &addr_hint, &addr_results);
242 panic_if(ret < 0,
"getaddrinf() failed: %s", strerror(errno));
244 DPRINTF(DistEthernet,
"Connecting to %s:%s\n",
247 ret =
::connect(
sock, (
struct sockaddr *)(addr_results->ai_addr),
248 addr_results->ai_addrlen);
249 panic_if(ret < 0,
"connect() failed: %s", strerror(errno));
251 freeaddrinfo(addr_results);
267 ret = ::send(sock, buf, length, MSG_NOSIGNAL);
269 if (errno == ECONNRESET || errno == EPIPE) {
270 exitSimLoop(
"Message server closed connection, simulation " 273 panic(
"send() failed: %s", strerror(errno));
276 panic_if(ret != length,
"send() failed");
284 ret = ::recv(sock, buf, length, MSG_WAITALL );
286 if (errno == ECONNRESET || errno == EPIPE)
287 inform(
"recv(): %s", strerror(errno));
289 panic(
"recv() failed: %s", strerror(errno));
290 }
else if (ret == 0) {
291 inform(
"recv(): Connection closed");
292 }
else if (ret != length)
293 panic(
"recv() failed");
295 return (ret == length);
308 DPRINTF(DistEthernetCmd,
"TCPIface::sendCmd() type: %d\n",
309 static_cast<int>(header.
msgType));
314 sendTCP(
s, (
void*)&header,
sizeof(header));
321 DPRINTF(DistEthernetCmd,
"TCPIface::recvHeader() type: %d ret: %d\n",
322 static_cast<int>(header.
msgType), ret);
331 panic_if(!ret,
"Error while reading socket");
#define panic(...)
This implements a cprintf based panic() function.
void initTransport() override
Init hook for the underlaying transport.
void sendCmd(const Header &header) override
Send out a control command to the remote end.
Overload hash function for BasicBlockRange type.
TCPIface(std::string server_name, unsigned server_port, unsigned dist_rank, unsigned dist_size, Tick sync_start, Tick sync_repeat, EventManager *em, bool use_pseudo_op, bool is_switch, int num_nodes)
The ctor creates and connects the stream socket to the server.
uint64_t Tick
Tick count type.
std::shared_ptr< EthPacketData > EthPacketPtr
void recvPacket(const Header &header, EthPacketPtr &packet) override
Receive a packet from the remote end.
void sendTCP(int sock, const void *buf, unsigned length)
Send out a message through a TCP stream socket.
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
static std::vector< int > sockRegistry
Storage for all opened sockets.
void establishConnection()
unsigned size
The number of gem5 processes comprising this dist simulation.
bool recvTCP(int sock, void *buf, unsigned length)
Receive the next incoming message through a TCP stream socket.
bool recvHeader(Header &header) override
Receive a header (i.e.
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
unsigned distIfaceId
Unique id for the dist link.
static unsigned distIfaceNum
Number of DistIface objects (i.e.
Compute node info and storage for the very first connection from each node (used by the switch) ...
int sock
The stream socket to connect to the server.
static std::vector< std::pair< NodeInfo, int > > nodes
The interface class to talk to peer gem5 processes.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
const std::string to_string(sc_enc enc)
void sendPacket(const Header &header, const EthPacketPtr &packet) override
Send out a data packet to the remote end.
unsigned rank
The rank of this process among the gem5 peers.