Simultaneous Events - How to make them more predictable?

206 views
Skip to first unread message

João Loureiro

unread,
Jun 4, 2014, 11:01:33 AM6/4/14
to ns-3-...@googlegroups.com
Hi,

I have in my project, a mesh grid network of wired nodes, something like a Network on Chip. They are all connected p2p to the four neighbors around it.

There is a phase in the network, in which all the nodes send a given value in the four directions to its neighbors, and consequently receive four other values from each of its neighbors. Since it has four net-devices, it sends the packets sequentially in this order: East - South - West - North. I might expect that the east node, to receive the packet first, but this is not exactly what happens...

This phase is scheduled to starts at the same time, in all the nodes, since the nodes can be synchronous in the real scenario.

I'm wondering which is the best workaround for this problem, to make this a bit more sequential-like event. As it is right now, it is to much unpredictable.

I tough about adding some extra time between each transmission by each node, but in the reality, this could be done in parallel trough some sort of DMA channel, so it does not represent the exact reality of the problem. In reality, it should look more like a random order of receptions, due some minor clock drifts, but in my simulation, there is a clear pattern, which I guess, is related to the order in which the Net-Devices were created.

Tomasso suggested something here: https://groups.google.com/forum/#!searchin/ns-3-users/simultaneous$20events/ns-3-users/yJ-SJKhwwjY/IetnQzkiMxAJ         but i'm not exactly sure how to do it.

Appreciate the attention!

Cheers,

João 

Tommaso Pecorella

unread,
Jun 4, 2014, 5:34:14 PM6/4/14
to ns-3-...@googlegroups.com
Hi,

opposite to the post you linked, you actually *want* a synchronous operation (and with a reason). As a consequence... here's how to do it.

The problem is this. Assume that you have the following code:

Simulator::Schedule (Seconds (1.0), &AdvancePosition, nodeA);
Simulator::Schedule (Seconds (1.0), &AdvancePosition, nodeB);

What's the first node who will advance its position? Totally random (as you noticed).
For real it isn't random, but practically it is.

There are basically two solutions: 1) time advancement and 2) dirty trick.
The "clean" solution (i.e., priority scheduling) is not feasible for a number of reasons. Mostly lack of generality.

The "Time advancement" is based on this. Let's assume that the time is measured in nanoseconds. You can divide the time in a different way, i.e., use nanosecond but think in terms of deca-nanoseconds (i.e., loose one decimal precision).
In this way you can "trick" the simulator to precisely schedule the events in the order you want.
Let's do an example, using seconds and 10th of seconds as time reference.
- Event 1 at time 1.1
- Event 2 at time 1.2
BOTH events will be considered as executed at Time 2.0 (note, you have to advance your timer), and the first will happen before the second. 

This method is quite complex, and it requires to carefully consider all the time operations, applying the proper rounding where necessary. I'd classify it as "mostly an academic thing", at least until the Time class will not provide an unified way to split the "Time" between a time and a priority representation.

And this leads to the second option: the trick.
The trick is... don't schedule two events, schedule ONE event :)

Consider this: the following instruction:
Simulator::Schedule (Seconds (1.0), &AdvancePosition, nodeA);
means:
1) Simulator, advance the time. When 1 second is passed, please do this for me:
nodeA->AdvancePosition();

An event is a deferred function call.

If you look at it in this way, you can do this:
1) call a method (a single one) in due time and
2) have it call the receivers in the proper order by directly invoking the right functions.

This will force the right "event" ordering.... by avoiding events.
The bad part of this is that you'll loose all the fancy things of Events (for this particular case), like logging and so on.

There are a number of ways to do this trick. E.g., create a single "channel" instance between all the nodes, and have it arbitrate the messages. Alternatively, don't use events in your channel and have the source handle the delay. Many alternatives, but all share one thing: don't use Events (just for this particular thing).

Hope this helps,

T.

