A few questions on ns3

487 views
Skip to first unread message

CL

unread,
Mar 7, 2017, 1:56:46 PM3/7/17
to ns-3-users


Hi,

I've been working on ns3 for some time now but there are still a few things that I do not understand. My goal is to build a network as shown below. ex_app is an external software sending/receiving data with ns3 through normal tcp/ip sockets. all nodes are on a csma channel with an openflow csma switch to route packets


    // Network topology
    //
     //        n0 n1 n2 n3 n4     
    //          |    |    |    |   |  
    //       -------------------------
    //       |   csma Switch   |
    //       -------------------------
    //        |        |          |
    //        n5    n6       n7
    //  
    //    information flows:
    //           
    //        ex_app->n0->csma_switch->{n5,n6}    
    //        n5->ex_app and n6->ex_app
    //   
    //        ex_app->n1 ex_app->n2 ex_app->n3 ex_app->n4
    //        {n1,n2,n3,n4}->csma_switch->n7->ex_app
    //

I've attached the code and I can also add the additional files if needed. My main questions are:

1)
    for (double s=0; s<100000; s++){
   
Simulator::Schedule(MicroSeconds (s*100), &read_pkt1, echoClient1, clientApps1, echoClient2, clientApps2);
   
Simulator::Schedule(MicroSeconds (s*100), &read_pkt2, echoClient3, clientApps3);
   
}


Is this the right way to schedule events? I need to call the functions read_pkt1 and read_pkt2 every 100 us for 100000 times ie for 10 secs. I also pass echoClient1 etc. as parameters to the function. read_pkt1 and read_pkt2 are almost the same, its just that I can't seem to pass more than 4 parameters to a function in the scheduler without it throwing an error.

2)
    // set the packet size
    echoClient1
.SetAttribute ("PacketSize", UintegerValue (msg1.str().length()));
   
// set the data
    echoClient1
.SetFill (clientApps1.Get (0), (uint8_t*) msg1.str().c_str(), msg1.str().length(), msg1.str().length());

Is this the right way to send a packet of my own data in ns3? msg1 is a std::ostringstream string for ex "hello world"

3)
    Ptr<Socket> source1 = Socket::CreateSocket (terminals.Get (0), tid);
   
InetSocketAddress remote1 = InetSocketAddress (Ipv4Address::GetAny (), 40);
    source1
->Connect (remote1);
   
///////Repeat above 5 times for 5 nodes. Full code in file attached.

   
Ptr<Socket> recvSink1 = Socket::CreateSocket (terminals.Get (5), tid);
   
InetSocketAddress local1 = InetSocketAddress (Ipv4Address::GetAny (), 9);
    recvSink1
->Bind (local1);
    recvSink1
->SetRecvCallback (MakeBoundCallback (&Send_pkt,2));
   

///////Repeat above 3 times for 3 nodes. Full code in file attached.

   
UdpEchoClientHelper echoClient1 (interfaces.GetAddress (5), 9);
    echoClient1
.SetAttribute ("Interval", TimeValue (MilliSeconds (1)));
    echoClient1
.SetAttribute ("MaxPackets", UintegerValue (100000000));
   
ApplicationContainer clientApps1 = echoClient1.Install (terminals.Get (0));
   
   
UdpEchoClientHelper echoClient2 (interfaces.GetAddress (6), 10);
    echoClient2
.SetAttribute ("Interval", TimeValue (MilliSeconds (1)));
    echoClient2
.SetAttribute ("MaxPackets", UintegerValue (100000000));
   
ApplicationContainer clientApps2 = echoClient2.Install (terminals.Get (0));
   
   
UdpEchoClientHelper echoClient3 (interfaces.GetAddress (7), 11);
    echoClient3
.SetAttribute ("Interval", TimeValue (MilliSeconds (1)));
    echoClient3
.SetAttribute ("MaxPackets", UintegerValue (100000000));
   
ApplicationContainer clientApps3 = echoClient3.Install (terminals.Get (0));


Finally and this is the part I'm sure I've got wrong.

I want to use nodes 0,1,2,3,4 as a source of packets. They must rx packets from the external app and send them through the switch to the other nodes.

Likewise nodes 5,6,7 are sinks and as soon as the receive a packet (through ns3), they make a callback to the Send_pkt fn which then sends the packets to the external app

