47 #include <arpa/inet.h>
49 #include <netinet/tcp.h>
50 #include <sys/socket.h>
51 #include <sys/types.h>
59 #include "debug/DistEthernet.hh"
60 #include "debug/DistEthernetCmd.hh"
63 #if defined(__FreeBSD__)
64 #include <netinet/in.h>
69 #if defined(__APPLE__) || defined(__MACH__)
71 #define MSG_NOSIGNAL SO_NOSIGPIPE
83 unsigned dist_rank,
unsigned dist_size,
87 DistIface(dist_rank, dist_size, sync_start, sync_repeat, em, use_pseudo_op,
88 is_switch, num_nodes), serverName(server_name),
89 serverPort(server_port), isSwitch(is_switch), listening(false)
93 DPRINTF(DistEthernet,
"TCPIface(listen): Can't bind port %d\n",
104 for (
int i = 0;
i <
size;
i++) {
106 DPRINTF(DistEthernet,
"First connection, waiting for link info\n");
108 panic(
"Failed to receive link info");
118 panic(
"Socket already listening!");
120 struct sockaddr_in sockaddr;
123 fdStatic = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
126 sockaddr.sin_family = PF_INET;
127 sockaddr.sin_addr.s_addr = INADDR_ANY;
128 sockaddr.sin_port = htons(port);
130 memset(&sockaddr.sin_zero, 0,
sizeof(sockaddr.sin_zero));
131 ret = ::bind(
fdStatic, (
struct sockaddr *)&sockaddr,
sizeof (sockaddr));
134 if (ret == -1 && errno != EADDRINUSE)
135 panic(
"ListenSocket(listen): bind() failed!");
140 if (errno != EADDRINUSE)
141 panic(
"ListenSocket(listen): listen() failed!");
154 static unsigned cur_rank = 0;
155 static unsigned cur_id = 0;
163 return cn.first.rank == cur_rank;
165 assert(iface0 !=
nodes.end());
166 assert(iface0->first.distIfaceId == 0);
167 sock = iface0->second;
171 DPRINTF(DistEthernet,
"Next connection, waiting for link info\n");
173 panic(
"Failed to receive link info");
174 assert(ni.
rank == cur_rank);
177 inform(
"Link okay (iface:%d -> (node:%d, iface:%d))",
196 DPRINTF(DistEthernet,
"Connected, waiting for ack (distIfaceId:%d\n",
199 panic(
"Failed to receive ack");
210 struct sockaddr_in sockaddr;
211 socklen_t slen =
sizeof (sockaddr);
215 if (setsockopt(
sock, IPPROTO_TCP, TCP_NODELAY, (
char *)&i,
217 warn(
"ListenSocket(accept): setsockopt() TCP_NODELAY failed!");
224 struct addrinfo addr_hint, *addr_results;
229 sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
230 panic_if(
sock < 0,
"socket() failed: %s", strerror(errno));
233 if (setsockopt(
sock, IPPROTO_TCP, TCP_NODELAY, (
char *)&fl,
sizeof(fl)) < 0)
234 warn(
"ConnectSocket(connect): setsockopt() TCP_NODELAY failed!");
236 bzero(&addr_hint,
sizeof(addr_hint));
237 addr_hint.ai_family = AF_INET;
238 addr_hint.ai_socktype = SOCK_STREAM;
239 addr_hint.ai_protocol = IPPROTO_TCP;
241 ret = getaddrinfo(
serverName.c_str(), port_str.c_str(),
242 &addr_hint, &addr_results);
243 panic_if(ret < 0,
"getaddrinf() failed: %s", strerror(errno));
245 DPRINTF(DistEthernet,
"Connecting to %s:%s\n",
248 ret =
::connect(
sock, (
struct sockaddr *)(addr_results->ai_addr),
249 addr_results->ai_addrlen);
250 panic_if(ret < 0,
"connect() failed: %s", strerror(errno));
252 freeaddrinfo(addr_results);
268 ret = ::send(sock, buf, length, MSG_NOSIGNAL);
270 if (errno == ECONNRESET || errno == EPIPE) {
271 exitSimLoop(
"Message server closed connection, simulation "
274 panic(
"send() failed: %s", strerror(errno));
277 panic_if(ret != length,
"send() failed");
285 ret = ::recv(sock, buf, length, MSG_WAITALL );
287 if (errno == ECONNRESET || errno == EPIPE)
288 inform(
"recv(): %s", strerror(errno));
290 panic(
"recv() failed: %s", strerror(errno));
291 }
else if (ret == 0) {
292 inform(
"recv(): Connection closed");
293 }
else if (ret != length)
294 panic(
"recv() failed");
296 return (ret == length);
309 DPRINTF(DistEthernetCmd,
"TCPIface::sendCmd() type: %d\n",
310 static_cast<int>(header.
msgType));
315 sendTCP(
s, (
void*)&header,
sizeof(header));
322 DPRINTF(DistEthernetCmd,
"TCPIface::recvHeader() type: %d ret: %d\n",
323 static_cast<int>(header.
msgType), ret);
332 panic_if(!ret,
"Error while reading socket");
panic_if(!root,"Invalid expression\n")
void initTransport() override
Init hook for the underlaying transport.
void sendCmd(const Header &header) override
Send out a control command to the remote end.
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.
static const int NumArgumentRegs M5_VAR_USED
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.
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.