X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/9223880adde1ff3d7b8941ca474eab9acfa862c5..007694fe3d4ebd6577e1fb0a1017330b1a575a67:/src/surf/ns3/ns3_simulator.cc diff --git a/src/surf/ns3/ns3_simulator.cc b/src/surf/ns3/ns3_simulator.cc index 29fd20e182..199d6c68d6 100644 --- a/src/surf/ns3/ns3_simulator.cc +++ b/src/surf/ns3/ns3_simulator.cc @@ -5,6 +5,26 @@ * under the terms of the license (GNU LGPL) which comes with this package. */ #include "surf/ns3/ns3_simulator.h" +#include "xbt/dict.h" +#include "xbt/log.h" +#include "xbt/sysdep.h" + +using namespace ns3; +using namespace std; + +xbt_dict_t dict_socket = NULL; + +NS3Sim SimulatorNS3; + +static void receive_callback(Ptr localSocket); +static void send_callback(Ptr localSocket, uint32_t txSpace); +static void datasent_callback(Ptr localSocket, uint32_t dataSent); +static void StartFlow(Ptr sock, + const char *to, + uint16_t port_number); + +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simulator_ns3, surf, + "Logging specific to the SURF network NS3 module"); // Constructor. NS3Sim::NS3Sim(){ @@ -12,3 +32,154 @@ NS3Sim::NS3Sim(){ //Destructor. NS3Sim::~NS3Sim(){ } + +/* + * This function create a flow from src to dst + * + * Parameters + * src: node source + * dst: node destination + * port_number: The port number to use + * start: the time the communication start + * addr: ip address + * totalBytes: number of bytes to transmit + */ +void NS3Sim::create_flow_NS3( + Ptr src, + Ptr dst, + uint16_t port_number, + double start, + const char *addr, + uint32_t totalBytes, + void * action) +{ + if(!dict_socket) dict_socket = xbt_dict_new(); + + PacketSinkHelper sink ("ns3::TcpSocketFactory", + InetSocketAddress (Ipv4Address::GetAny(), + port_number)); + sink.Install (dst); + Ptr sock = Socket::CreateSocket (src, + TcpSocketFactory::GetTypeId()); + + MySocket *mysocket = new MySocket(); + mysocket->totalBytes = totalBytes; + mysocket->remaining = totalBytes; + mysocket->bufferedBytes = 0; + mysocket->sentBytes = 0; + mysocket->finished = 0; + mysocket->action = action; + xbt_dict_set(dict_socket,(const char*)&sock, mysocket,NULL); + sock->Bind(InetSocketAddress(port_number)); + Simulator::Schedule (Seconds(start),&StartFlow, sock, addr, port_number); +} + +void* NS3Sim::get_action_from_socket(void *socket){ + return ((MySocket *)socket)->action; +} + +char NS3Sim::get_finished(void *socket){ + return ((MySocket *)socket)->finished; +} + +double NS3Sim::get_remains_from_socket(void *socket){ + return ((MySocket *)socket)->remaining; +} + +double NS3Sim::get_sent_from_socket(void *socket){ + return ((MySocket *)socket)->sentBytes; +} + +void NS3Sim::simulator_stop(double min){ + if(min > 0.0) + Simulator::Stop(Seconds(min)); + else + Simulator::Stop(); +} + +void NS3Sim::simulator_start(void){ + XBT_DEBUG("Start simulator"); + Simulator::Run (); +} + +static void receive_callback(Ptr localSocket){ + MySocket* mysocket = (MySocket*)xbt_dict_get_or_null(dict_socket,(char*)&localSocket); + + if (mysocket->finished == 0){ + mysocket->finished = 1; +// cout << "[" << Simulator::Now ().GetSeconds() << "] " << "recv_cb of F[" << mysocket->totalBytes << "] " << endl; + XBT_DEBUG("Stop simulator at %f seconds", Simulator::Now().GetSeconds()); + Simulator::Stop(); + } +} + +static void send_callback(Ptr localSocket, uint32_t txSpace){ + MySocket* mysocket = (MySocket*)xbt_dict_get_or_null(dict_socket,(char*)&localSocket); + + if (mysocket->remaining == 0){ + //all data was already buffered (and socket was already closed), just return + return; + } + + uint32_t toWrite = min (mysocket->remaining, txSpace); + uint8_t *data = (uint8_t*)malloc(sizeof(uint8_t)*toWrite); + int amountSent = localSocket->Send (&data[0], toWrite, 0); + free (data); + if (amountSent > 0){ + mysocket->bufferedBytes += amountSent; + mysocket->remaining -= amountSent; + } +// cout << "[" << Simulator::Now ().GetSeconds() << "] " << "send_cb of F[" << mysocket->totalBytes << "] ("<< mysocket->remaining << " / " << mysocket->totalBytes << ") " << amountSent << " buffered." << endl; + + if (mysocket->remaining == 0){ + //everything was buffered to send, tell NS3 to close the socket + localSocket->Close(); + } + return; +} + +static void datasent_callback(Ptr localSocket, uint32_t dataSent){ + MySocket* mysocket = (MySocket*)xbt_dict_get_or_null(dict_socket,(char*)&localSocket); + mysocket->sentBytes += dataSent; +// cout << "[" << Simulator::Now ().GetSeconds() << "] " << "datasent_cb of F[" << mysocket->totalBytes << "] " << dataSent << " sent." << endl; +} + +static void normalClose_callback(Ptr localSocket){ + MySocket* mysocket = (MySocket*)xbt_dict_get_or_null(dict_socket,(char*)&localSocket); +// cout << "[" << Simulator::Now ().GetSeconds() << "] " << "normalClose_cb of F[" << mysocket->totalBytes << "]" << endl; + receive_callback (localSocket); +} + +static void errorClose_callback(Ptr localSocket){ + MySocket* mysocket = (MySocket*)xbt_dict_get_or_null(dict_socket,(char*)&localSocket); +// cout << "[" << Simulator::Now ().GetSeconds() << "] " << "errorClose_cb of F[" << mysocket->totalBytes << "]" << endl; + xbt_die("NS3: a socket was closed anormally"); +} + +static void succeededConnect_callback(Ptr localSocket){ + MySocket* mysocket = (MySocket*)xbt_dict_get_or_null(dict_socket,(char*)&localSocket); +// cout << "[" << Simulator::Now ().GetSeconds() << "] " << "succeededConnect_cb of F[" << mysocket->totalBytes << "]" << endl; +} + +static void failedConnect_callback(Ptr localSocket){ + MySocket* mysocket = (MySocket*)xbt_dict_get_or_null(dict_socket,(char*)&localSocket); +// cout << "[" << Simulator::Now ().GetSeconds() << "] " << "failedConnect_cb of F[" << mysocket->totalBytes << "]" << endl; + xbt_die("NS3: a socket failed to connect"); +} + +static void StartFlow(Ptr sock, + const char *to, + uint16_t port_number) +{ + InetSocketAddress serverAddr (to, port_number); + + sock->Connect(serverAddr); + sock->SetSendCallback (MakeCallback (&send_callback)); + sock->SetRecvCallback (MakeCallback (&receive_callback)); + sock->SetDataSentCallback (MakeCallback (&datasent_callback)); + sock->SetConnectCallback (MakeCallback (&succeededConnect_callback), MakeCallback (&failedConnect_callback)); + sock->SetCloseCallbacks (MakeCallback (&normalClose_callback), MakeCallback (&errorClose_callback)); + + MySocket* mysocket = (MySocket*)xbt_dict_get_or_null(dict_socket,(char*)&sock); +// cout << "[" << Simulator::Now().GetSeconds() << "] Starting flow to " << to << " using port " << port_number << endl; +}