1 /* Copyright (c) 2007-2014. The SimGrid Team.
2 * All rights reserved. */
4 /* This program is free software; you can redistribute it and/or modify it
5 * under the terms of the license (GNU LGPL) which comes with this package. */
7 #include "src/surf/ns3/ns3_simulator.h"
10 #include "xbt/sysdep.h"
12 xbt_dict_t dict_socket = NULL;
15 static char socket_key[24];
17 static void receive_callback(ns3::Ptr<ns3::Socket> localSocket);
18 static void send_callback(ns3::Ptr<ns3::Socket> localSocket, uint32_t txSpace);
19 static void datasent_callback(ns3::Ptr<ns3::Socket> localSocket, uint32_t dataSent);
20 static void StartFlow(ns3::Ptr<ns3::Socket> sock, const char *to, uint16_t port_number);
22 XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(ns3);
27 static inline void transformSocketPtr (ns3::Ptr<ns3::Socket> localSocket)
29 std::stringstream sstream;
30 sstream << localSocket ;
31 std::string s = sstream.str();
32 sprintf(socket_key,"%s",s.c_str());
35 static void delete_mysocket(void *p)
37 MySocket *sock = (MySocket *)p;
42 * This function creates a flow from src to dst
46 * dst: node destination
47 * port_number: The port number to use
48 * start: the time the communication start
50 * totalBytes: number of bytes to transmit
52 void NS3Sim::create_flow_NS3(ns3::Ptr<ns3::Node> src, ns3::Ptr<ns3::Node> dst, uint16_t port_number,
53 double startTime, const char *ipAddr, uint32_t totalBytes,
54 simgrid::surf::NetworkNS3Action * action)
57 dict_socket = xbt_dict_new_homogeneous(delete_mysocket);
59 ns3::PacketSinkHelper sink("ns3::TcpSocketFactory", ns3::InetSocketAddress (ns3::Ipv4Address::GetAny(), port_number));
62 ns3::Ptr<ns3::Socket> sock = ns3::Socket::CreateSocket (src, ns3::TcpSocketFactory::GetTypeId());
64 MySocket *mysocket = new MySocket();
65 mysocket->totalBytes = totalBytes;
66 mysocket->remaining = totalBytes;
67 mysocket->action = action;
69 transformSocketPtr(sock);
70 xbt_dict_set(dict_socket,socket_key, mysocket,NULL);
72 sock->Bind(ns3::InetSocketAddress(port_number));
73 XBT_DEBUG("Create flow starting to %fs + %fs = %fs",
74 startTime-ns3::Simulator::Now().GetSeconds(), ns3::Simulator::Now().GetSeconds(), startTime);
76 ns3::Simulator::Schedule (ns3::Seconds(startTime-ns3::Simulator::Now().GetSeconds()),
77 &StartFlow, sock, ipAddr, port_number);
80 void NS3Sim::simulator_start(double min){
82 ns3::Simulator::Stop(ns3::Seconds(min));
83 XBT_DEBUG("Start simulator '%f'",min);
84 ns3::Simulator::Run ();
87 static MySocket* get_my_socket(ns3::Ptr<ns3::Socket> localSocket) {
88 transformSocketPtr(localSocket);
89 return (MySocket*)xbt_dict_get_or_null(dict_socket,socket_key);
92 static void receive_callback(ns3::Ptr<ns3::Socket> localSocket){
93 MySocket* mysocket = get_my_socket(localSocket);
95 if (mysocket->finished == false){
96 mysocket->finished = true;
97 XBT_DEBUG("recv_cb of F[%p, %p, %d]", mysocket, mysocket->action, mysocket->totalBytes);
98 XBT_DEBUG("Stop simulator at %f seconds", ns3::Simulator::Now().GetSeconds());
99 ns3::Simulator::Stop(ns3::Seconds(0.0));
100 ns3::Simulator::Run();
104 static void send_callback(ns3::Ptr<ns3::Socket> localSocket, uint32_t txSpace){
105 MySocket* mysocket = get_my_socket(localSocket);
107 if (mysocket->remaining == 0){
108 // all data was already buffered (and socket was already closed), just return
112 uint8_t *data = (uint8_t*)malloc(sizeof(uint8_t)*txSpace);
114 while (mysocket->bufferedBytes < mysocket->totalBytes
115 && localSocket->GetTxAvailable () > 0)
117 uint32_t toWrite = std::min ((mysocket->remaining), txSpace);
118 toWrite = std::min (toWrite, localSocket->GetTxAvailable ());
119 int amountSent = localSocket->Send (data, toWrite, 0);
123 (mysocket->bufferedBytes) += amountSent;
124 (mysocket->remaining) -= amountSent;
125 XBT_DEBUG("send_cb of F[%p, %p, %d] (%d/%d) %d buffered", mysocket, mysocket->action, mysocket->totalBytes, mysocket->remaining, mysocket->totalBytes, amountSent);
131 if ((mysocket->bufferedBytes) >= mysocket->totalBytes)
132 localSocket->Close();
135 static void datasent_callback(ns3::Ptr<ns3::Socket> localSocket, uint32_t dataSent){
136 MySocket* mysocket = get_my_socket(localSocket);
137 mysocket->sentBytes += dataSent;
138 XBT_DEBUG("datasent_cb of F[%p, %p, %d] %d sent", mysocket, mysocket->action, mysocket->totalBytes, dataSent);
141 static void normalClose_callback(ns3::Ptr<ns3::Socket> localSocket){
142 MySocket* mysocket = get_my_socket(localSocket);
143 XBT_DEBUG("normalClose_cb of F[%p, %p, %d]", mysocket, mysocket->action, mysocket->totalBytes);
144 receive_callback (localSocket);
147 static void errorClose_callback(ns3::Ptr<ns3::Socket> localSocket){
148 MySocket* mysocket = get_my_socket(localSocket);
149 XBT_DEBUG("errorClose_cb of F[%p, %p, %d]", mysocket, mysocket->action, mysocket->totalBytes);
150 xbt_die("NS3: a socket was closed anormally");
153 static void succeededConnect_callback(ns3::Ptr<ns3::Socket> localSocket){
154 MySocket* mysocket = get_my_socket(localSocket);
155 XBT_DEBUG("succeededConnect_cb of F[%p, %p, %d]", mysocket, mysocket->action, mysocket->totalBytes);
158 static void failedConnect_callback(ns3::Ptr<ns3::Socket> localSocket){
159 MySocket* mysocket = get_my_socket(localSocket);
160 XBT_DEBUG("failedConnect_cb of F[%p, %p, %d]", mysocket, mysocket->action, mysocket->totalBytes);
161 xbt_die("NS3: a socket failed to connect");
164 static void StartFlow(ns3::Ptr<ns3::Socket> sock, const char *to, uint16_t port_number)
166 ns3::InetSocketAddress serverAddr (to, port_number);
168 sock->Connect(serverAddr);
169 sock->SetSendCallback (MakeCallback (&send_callback));
170 sock->SetRecvCallback (MakeCallback (&receive_callback));
171 sock->SetDataSentCallback (MakeCallback (&datasent_callback));
172 sock->SetConnectCallback (MakeCallback (&succeededConnect_callback), MakeCallback (&failedConnect_callback));
173 sock->SetCloseCallbacks (MakeCallback (&normalClose_callback), MakeCallback (&errorClose_callback));
175 MySocket* mysocket = get_my_socket(sock);
176 XBT_DEBUG("startFlow_cb of F[%p, %p, %d] dest=%s port=%d", mysocket, mysocket->action, mysocket->totalBytes, to, port_number);