João Loureiro

unread,
Jun 5, 2014, 10:26:19 AM6/5/14
to ns-3-...@googlegroups.com
Thanks Tommaso.

I believe that the smallest overhead is implementing a nano-second offset between each transmission of each of the net devices of the same node. So I did it.

But iI'm havind some problem with the scheduling, which is beahaving not as it should. It schedules the transmission at the right time, but changes the beahaviour of the reception/retransmission... Maybe I'm doing something wrong. If you could take a look please.

Thank you!

João

USNSwitch::SendPacket(Ptr<const Packet> pck, uint8_t ports){
       
//check if it will be sent to more then one port, if positive, some time
       
//offset will be inserted between each transmission in order to guarantee
       
//the expected transmission sequence, from east to north, or 1 to 4
        uint8_t n_ports
= 0;
       
for (uint8_t i = 0 ; i < NumNetDevices; i++){ //loops to all the bits to check which port should the packet be sent to
           
if (((ports >> i) & 0b00000001) == 1){
                uint8_t port
= 0b00000001 << i;
               
               
Time t = Simulator::Now();
                t
+= NanoSeconds(n_ports);

               
Simulator::Schedule(t, &USNSwitch::SendSinglePacket, this, pck, port); //this should have worked, but it
                                                                                       
//inserts something like 2 seconds between transmissions
               
//SendSinglePacket(pck, port); //for testing the usage of the old function with the new logic. Works ok!

                n_ports
++;
           
}
       
}
   
}
   
   
void
   
USNSwitch::SendSinglePacket(Ptr<const Packet> pck, uint8_t ports) {

       
Ptr<Node> node = this->GetNode();
        uint8_t n_devices
= node->GetNDevices();

       
USNHeader hd;
        pck
->PeekHeader(hd);

//        NodeRef nr;
//        nr.x = 30;
//        nr.y = 44;

       
Time t = Simulator::Now();
        t
= t;
        m_switchTxTrace
(pck);

       
//starts sending the packets from port 1 to port 4.
       
for (uint32_t i = 0; i < NumNetDevices; i++) { //sends one packet per netdevice installed, according to the bitmask received
            uint8_t p
= ports >> i;
           
if ((p & 1) == 1) {
               
for (uint32_t j = 0; j < n_devices; j++) { //iterate to find which netdevice is the correct one
                   
if (node->GetDevice(j)->GetObject<USNNetDevice>()->GetUSNAddress() == i + 1) {

                       
//TODO: this should be replaced by callbacks urgently
                       
if (hd.GetUSNProtocol() == P_NETWORK_DISCOVERY) {
                           
PacketsSent [P_NETWORK_DISCOVERY]++;
                       
} else if (hd.GetUSNProtocol() == P_VALUE_ANNOUNCEMENT) {
                           
PacketsSent [P_VALUE_ANNOUNCEMENT]++;
                       
} else if (hd.GetUSNProtocol() == P_EVENT_ANNOUNCEMENT) {
                           
PacketsSent [P_EVENT_ANNOUNCEMENT]++;
                       
}

                        node
->GetDevice(j)->GetObject<USNNetDevice>()->Send(pck->Copy());

                       
break;
                   
}
               
}
           
}
       
}
   
}

João Loureiro

unread,
Jun 5, 2014, 11:00:35 AM6/5/14
to ns-3-...@googlegroups.com
Actually that was a very beginner mistake...

Time t = Simulator::Now();



I was adding the actual time to the schedule of the transmission. But it is already there. Problem solved.

Thanks again.

Tommaso Pecorella

unread,
Jun 5, 2014, 11:01:46 AM6/5/14
to ns-3-...@googlegroups.com
Hi,

it's a common mistake :)

The Schedule function wants the delay between the call and the event execution. I.e., the delta time. You're using an absolute time (Now + delta).

Cheers,

T.
Reply all
Reply to author
Forward
0 new messages