I'm not sure whether to put nodes 0,1,2,3,4 or 5,6,7 as the terminals for udpechoclient. I assume its 0,1,2,3,4 because these are the nodes I send packets through? Also where do I install the udpechoclienthelper object?

Basically what do I write here?

    UdpEchoClientHelper echoClient1 (interfaces.GetAddress (5), 9);
and here?
   
ApplicationContainer clientApps2 = echoClient2.Install (terminals.Get (0));

Can I use UdpEchoClientHelper without a server? My main goal was to just use the setfill function of udpechoclient. I don't want the packets to echo back, just to be sent every 1 ms and every time the data depends on whats put in using setfill.

Thanks
working.cc

Tommaso Pecorella

unread,
Mar 7, 2017, 4:47:51 PM3/7/17
to ns-3-users
Hi,

I'll be short:
1) Yes, it't the right way. Recently we added also a 6-params Schedule, but maybe it's not in 3.26.
2) Yes, but from the looks of it you messed up with the function calls. Probably you copy-pasted the functions definitions.
3) Yes, you can use UdpClient without UdpServer. For your case you'll need your own application to receive and re-send the packets.

Cheers,

T.

pdbarnes

unread,
Mar 8, 2017, 12:25:02 AM3/8/17
to ns-3-users
I'm usually wrong when I contradict Tommaso, but here goes anyway:

> 1) Yes, it't the right way.

It's *a* way, but arguably not the best way, because it uses a lot of memory, and slows down the execution to have so many events in the Scheduler. Instead, schedule just the first read_pktx call, then have those functions Schedule the next call. Kind of like tail recursion.

Peter

CL

unread,
Mar 8, 2017, 10:52:34 AM3/8/17
to ns-3-users
Thank you Tom, I think I figured it out. It should be:

UdpEchoClientHelper echoClient1 (interfaces.GetAddress (sink node), 9);

    echoClient1.SetAttribute ("Interval", TimeValue (MilliSeconds (1)));
    echoClient1.SetAttribute ("MaxPackets", UintegerValue (100000000));
    ApplicationContainer clientApps1 = echoClient1.Install (terminals.Get (source node));

Could you elaborate more on where I messed up in 2? It seems to work as I can see the data in the pcap files.

CL

unread,
Mar 8, 2017, 11:14:31 AM3/8/17
to ns-3-users
Hi Peter,

Thanks for that answer! Since ns3 needs to work with my external application, I've noticed its really slow, maybe 1000 times slower than the other one.

I get what you're saying but just wanted to double check how to implement it. It should be:

Simulator::Schedule(MicroSeconds (0), &read_pkt1, echoClient1, clientApps1, echoClient2, clientApps2);
Simulator::Schedule(MicroSeconds (0), &read_pkt2, echoClient3, clientApps3, echoClient4, clientApps4);
Simulator::Schedule(MicroSeconds (0), &read_pkt3, echoClient5, clientApps5, echoClient6, clientApps6);

in the main function and within each sub function read_pktx:

probably declare a global variable or pass a parameter say "count"

void read_pktx(UdpEchoClientHelper echoClientx, ApplicationContainer clientAppsx, UdpEchoClientHelper echoClientx, ApplicationContainer clientAppsx){

     // do stuff

     if(count < 100000){
       
        
Simulator
::Schedule(MicroSeconds (count * 100), &read_pktx, echoClientx, clientAppsx, echoClientx, clientAppsx);
         count++;
     }
}

Won't this use more memory since it's recursive and I don't need recursive? I mean the previous function calls will still have their variables on stack right? Or does waf optimize for this?

CL

unread,
Mar 8, 2017, 11:27:17 AM3/8/17
to ns-3-users
I cant seem to edit my previous post so here goes,

What do you mean by "
For your case you'll need your own application to receive and re-send the packets."

My application does receive the packets fine, but does not send them back. Is that a problem? Does the udpechoclient use up memory/resources just waiting for my echoes back (around 10000000 packets)? That is what I meant when I asked can we use the echoclient without an echoserver.

Thanks!


pdbarnes

unread,
Mar 9, 2017, 12:06:26 AM3/9/17
to ns-3-users


On Wednesday, March 8, 2017 at 8:27:17 AM UTC-8, CL wrote:
 can we use the echoclient without an echoserver.

Yes, by sending to the discard port, 9, as Tommaso showed.

Peter 

pdbarnes

unread,
Mar 9, 2017, 12:11:45 AM3/9/17
to ns-3-users


On Wednesday, March 8, 2017 at 8:14:31 AM UTC-8, CL wrote:

Simulator::Schedule(MicroSeconds (0), &read_pkt1, echoClient1, clientApps1, echoClient2, clientApps2);
Simulator::Schedule(MicroSeconds (0), &read_pkt2, echoClient3, clientApps3, echoClient4, clientApps4);
Simulator::Schedule(MicroSeconds (0), &read_pkt3, echoClient5, clientApps5, echoClient6, clientApps6);

in the main function and within each sub function read_pktx:

probably declare a global variable or pass a parameter say "count"

void read_pktx(UdpEchoClientHelper echoClientx, ApplicationContainer clientAppsx, UdpEchoClientHelper echoClientx, ApplicationContainer clientAppsx){

     // do stuff

     if(count < 100000){
       
        
Simulator
::Schedule(MicroSeconds (count * 100), &read_pktx, echoClientx, clientAppsx, echoClientx, clientAppsx);
         count++;
     }
}

Won't this use more memory since it's recursive and I don't need recursive? I mean the previous function calls will still have their variables on stack right? Or does waf optimize for this?

This is almost exactly what I was thinking, except I would use Simulator::Stop() in the main function, rather than count packets in these callback functions.

It's not recursive (it just looks that way).  The first event is scheduled in the main function. When that event executes it schedules the next call to the the event handler read_pktx.  That way you only have one event at a time on the Scheduler queue (for each read_pktx), which saves memory and time.  When the current event completes (returns to the Simulator) the Simulator will reclaim the event memory, yielding the memory savings.

CL

unread,
Mar 10, 2017, 12:20:55 PM3/10/17
to ns-3-users
Hey Peter,

I just tried your suggestion but unfortunately it was slower than the for loop. If you have any more ideas on how to make it faster please let me know.

To synchronize ns3 with the external app, i use a clock signal from the app and run ns3 to that. I've modified the wall clock synchronizer files for that. It works, but i guess that's why it slow. If you or Tom have any suggestions on how to make it faster, I would appreciate it.

I know ns3 receives the clock signals in tandem with that being sent (i just printed it on the terminal from wall clock sync), but after that it slows down dramatically while executing my code. If I don't use the real time clock, it self synchronizes but there is a random amount of delay involved, so I'm not sure where to look for this delay.

pdbarnes

unread,
Mar 10, 2017, 3:45:44 PM3/10/17
to ns-3-users

On Friday, March 10, 2017 at 9:20:55 AM UTC-8, CL wrote:
To synchronize ns3 with the external app, i use a clock signal from the app and run ns3 to that. I've modified the wall clock synchronizer files for that. It works, but i guess that's why it slow. If you or Tom have any suggestions on how to make it faster, I would appreciate it.

I know ns3 receives the clock signals in tandem with that being sent (i just printed it on the terminal from wall clock sync), but after that it slows down dramatically while executing my code. If I don't use the real time clock, it self synchronizes but there is a random amount of delay involved, so I'm not sure where to look for this delay.

0.  When you say it's really slow, "1000 times slower," please give more information.  How many packets are being simulated?  How much wall time does it take?  What are you comparing to when you say "slower"?

1. Can you run the ns-3 portion, without connecting or synchronizing with the external app?  Or substitute an ns-3 Application in place of the external app?  How fast does it run in this stand-alone case, with the default scheduler (instead of wall-clock variants) ?  These tests will tell how fast ns-3 can run your model with OpenFlow in the best case. Is this fast enough?

2.  Can you replace the OpenFlow switch with a simple ns-3 router node?  How fast does it run now?  If this is significantly faster than step 1, then OpenFlow might be the bottleneck.

2. Can you use the unmodified real-time scheduler?  And throttle your external app to something reasonable?  Is ns-3 able to keep up with real time?

Peter

CL

unread,
Mar 16, 2017, 12:44:40 AM3/16/17
to ns-3-users
Hi Peter,

Sorry for the delay in my reply. I was focused on making my project work. I've got it working now. Your questions really helped me solve the problem. It was essentially your last point


Can you use the unmodified real-time scheduler?  And throttle your external app to something reasonable?  Is ns-3 able to keep up with real time?


Ns3 was unable to keep up since the external app moving forward and there was no feedback loop telling it to wait for ns3. I've done that now and it works well. Thanks for your time and patience.
Reply all
Reply to author
Forward
0 new messages