A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
animation-interface.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation;
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15  *
16  * Author: George F. Riley<riley@ece.gatech.edu>
17  * Modified by: John Abraham <john.abraham@gatech.edu>
18  */
19 
20 // Interface between ns3 and the network animator
21 
22 
23 // ns3 includes
24 #include "ns3/animation-interface.h"
25 #include "ns3/channel.h"
26 #include "ns3/config.h"
27 #include "ns3/node.h"
28 #include "ns3/mobility-model.h"
29 #include "ns3/packet.h"
30 #include "ns3/simulator.h"
31 #include "ns3/animation-interface-helper.h"
32 #include "ns3/wifi-mac-header.h"
33 #include "ns3/wimax-mac-header.h"
34 #include "ns3/wifi-net-device.h"
35 #include "ns3/wifi-mac.h"
36 #include "ns3/constant-position-mobility-model.h"
37 #include "ns3/lte-ue-phy.h"
38 #include "ns3/lte-enb-phy.h"
39 #include "ns3/uan-net-device.h"
40 #include "ns3/uan-mac.h"
41 #include "ns3/ipv4.h"
42 
43 #include <stdio.h>
44 #include <unistd.h>
45 #include <sstream>
46 #include <fstream>
47 #include <string>
48 #include <iomanip>
49 #include <map>
50 
51 NS_LOG_COMPONENT_DEFINE ("AnimationInterface");
52 
53 namespace ns3 {
54 
55 #define PURGE_INTERVAL 5
56 
57 static bool initialized = false;
58 std::map <uint32_t, std::string> AnimationInterface::nodeDescriptions;
59 std::map <uint32_t, Rgb> AnimationInterface::nodeColors;
60 std::map <P2pLinkNodeIdPair, LinkProperties, LinkPairCompare> AnimationInterface::linkProperties;
61 
62 
63 AnimationInterface::AnimationInterface (const std::string fn, uint64_t maxPktsPerFile, bool usingXML)
64  : m_xml (usingXML), m_mobilityPollInterval (Seconds(0.25)),
65  m_outputFileName (fn),
66  m_outputFileSet (false), gAnimUid (0), m_randomPosition (true),
67  m_writeCallback (0), m_started (false),
68  m_enablePacketMetadata (false), m_startTime (Seconds(0)), m_stopTime (Seconds(3600 * 1000)),
69  m_maxPktsPerFile (maxPktsPerFile), m_originalFileName (fn)
70 {
71  m_uniformRandomVariable = CreateObject<UniformRandomVariable> ();
72 
73  initialized = true;
74  StartAnimation ();
75 }
76 
78 {
79  StopAnimation ();
80 }
81 
83 {
84  NS_LOG_INFO ("XML output set");
85  m_xml = true;
86 }
87 
88 
90 {
91  static int i = 0;
92  std::ostringstream oss;
93  oss << i;
96  {
97  return;
98  }
99  StopAnimation ();
100  m_outputFileName = m_originalFileName + "-" + oss.str ();
101  StartAnimation (true);
102  ++i;
103 
104 }
105 
107 {
108  return "netanim-3.101";
109 }
110 
112 {
113  m_startTime = t;
114 }
115 
117 {
118  m_stopTime = t;
119 }
120 
121 bool AnimationInterface::SetOutputFile (const std::string& fn)
122 {
123  if (m_outputFileSet)
124  {
125  return true;
126  }
127  NS_LOG_INFO ("Creating new trace file:" << fn.c_str ());
128  m_f = fopen (fn.c_str (), "w");
129  if (!m_f)
130  {
131  NS_FATAL_ERROR ("Unable to open Animation output file");
132  return false; // Can't open
133  }
134  m_outputFileName = fn;
135  m_outputFileSet = true;
136  return true;
137 }
138 
140 {
141  m_enablePacketMetadata = enable;
142  if (enable)
144 }
145 
147 {
148  return initialized;
149 }
150 
152 {
153  return m_started;
154 
155 }
156 
157 void AnimationInterface::SetAnimWriteCallback (AnimWriteCallback cb)
158 {
159  m_writeCallback = cb;
160 }
161 
163 {
164  m_writeCallback = 0;
165 }
166 
168 {
169  if ((Simulator::Now () >= m_startTime) &&
170  (Simulator::Now () <= m_stopTime))
171  return true;
172  else
173  return false;
174 }
175 
177 {
178  return (m_pendingUanPackets.find (AnimUid) != m_pendingUanPackets.end ());
179 }
180 
182 {
183  return (m_pendingWifiPackets.find (AnimUid) != m_pendingWifiPackets.end ());
184 }
185 
187 {
188  return (m_pendingCsmaPackets.find (AnimUid) != m_pendingCsmaPackets.end ());
189 }
190 
191 
193 {
194  return (m_pendingWimaxPackets.find (AnimUid) != m_pendingWimaxPackets.end ());
195 }
196 
198 {
199  return (m_pendingLtePackets.find (AnimUid) != m_pendingLtePackets.end ());
200 }
201 
203 {
205 }
206 
208 {
209  m_randomPosition = setRandPos;
210 }
211 
213 {
215  if (loc)
216  {
217  m_nodeLocation[n->GetId ()] = loc->GetPosition ();
218  }
219  else
220  {
221  NS_LOG_UNCOND ( "AnimationInterface WARNING:Node:" << n->GetId () << " Does not have a mobility model. Use SetConstantPosition if it is stationary");
222  Vector deterministicVector (100,100,0);
224  if (m_randomPosition)
225  {
226  m_nodeLocation[n->GetId ()] = randomVector;
227  }
228  else
229  {
230  m_nodeLocation[n->GetId ()] = deterministicVector;
231  }
232  }
233  return m_nodeLocation[n->GetId ()];
234 }
235 
237 {
238  m_nodeLocation[n->GetId ()] = v;
239  return v;
240 }
241 
243 {
244  #ifdef NS_LOG
245  if (m_nodeLocation.find (n->GetId()) == m_nodeLocation.end ())
246  {
247  NS_FATAL_ERROR ("Node:" <<n->GetId() << " not found in Location table");
248  }
249  #endif
250  return m_nodeLocation[n->GetId ()];
251 }
252 
254 {
255  if (m_pendingWifiPackets.empty ())
256  return;
257  std::vector <uint64_t> purgeList;
258  for (std::map<uint64_t, AnimPacketInfo>::iterator i = m_pendingWifiPackets.begin ();
259  i != m_pendingWifiPackets.end ();
260  ++i)
261  {
262 
263  AnimPacketInfo pktInfo = i->second;
264  double delta = (Simulator::Now ().GetSeconds () - pktInfo.m_fbTx);
265  if (delta > PURGE_INTERVAL)
266  {
267  purgeList.push_back (i->first);
268  }
269  }
270 
271  for (std::vector <uint64_t>::iterator i = purgeList.begin ();
272  i != purgeList.end ();
273  ++i)
274  {
275  m_pendingWifiPackets.erase (*i);
276  }
277 
278 }
279 
281 {
282  if (m_pendingWimaxPackets.empty ())
283  return;
284  std::vector <uint64_t> purgeList;
285  for (std::map<uint64_t, AnimPacketInfo>::iterator i = m_pendingWimaxPackets.begin ();
286  i != m_pendingWimaxPackets.end ();
287  ++i)
288  {
289 
290  AnimPacketInfo pktInfo = i->second;
291  double delta = (Simulator::Now ().GetSeconds () - pktInfo.m_fbTx);
292  if (delta > PURGE_INTERVAL)
293  {
294  purgeList.push_back (i->first);
295  }
296  }
297 
298  for (std::vector <uint64_t>::iterator i = purgeList.begin ();
299  i != purgeList.end ();
300  ++i)
301  {
302  m_pendingWimaxPackets.erase (*i);
303  }
304 
305 }
306 
307 
309 {
310  if (m_pendingLtePackets.empty ())
311  return;
312  std::vector <uint64_t> purgeList;
313  for (std::map<uint64_t, AnimPacketInfo>::iterator i = m_pendingLtePackets.begin ();
314  i != m_pendingLtePackets.end ();
315  ++i)
316  {
317 
318  AnimPacketInfo pktInfo = i->second;
319  double delta = (Simulator::Now ().GetSeconds () - pktInfo.m_fbTx);
320  if (delta > PURGE_INTERVAL)
321  {
322  purgeList.push_back (i->first);
323  }
324  }
325 
326  for (std::vector <uint64_t>::iterator i = purgeList.begin ();
327  i != purgeList.end ();
328  ++i)
329  {
330  m_pendingLtePackets.erase (*i);
331  }
332 }
333 
335 {
336  if (m_pendingCsmaPackets.empty ())
337  return;
338  std::vector <uint64_t> purgeList;
339  for (std::map<uint64_t, AnimPacketInfo>::iterator i = m_pendingCsmaPackets.begin ();
340  i != m_pendingCsmaPackets.end ();
341  ++i)
342  {
343 
344  AnimPacketInfo pktInfo = i->second;
345  double delta = (Simulator::Now ().GetSeconds () - pktInfo.m_fbTx);
346  if (delta > PURGE_INTERVAL)
347  {
348  purgeList.push_back (i->first);
349  }
350  }
351 
352  for (std::vector <uint64_t>::iterator i = purgeList.begin ();
353  i != purgeList.end ();
354  ++i)
355  {
356  m_pendingCsmaPackets.erase (*i);
357  }
358 
359 }
360 
362 {
363  Ptr<Ipv4> ipv4 = NodeList::GetNode (nd->GetNode ()->GetId ())->GetObject <Ipv4> ();
364  if (!ipv4)
365  return "0.0.0.0";
366  uint32_t ifIndex = ipv4->GetInterfaceForDevice (nd);
367  Ipv4InterfaceAddress addr = ipv4->GetAddress (ifIndex, 0);
368  std::ostringstream oss;
369  oss << addr.GetLocal ();
370  return oss.str ();
371 }
372 
374 {
375  m_currentPktCount = 0;
376  m_started = true;
378 
379  // Find the min/max x/y for the xml topology element
380  m_topoMinX = -2;
381  m_topoMinY = -2;
382  m_topoMaxX = 2;
383  m_topoMaxY = 2;
384  for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
385  {
386  Ptr<Node> n = *i;
387  NS_LOG_INFO ("Update Position for Node: " << n->GetId ());
388  Vector v = UpdatePosition (n);
389  m_topoMinX = std::min (m_topoMinX, v.x);
390  m_topoMinY = std::min (m_topoMinY, v.y);
391  m_topoMaxX = std::max (m_topoMaxX, v.x);
392  m_topoMaxY = std::max (m_topoMaxY, v.y);
393  struct Rgb rgb = {255, 0, 0};
394  if (nodeColors.find (n->GetId ()) == nodeColors.end ())
395  {
396  nodeColors[n->GetId ()] = rgb;
397  }
398  }
399 
400  AddMargin ();
401  if (m_xml)
402  { // output the xml headers
403  std::ostringstream oss;
404  oss << GetXMLOpen_anim (0);
405  oss << GetPreamble ();
407  WriteN (oss.str ());
408  }
409  NS_LOG_INFO ("Setting topology for "<<NodeList::GetNNodes ()<<" Nodes");
410  // Dump the topology
411  for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
412  {
413  Ptr<Node> n = *i;
414  std::ostringstream oss;
415  if (m_xml)
416  {
417  Vector v = GetPosition (n);
418  struct Rgb rgb = nodeColors[n->GetId ()];
419  oss << GetXMLOpenClose_node (0, n->GetId (), v.x, v.y, rgb);
420  WriteN (oss.str ());
421  }
422  else
423  {
424  // Location exists, dump it
425  Vector v = GetPosition (n);
426  oss << "0.0 N " << n->GetId ()
427  << " " << v.x << " " << v.y << std::endl;
428  WriteN (oss.str ().c_str (), oss.str ().length ());
429  }
430  }
431  NS_LOG_INFO ("Setting p2p links");
432  // Now dump the p2p links
433  for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
434  {
435  Ptr<Node> n = *i;
436  uint32_t n1Id = n->GetId ();
437  uint32_t nDev = n->GetNDevices (); // Number of devices
438  for (uint32_t i = 0; i < nDev; ++i)
439  {
440  Ptr<NetDevice> dev = n->GetDevice (i);
441  NS_ASSERT (dev);
442  Ptr<Channel> ch = dev->GetChannel ();
443  if (!ch)
444  {
445  NS_LOG_DEBUG ("No channel can't be a p2p device");
446  continue;
447  }
448  std::string channelType = ch->GetInstanceTypeId ().GetName ();
449  if (channelType == std::string ("ns3::PointToPointChannel"))
450  { // Since these are duplex links, we only need to dump
451  // if srcid < dstid
452  uint32_t nChDev = ch->GetNDevices ();
453  for (uint32_t j = 0; j < nChDev; ++j)
454  {
455  Ptr<NetDevice> chDev = ch->GetDevice (j);
456  uint32_t n2Id = chDev->GetNode ()->GetId ();
457  if (n1Id < n2Id)
458  {
459  // ouptut the p2p link
460  NS_LOG_INFO ("Link:" << GetIpv4Address (dev) << "----" << GetIpv4Address (chDev));
461  SetLinkDescription (n1Id, n2Id, "", GetIpv4Address (dev), GetIpv4Address (chDev));
462  std::ostringstream oss;
463  if (m_xml)
464  {
465  oss << GetXMLOpenClose_link (0, n1Id, 0, n2Id);
466  }
467  else
468  {
469  oss << "0.0 L " << n1Id << " " << n2Id << std::endl;
470  }
471  WriteN (oss.str ());
472  }
473  }
474  }
475  else
476  {
477  //NS_FATAL_ERROR ("Net animation currently only supports point-to-point links.");
478  }
479  }
480  }
481  linkProperties.clear ();
482  if (m_xml && !restart)
483  {
484  WriteN (GetXMLClose ("topology"));
486  }
487  if (!restart)
488  ConnectCallbacks ();
489 }
490 
492 {
493 
494  Ptr<LteEnbPhy> lteEnbPhy = nd->GetPhy ();
495  Ptr<LteSpectrumPhy> dlPhy = lteEnbPhy->GetDownlinkSpectrumPhy ();
496  Ptr<LteSpectrumPhy> ulPhy = lteEnbPhy->GetUplinkSpectrumPhy ();
497  std::ostringstream oss;
498  //NodeList/*/DeviceList/*/
499  oss << "NodeList/" << n->GetId () << "/DeviceList/" << devIndex << "/";
500  if (dlPhy)
501  {
502  dlPhy->TraceConnect ("TxStart",oss.str (), MakeCallback (&AnimationInterface::LteSpectrumPhyTxStart, this));
503  dlPhy->TraceConnect ("RxStart",oss.str (), MakeCallback (&AnimationInterface::LteSpectrumPhyRxStart, this));
504  }
505  if (ulPhy)
506  {
507  ulPhy->TraceConnect ("TxStart",oss.str (), MakeCallback (&AnimationInterface::LteSpectrumPhyTxStart, this));
508  ulPhy->TraceConnect ("RxStart",oss.str (), MakeCallback (&AnimationInterface::LteSpectrumPhyRxStart, this));
509  }
510 }
511 
512 
513 
515 {
516 
517  Ptr<LteUePhy> lteUePhy = nd->GetPhy ();
518  Ptr<LteSpectrumPhy> dlPhy = lteUePhy->GetDownlinkSpectrumPhy ();
519  Ptr<LteSpectrumPhy> ulPhy = lteUePhy->GetUplinkSpectrumPhy ();
520  std::ostringstream oss;
521  //NodeList/*/DeviceList/*/
522  oss << "NodeList/" << n->GetId () << "/DeviceList/" << devIndex << "/";
523  if (dlPhy)
524  {
525  dlPhy->TraceConnect ("TxStart",oss.str (), MakeCallback (&AnimationInterface::LteSpectrumPhyTxStart, this));
526  dlPhy->TraceConnect ("RxStart",oss.str (), MakeCallback (&AnimationInterface::LteSpectrumPhyRxStart, this));
527  }
528  if (ulPhy)
529  {
530  ulPhy->TraceConnect ("TxStart",oss.str (), MakeCallback (&AnimationInterface::LteSpectrumPhyTxStart, this));
531  ulPhy->TraceConnect ("RxStart",oss.str (), MakeCallback (&AnimationInterface::LteSpectrumPhyRxStart, this));
532  }
533 }
534 
536 {
537 
538  for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
539  {
540  Ptr<Node> n = *i;
541  NS_ASSERT (n);
542  uint32_t nDevices = n->GetNDevices ();
543  for (uint32_t devIndex = 0; devIndex < nDevices; ++devIndex)
544  {
545  Ptr <NetDevice> nd = n->GetDevice(devIndex);
546  if (!nd)
547  continue;
548  Ptr<LteUeNetDevice> lteUeNetDevice = DynamicCast<LteUeNetDevice> (nd);
549  if (lteUeNetDevice)
550  {
551  ConnectLteUe (n, lteUeNetDevice, devIndex);
552  continue;
553  }
554  Ptr<LteEnbNetDevice> lteEnbNetDevice = DynamicCast<LteEnbNetDevice> (nd);
555  if (lteEnbNetDevice)
556  ConnectLteEnb (n, lteEnbNetDevice, devIndex);
557  }
558 
559  }
560 }
561 
563 {
564  // Connect the callbacks
565  Config::Connect ("/ChannelList/*/TxRxPointToPoint",
567  Config::Connect ("NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxBegin",
569  Config::Connect ("NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxBegin",
571  Config::ConnectWithoutContext ("/NodeList/*/$ns3::MobilityModel/CourseChange",
573  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WimaxNetDevice/Tx",
575  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WimaxNetDevice/Rx",
577  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::LteNetDevice/Tx",
579  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::LteNetDevice/Rx",
581  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::CsmaNetDevice/PhyTxBegin",
583  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::CsmaNetDevice/PhyTxEnd",
585  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::CsmaNetDevice/PhyRxEnd",
587  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::CsmaNetDevice/MacRx",
589  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::UanNetDevice/Phy/PhyTxBegin",
591  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::UanNetDevice/Phy/PhyRxBegin",
593 
594  ConnectLte ();
595 
596 }
597 
598 
600 {
601  m_started = false;
602  NS_LOG_INFO ("Stopping Animation");
604  if (m_f)
605  {
606  if (m_xml)
607  { // Terminate the anim element
608  WriteN (GetXMLClose ("anim"));
609  }
610  fclose (m_f);
611  }
612  m_outputFileSet = false;
613 }
614 
615 int AnimationInterface::WriteN (const std::string& st)
616 {
617  if (m_writeCallback)
618  {
619  m_writeCallback (st.c_str ());
620  }
621  return WriteN (st.c_str (), st.length ());
622 }
623 
624 // Private methods
626 {
627  // Compute width/height, and add a small margin
628  double w = m_topoMaxX - m_topoMinX;
629  double h = m_topoMaxY - m_topoMinY;
630  m_topoMinX -= w * 0.05;
631  m_topoMinY -= h * 0.05;
632  m_topoMaxX = m_topoMinX + w * 1.5;
633  m_topoMaxY = m_topoMinY + h * 1.5;
634  NS_LOG_INFO ("Added Canvas Margin:" << m_topoMinX << "," <<
635  m_topoMinY << "," << m_topoMaxX << "," << m_topoMaxY);
636 }
637 
638 std::vector <Ptr <Node> > AnimationInterface::RecalcTopoBounds ()
639 {
640  std::vector < Ptr <Node> > MovedNodes;
641  for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
642  {
643  Ptr<Node> n = *i;
644  NS_ASSERT (n);
645  Ptr <MobilityModel> mobility = n->GetObject <MobilityModel> ();
646  Vector newLocation;
647  if (!mobility)
648  {
649  newLocation = GetPosition (n);
650  }
651  else
652  {
653  newLocation = mobility->GetPosition ();
654  }
655  if (!NodeHasMoved (n, newLocation))
656  {
657  continue; //Location has not changed
658  }
659  else
660  {
661  UpdatePosition (n, newLocation);
662  RecalcTopoBounds (newLocation);
663  MovedNodes.push_back (n);
664  }
665  }
666  return MovedNodes;
667 }
668 
670 {
671  double oldminX = m_topoMinX;
672  double oldminY = m_topoMinY;
673  double oldmaxX = m_topoMaxX;
674  double oldmaxY = m_topoMaxY;
675  m_topoMinX = std::min (m_topoMinX, v.x);
676  m_topoMinY = std::min (m_topoMinY, v.y);
677  m_topoMaxX = std::max (m_topoMaxX, v.x);
678  m_topoMaxY = std::max (m_topoMaxY, v.y);
679 
680  if ((m_topoMinX != oldminX) || (m_topoMinY != oldminY) ||
681  (m_topoMaxX != oldmaxX) || (m_topoMaxY != oldmaxY))
682  {
683  AddMargin ();
684  }
685 }
686 
687 int AnimationInterface::WriteN (const char* data, uint32_t count)
688 {
689  // Write count bytes to h from data
690  uint32_t nLeft = count;
691  const char* p = data;
692  uint32_t written = 0;
693  while (nLeft)
694  {
695  int n = fwrite (p, 1, nLeft, m_f);
696  if (n <= 0)
697  {
698  return written;
699  }
700  written += n;
701  nLeft -= n;
702  p += n;
703  }
704  return written;
705 }
706 
708 {
709  Time now = Simulator::Now ();
710  std::ostringstream oss;
711  double fbTx = now.GetSeconds ();
712  double lbTx = now.GetSeconds ();
713  double fbRx = now.GetSeconds ();
714  double lbRx = now.GetSeconds ();
715  if (m_xml)
716  {
717  oss << GetXMLOpen_packet (0, 0, fbTx, lbTx, "DummyPktIgnoreThis");
718  oss << GetXMLOpenClose_rx (0, 0, fbRx, lbRx);
719  oss << GetXMLClose ("packet");
720  }
721  WriteN (oss.str ());
722 
723 
724 }
727  Time txTime, Time rxTime)
728 {
729  if (!m_started || !IsInTimeWindow ())
730  return;
731  NS_ASSERT (tx);
732  NS_ASSERT (rx);
733  Time now = Simulator::Now ();
734  std::ostringstream oss;
735  double fbTx = now.GetSeconds ();
736  double lbTx = (now + txTime).GetSeconds ();
737  double fbRx = (now + rxTime - txTime).GetSeconds ();
738  double lbRx = (now + rxTime).GetSeconds ();
739  if (m_xml)
740  {
741  oss << GetXMLOpen_packet (0, tx->GetNode ()->GetId (), fbTx, lbTx);
742  oss << GetXMLOpenClose_rx (0, rx->GetNode ()->GetId (), fbRx, lbRx);
745  oss << GetXMLClose ("packet");
748  }
749  else
750  {
751  oss << std::setprecision (10);
752  oss << now.GetSeconds () << " P "
753  << tx->GetNode ()->GetId () << " "
754  << rx->GetNode ()->GetId () << " "
755  << (now + txTime).GetSeconds () << " " // last bit tx time
756  << (now + rxTime - txTime).GetSeconds () << " " // first bit rx time
757  << (now + rxTime).GetSeconds () << std::endl; // last bit rx time
758  }
759  WriteN (oss.str ());
760 }
761 
762 
765 {
766  // Use "NodeList/*/DeviceList/*/ as reference
767  // where element [1] is the Node Id
768  // element [2] is the NetDevice Id
769 
770  std::vector <std::string> elements = GetElementsFromContext (context);
771  Ptr <Node> n = NodeList::GetNode (atoi (elements[1].c_str ()));
772  NS_ASSERT (n);
773  return n->GetDevice (atoi (elements[3].c_str ()));
774 }
775 
777 {
778  m_pendingUanPackets[AnimUid] = pktinfo;
779 }
780 
781 
783 {
784  m_pendingWifiPackets[AnimUid] = pktinfo;
785 }
786 
788 {
789  NS_ASSERT (pktinfo.m_txnd);
790  m_pendingWimaxPackets[AnimUid] = pktinfo;
791 }
792 
794 {
795  NS_ASSERT (pktinfo.m_txnd);
796  m_pendingLtePackets[AnimUid] = pktinfo;
797 }
798 
800 {
801  NS_ASSERT (pktinfo.m_txnd);
802  m_pendingCsmaPackets[AnimUid] = pktinfo;
803 }
804 
806 {
807  AnimByteTag tag;
808  TypeId tid = tag.GetInstanceTypeId ();
810  bool found = false;
811  while (i.HasNext ())
812  {
813  ByteTagIterator::Item item = i.Next ();
814  if (tid == item.GetTypeId ())
815  {
816  item.GetTag (tag);
817  found = true;
818  }
819  }
820  if (found)
821  {
822  return tag.Get ();
823  }
824  else
825  {
826  return 0;
827  }
828 }
829 
831 {
832  if (!m_started || !IsInTimeWindow ())
833  return;
834  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
835  NS_ASSERT (ndev);
836  Ptr <Node> n = ndev->GetNode ();
837  NS_ASSERT (n);
838  gAnimUid++;
839  NS_LOG_INFO ("Uan TxBeginTrace for packet:" << gAnimUid);
840  AnimByteTag tag;
841  tag.Set (gAnimUid);
842  p->AddByteTag (tag);
843  AnimPacketInfo pktinfo (ndev, Simulator::Now (), Simulator::Now (), UpdatePosition (n));
844  AddPendingUanPacket (gAnimUid, pktinfo);
845 
846 
847 }
848 
850 {
851  if (!m_started || !IsInTimeWindow ())
852  return;
853  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
854  NS_ASSERT (ndev);
855  Ptr <Node> n = ndev->GetNode ();
856  NS_ASSERT (n);
857  uint64_t AnimUid = GetAnimUidFromPacket (p);
858  NS_LOG_INFO ("UanPhyGenRxTrace for packet:" << AnimUid);
859  if (!UanPacketIsPending (AnimUid))
860  {
861  NS_LOG_WARN ("UanPhyGenRxBeginTrace: unknown Uid");
862  return;
863  }
864  m_pendingUanPackets[AnimUid].ProcessRxBegin (ndev, Simulator::Now ());
865  m_pendingUanPackets[AnimUid].ProcessRxEnd (ndev, Simulator::Now (), UpdatePosition (n));
866  OutputWirelessPacket (p, m_pendingUanPackets[AnimUid], m_pendingUanPackets[AnimUid].GetRxInfo (ndev));
867 
868 }
869 
870 
871 void AnimationInterface::WifiPhyTxBeginTrace (std::string context,
873 {
874  if (!m_started || !IsInTimeWindow ())
875  return;
876  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
877  NS_ASSERT (ndev);
878  Ptr <Node> n = ndev->GetNode ();
879  NS_ASSERT (n);
880  // Add a new pending wireless
881  gAnimUid++;
882  NS_LOG_INFO ("Wifi TxBeginTrace for packet:" << gAnimUid);
883  AnimByteTag tag;
884  tag.Set (gAnimUid);
885  p->AddByteTag (tag);
886  AnimPacketInfo pktinfo (ndev, Simulator::Now (), Simulator::Now (), UpdatePosition (n));
887  AddPendingWifiPacket (gAnimUid, pktinfo);
888  Ptr<WifiNetDevice> netDevice = DynamicCast<WifiNetDevice> (ndev);
889  Mac48Address nodeAddr = netDevice->GetMac()->GetAddress();
890  std::ostringstream oss;
891  oss << nodeAddr;
892  m_macToNodeIdMap[oss.str ()] = n->GetId ();
893  NS_LOG_INFO ("Added Mac" << oss.str () << " node:" <<m_macToNodeIdMap[oss.str ()]);
894 }
895 
896 void AnimationInterface::WifiPhyTxEndTrace (std::string context,
898 {
899 }
900 
901 void AnimationInterface::WifiPhyTxDropTrace (std::string context,
903 {
904  if (!m_started || !IsInTimeWindow ())
905  return;
906  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
907  NS_ASSERT (ndev);
908  // Erase pending wifi
909  uint64_t AnimUid = GetAnimUidFromPacket (p);
910  NS_LOG_INFO ("TxDropTrace for packet:" << AnimUid);
911  NS_ASSERT (WifiPacketIsPending (AnimUid) == true);
912  m_pendingWifiPackets.erase (m_pendingWifiPackets.find (AnimUid));
913 }
914 
915 
916 void AnimationInterface::WifiPhyRxBeginTrace (std::string context,
918 {
919  if (!m_started || !IsInTimeWindow ())
920  return;
921  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
922  NS_ASSERT (ndev);
923  Ptr <Node> n = ndev->GetNode ();
924  NS_ASSERT (n);
925  uint64_t AnimUid = GetAnimUidFromPacket (p);
926  NS_LOG_INFO ("Wifi RxBeginTrace for packet:" << AnimUid);
927  if (!WifiPacketIsPending (AnimUid))
928  {
929  NS_LOG_WARN ("WifiPhyRxBeginTrace: unknown Uid");
930  std::ostringstream oss;
931  WifiMacHeader hdr;
932  if(!p->PeekHeader (hdr))
933  {
934  NS_LOG_WARN ("WifiMacHeader not present");
935  return;
936  }
937  oss << hdr.GetAddr2 ();
938  if (m_macToNodeIdMap.find (oss.str ()) == m_macToNodeIdMap.end ())
939  {
940  //NS_LOG_UNCOND (oss.str ());
941  return;
942  }
943  Ptr <Node> txNode = NodeList::GetNode (m_macToNodeIdMap[oss.str ()]);
944  AnimPacketInfo pktinfo (0, Simulator::Now (), Simulator::Now (), UpdatePosition (txNode), m_macToNodeIdMap[oss.str ()]);
945  AddPendingWifiPacket (AnimUid, pktinfo);
946  NS_LOG_WARN ("WifiPhyRxBegin: unknown Uid, but we are adding a wifi packet");
947  }
948  // TODO: NS_ASSERT (WifiPacketIsPending (AnimUid) == true);
949  m_pendingWifiPackets[AnimUid].ProcessRxBegin (ndev, Simulator::Now ());
950  m_pendingWifiPackets[AnimUid].ProcessRxEnd (ndev, Simulator::Now (), UpdatePosition (n));
951  OutputWirelessPacket (p, m_pendingWifiPackets[AnimUid], m_pendingWifiPackets[AnimUid].GetRxInfo (ndev));
952 }
953 
954 
955 void AnimationInterface::WifiPhyRxEndTrace (std::string context,
957 {
958  if (!m_started || !IsInTimeWindow ())
959  return;
960  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
961  NS_ASSERT (ndev);
962  Ptr <Node> n = ndev->GetNode ();
963  NS_ASSERT (n);
964  uint64_t AnimUid = GetAnimUidFromPacket (p);
965  if (!WifiPacketIsPending (AnimUid))
966  {
967  NS_LOG_WARN ("WifiPhyRxEndTrace: unknown Uid");
968  AnimPacketInfo pktinfo (ndev, Simulator::Now (), Simulator::Now (), UpdatePosition (n));
969  AddPendingWifiPacket (AnimUid, pktinfo);
970  }
971  // TODO: NS_ASSERT (WifiPacketIsPending (AnimUid) == true);
972  AnimPacketInfo& pktInfo = m_pendingWifiPackets[AnimUid];
973  pktInfo.ProcessRxEnd (ndev, Simulator::Now (), UpdatePosition (n));
974  AnimRxInfo pktrxInfo = pktInfo.GetRxInfo (ndev);
975  if (pktrxInfo.IsPhyRxComplete ())
976  {
977  NS_LOG_INFO ("MacRxTrace for packet:" << AnimUid << " complete");
978  OutputWirelessPacket (p, pktInfo, pktrxInfo);
979  }
980 }
981 
982 void AnimationInterface::WifiMacRxTrace (std::string context,
984 {
985  if (!m_started || !IsInTimeWindow ())
986  return;
987  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
988  NS_ASSERT (ndev);
989  Ptr <Node> n = ndev->GetNode ();
990  NS_ASSERT (n);
991  uint64_t AnimUid = GetAnimUidFromPacket (p);
992  if (!WifiPacketIsPending (AnimUid))
993  {
994  NS_LOG_WARN ("WifiMacRxTrace: unknown Uid");
995  return;
996  }
997  // TODO: NS_ASSERT (WifiPacketIsPending (AnimUid) == true);
998  AnimPacketInfo& pktInfo = m_pendingWifiPackets[AnimUid];
999  AnimRxInfo pktrxInfo = pktInfo.GetRxInfo (ndev);
1000  if (pktrxInfo.IsPhyRxComplete ())
1001  {
1002  NS_LOG_INFO ("MacRxTrace for packet:" << AnimUid << " complete");
1003  OutputWirelessPacket (p, pktInfo, pktrxInfo);
1004  }
1005 
1006 }
1007 void AnimationInterface::WifiPhyRxDropTrace (std::string context,
1009 {
1010 }
1011 
1012 void AnimationInterface::WimaxTxTrace (std::string context, Ptr<const Packet> p, const Mac48Address & m)
1013 {
1014  if (!m_started || !IsInTimeWindow ())
1015  return;
1016  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
1017  NS_ASSERT (ndev);
1018  Ptr <Node> n = ndev->GetNode ();
1019  NS_ASSERT (n);
1020  gAnimUid++;
1021  NS_LOG_INFO ("WimaxTxTrace for packet:" << gAnimUid);
1022  AnimPacketInfo pktinfo (ndev, Simulator::Now (), Simulator::Now () + Seconds (0.001), UpdatePosition (n));
1023  //TODO 0.0001 is used until Wimax implements TxBegin and TxEnd traces
1024  AnimByteTag tag;
1025  tag.Set (gAnimUid);
1026  p->AddByteTag (tag);
1027  AddPendingWimaxPacket (gAnimUid, pktinfo);
1028 }
1029 
1030 
1031 void AnimationInterface::WimaxRxTrace (std::string context, Ptr<const Packet> p, const Mac48Address & m)
1032 {
1033  if (!m_started || !IsInTimeWindow ())
1034  return;
1035  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
1036  NS_ASSERT (ndev);
1037  Ptr <Node> n = ndev->GetNode ();
1038  NS_ASSERT (n);
1039  uint64_t AnimUid = GetAnimUidFromPacket (p);
1040  NS_LOG_INFO ("WimaxRxTrace for packet:" << AnimUid);
1041  NS_ASSERT (WimaxPacketIsPending (AnimUid) == true);
1042  AnimPacketInfo& pktInfo = m_pendingWimaxPackets[AnimUid];
1043  pktInfo.ProcessRxBegin (ndev, Simulator::Now ());
1044  pktInfo.ProcessRxEnd (ndev, Simulator::Now () + Seconds (0.001), UpdatePosition (n));
1045  //TODO 0.001 is used until Wimax implements RxBegin and RxEnd traces
1046  AnimRxInfo pktrxInfo = pktInfo.GetRxInfo (ndev);
1047  OutputWirelessPacket (p, pktInfo, pktrxInfo);
1048 }
1049 
1050 void AnimationInterface::LteTxTrace (std::string context, Ptr<const Packet> p, const Mac48Address & m)
1051 {
1052  if (!m_started || !IsInTimeWindow ())
1053  return;
1054  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
1055  NS_ASSERT (ndev);
1056  Ptr <Node> n = ndev->GetNode ();
1057  NS_ASSERT (n);
1058  gAnimUid++;
1059  NS_LOG_INFO ("LteTxTrace for packet:" << gAnimUid);
1060  AnimPacketInfo pktinfo (ndev, Simulator::Now (), Simulator::Now () + Seconds (0.001), UpdatePosition (n));
1061  //TODO 0.0001 is used until Lte implements TxBegin and TxEnd traces
1062  AnimByteTag tag;
1063  tag.Set (gAnimUid);
1064  p->AddByteTag (tag);
1065  AddPendingLtePacket (gAnimUid, pktinfo);
1066 }
1067 
1068 
1069 void AnimationInterface::LteRxTrace (std::string context, Ptr<const Packet> p, const Mac48Address & m)
1070 {
1071  if (!m_started || !IsInTimeWindow ())
1072  return;
1073  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
1074  NS_ASSERT (ndev);
1075  Ptr <Node> n = ndev->GetNode ();
1076  NS_ASSERT (n);
1077  uint64_t AnimUid = GetAnimUidFromPacket (p);
1078  NS_LOG_INFO ("LteRxTrace for packet:" << gAnimUid);
1079  if (!LtePacketIsPending (AnimUid))
1080  {
1081  NS_LOG_WARN ("LteRxTrace: unknown Uid");
1082  return;
1083  }
1084  AnimPacketInfo& pktInfo = m_pendingLtePackets[AnimUid];
1085  pktInfo.ProcessRxBegin (ndev, Simulator::Now ());
1086  pktInfo.ProcessRxEnd (ndev, Simulator::Now () + Seconds (0.001), UpdatePosition (n));
1087  //TODO 0.001 is used until Lte implements RxBegin and RxEnd traces
1088  AnimRxInfo pktrxInfo = pktInfo.GetRxInfo (ndev);
1089  OutputWirelessPacket (p, pktInfo, pktrxInfo);
1090 }
1091 
1093 {
1094  if (!m_started || !IsInTimeWindow ())
1095  return;
1096  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
1097  NS_ASSERT (ndev);
1098  Ptr <Node> n = ndev->GetNode ();
1099  NS_ASSERT (n);
1100 
1101  std::list <Ptr <Packet> > pbList = pb->GetPackets ();
1102  for (std::list <Ptr <Packet> >::iterator i = pbList.begin ();
1103  i != pbList.end ();
1104  ++i)
1105  {
1106  Ptr <Packet> p = *i;
1107  gAnimUid++;
1108  NS_LOG_INFO ("LteSpectrumPhyTxTrace for packet:" << gAnimUid);
1109  AnimPacketInfo pktinfo (ndev, Simulator::Now (), Simulator::Now () + Seconds (0.001), UpdatePosition (n));
1110  //TODO 0.0001 is used until Lte implements TxBegin and TxEnd traces
1111  AnimByteTag tag;
1112  tag.Set (gAnimUid);
1113  p->AddByteTag (tag);
1114  AddPendingLtePacket (gAnimUid, pktinfo);
1115  }
1116 }
1117 
1119 {
1120  if (!m_started || !IsInTimeWindow ())
1121  return;
1122  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
1123  NS_ASSERT (ndev);
1124  Ptr <Node> n = ndev->GetNode ();
1125  NS_ASSERT (n);
1126 
1127  std::list <Ptr <Packet> > pbList = pb->GetPackets ();
1128  for (std::list <Ptr <Packet> >::iterator i = pbList.begin ();
1129  i != pbList.end ();
1130  ++i)
1131  {
1132  Ptr <Packet> p = *i;
1133  uint64_t AnimUid = GetAnimUidFromPacket (p);
1134  NS_LOG_INFO ("LteSpectrumPhyRxTrace for packet:" << gAnimUid);
1135  if (!LtePacketIsPending (AnimUid))
1136  {
1137  NS_LOG_WARN ("LteSpectrumPhyRxTrace: unknown Uid");
1138  return;
1139  }
1140  AnimPacketInfo& pktInfo = m_pendingLtePackets[AnimUid];
1141  pktInfo.ProcessRxBegin (ndev, Simulator::Now ());
1142  pktInfo.ProcessRxEnd (ndev, Simulator::Now () + Seconds (0.001), UpdatePosition (n));
1143  //TODO 0.001 is used until Lte implements RxBegin and RxEnd traces
1144  AnimRxInfo pktrxInfo = pktInfo.GetRxInfo (ndev);
1145  OutputWirelessPacket (p, pktInfo, pktrxInfo);
1146  }
1147 }
1148 
1150 {
1151  if (!m_started || !IsInTimeWindow ())
1152  return;
1153  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
1154  NS_ASSERT (ndev);
1155  Ptr <Node> n = ndev->GetNode ();
1156  NS_ASSERT (n);
1157  gAnimUid++;
1158  NS_LOG_INFO ("CsmaPhyTxBeginTrace for packet:" << gAnimUid);
1159  AnimByteTag tag;
1160  tag.Set (gAnimUid);
1161  p->AddByteTag (tag);
1162  AnimPacketInfo pktinfo (ndev, Simulator::Now (), Simulator::Now (), UpdatePosition (n));
1163  AddPendingCsmaPacket (gAnimUid, pktinfo);
1164 
1165 }
1166 
1168 {
1169  if (!m_started || !IsInTimeWindow ())
1170  return;
1171  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
1172  NS_ASSERT (ndev);
1173  Ptr <Node> n = ndev->GetNode ();
1174  NS_ASSERT (n);
1175  uint64_t AnimUid = GetAnimUidFromPacket (p);
1176  NS_LOG_INFO ("CsmaPhyTxEndTrace for packet:" << AnimUid);
1177  if (!CsmaPacketIsPending (AnimUid))
1178  {
1179  NS_LOG_WARN ("CsmaPhyTxEndTrace: unknown Uid");
1180  AnimPacketInfo pktinfo (ndev, Simulator::Now (), Simulator::Now (), UpdatePosition (n));
1181  AddPendingCsmaPacket (AnimUid, pktinfo);
1182  NS_LOG_WARN ("Unknown Uid, but adding Csma Packet anyway");
1183  }
1184  // TODO: NS_ASSERT (CsmaPacketIsPending (AnimUid) == true);
1185  AnimPacketInfo& pktInfo = m_pendingCsmaPackets[AnimUid];
1186  pktInfo.m_lbTx = Simulator::Now ().GetSeconds ();
1187 }
1188 
1190 {
1191  if (!m_started || !IsInTimeWindow ())
1192  return;
1193  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
1194  NS_ASSERT (ndev);
1195  Ptr <Node> n = ndev->GetNode ();
1196  NS_ASSERT (n);
1197  uint64_t AnimUid = GetAnimUidFromPacket (p);
1198  if (!CsmaPacketIsPending (AnimUid))
1199  {
1200  NS_LOG_WARN ("CsmaPhyRxEndTrace: unknown Uid");
1201  return;
1202  }
1203  // TODO: NS_ASSERT (CsmaPacketIsPending (AnimUid) == true);
1204  AnimPacketInfo& pktInfo = m_pendingCsmaPackets[AnimUid];
1205  m_pendingCsmaPackets[AnimUid].ProcessRxBegin (ndev, Simulator::Now ());
1206  pktInfo.ProcessRxEnd (ndev, Simulator::Now (), UpdatePosition (n));
1207  NS_LOG_INFO ("CsmaPhyRxEndTrace for packet:" << AnimUid);
1208 }
1209 
1210 
1211 void AnimationInterface::CsmaMacRxTrace (std::string context,
1213 {
1214  if (!m_started || !IsInTimeWindow ())
1215  return;
1216  NS_LOG_FUNCTION (this);
1217  Ptr <NetDevice> ndev = GetNetDeviceFromContext (context);
1218  NS_ASSERT (ndev);
1219  Ptr <Node> n = ndev->GetNode ();
1220  NS_ASSERT (n);
1221  uint64_t AnimUid = GetAnimUidFromPacket (p);
1222  if (!CsmaPacketIsPending (AnimUid))
1223  {
1224  NS_LOG_WARN ("CsmaMacRxTrace: unknown Uid");
1225  return;
1226  }
1227  // TODO: NS_ASSERT (CsmaPacketIsPending (AnimUid) == true);
1228  AnimPacketInfo& pktInfo = m_pendingCsmaPackets[AnimUid];
1229  AnimRxInfo pktrxInfo = pktInfo.GetRxInfo (ndev);
1230  if (pktrxInfo.IsPhyRxComplete ())
1231  {
1232  NS_LOG_INFO ("MacRxTrace for packet:" << AnimUid << " complete");
1233  OutputCsmaPacket (p, pktInfo, pktrxInfo);
1234  }
1235 }
1236 
1237 
1239 
1240 {
1241  if (!m_started || !IsInTimeWindow ())
1242  return;
1243  Ptr <Node> n = mobility->GetObject <Node> ();
1244  NS_ASSERT (n);
1245  Vector v ;
1246  if (!mobility)
1247  {
1248  v = GetPosition (n);
1249  }
1250  else
1251  {
1252  v = mobility->GetPosition ();
1253  }
1254  UpdatePosition (n,v);
1255  RecalcTopoBounds (v);
1256  std::ostringstream oss;
1258  oss << GetXMLOpenClose_node (0,n->GetId (),v.x,v.y);
1259  oss << GetXMLClose ("topology");
1260  WriteN (oss.str ());
1261  WriteDummyPacket ();
1262 }
1263 
1265 {
1266  Vector oldLocation = GetPosition (n);
1267  if ((ceil (oldLocation.x) == ceil (newLocation.x)) &&
1268  (ceil (oldLocation.y) == ceil (newLocation.y)))
1269  {
1270 
1271  return false;
1272  }
1273  else
1274  {
1275  return true;
1276  }
1277 }
1278 
1280 {
1281  if (!m_started || !IsInTimeWindow ())
1282  return;
1283  std::vector <Ptr <Node> > MovedNodes = RecalcTopoBounds ();
1284  std::ostringstream oss;
1286  for (uint32_t i = 0; i < MovedNodes.size (); i++)
1287  {
1288  Ptr <Node> n = MovedNodes [i];
1289  NS_ASSERT (n);
1290  Vector v = GetPosition (n);
1291  oss << GetXMLOpenClose_node (0, n->GetId (), v.x, v.y);
1292  }
1293  oss << GetXMLClose ("topology");
1294  WriteN (oss.str ());
1295  WriteDummyPacket ();
1296  if (!Simulator::IsFinished ())
1297  {
1298  PurgePendingWifi ();
1299  PurgePendingWimax ();
1300  PurgePendingLte ();
1301  PurgePendingCsma ();
1303  }
1304 }
1305 
1307 {
1308  std::ostringstream oss;
1309  p->Print (oss);
1310  return oss.str ();
1311 }
1312 
1314 {
1315  return m_currentPktCount;
1316 }
1317 
1318 int64_t
1320 {
1321  NS_LOG_FUNCTION (this << stream);
1323  return 1;
1324 }
1325 
1326 // Helper to output a wireless packet.
1327 // For now, only the XML interface is supported
1328 
1329 
1331 {
1332  std::string s =
1333  "<information><!-- \n\
1334  Description of attributes:\n\
1335  =========================\n\
1336  anim\n\
1337  * ver = Current version\n\
1338  topology\n\
1339  * minX = minimum X coordinate of the canvas\n\
1340  * minY = minimum Y coordinate of the canvas\n\
1341  * maxX = maximum X coordinate of the canvas\n\
1342  * maxY = maximum Y coordinate of the canvas\n\
1343  node\n\
1344  * id = Node Id\n\
1345  * locX = X coordinate\n\
1346  * locY = Y coordinate\n\
1347  * r = Red component\n\
1348  * g = Green component\n\
1349  * b = Blue component\n\
1350  link\n\
1351  * fromId = From Node Id\n\
1352  * toId = To Node Id\n\
1353  * fd = From Node description (for IP Address)\n\
1354  * td = To Node description (for IP Address)\n\
1355  * ld = Link description (for Bandwidth, delay etc)\n\
1356  linkupdate\n\
1357  * t = Simulation time\n\
1358  * ld = Link description (for Bandwidth, delay etc)\n\
1359  nodeupdate\n\
1360  * t = Simulation time\n\
1361  * descr = Node description\n\
1362  * r = Red component\n\
1363  * g = Green component\n\
1364  * b = Blue component\n\
1365  * visible = Node visibility\n\
1366  packet\n\
1367  * fbTx = First bit transmit time\n\
1368  * lbTx = Last bit transmit time\n\
1369  rx\n\
1370  * toId = To Node Id\n\
1371  * fbRx = First bit Rx Time\n\
1372  * lbRx = Last bit Rx\n\
1373  wpacket\n\
1374  * fromId = From Node Id\n\
1375  * fbTx = First bit transmit time\n\
1376  * lbTx = Last bit transmit time\n\
1377  * range = Reception range\n\
1378  rx\n\
1379  * toId = To Node Id\n\
1380  * fbRx = First bit Rx time\n\
1381  * lbRx = Last bit Rx time-->\n\
1382  </information>\n";
1383 return s;
1384 }
1385 
1387 {
1388  StartNewTraceFile ();
1389  NS_ASSERT (m_xml);
1390  std::ostringstream oss;
1391  uint32_t nodeId = 0;
1392  if (pktInfo.m_txnd)
1393  nodeId = pktInfo.m_txnd->GetNode ()->GetId ();
1394  else
1395  nodeId = pktInfo.m_txNodeId;
1396 
1397  double lbTx = pktInfo.firstlastbitDelta + pktInfo.m_fbTx;
1398  oss << GetXMLOpen_wpacket (0, nodeId, pktInfo.m_fbTx, lbTx, pktrxInfo.rxRange);
1399 
1400  uint32_t rxId = pktrxInfo.m_rxnd->GetNode ()->GetId ();
1401  oss << GetXMLOpenClose_rx (0, rxId, pktrxInfo.m_fbRx, pktrxInfo.m_lbRx);
1404 
1405  oss << GetXMLClose ("wpacket");
1406  WriteN (oss.str ());
1407 }
1408 
1410 {
1411  StartNewTraceFile ();
1412  NS_ASSERT (m_xml);
1413  std::ostringstream oss;
1414  NS_ASSERT (pktInfo.m_txnd);
1415  uint32_t nodeId = pktInfo.m_txnd->GetNode ()->GetId ();
1416 
1417  oss << GetXMLOpen_packet (0, nodeId, pktInfo.m_fbTx, pktInfo.m_lbTx);
1418  uint32_t rxId = pktrxInfo.m_rxnd->GetNode ()->GetId ();
1419  oss << GetXMLOpenClose_rx (0, rxId, pktrxInfo.m_fbRx, pktrxInfo.m_lbRx);
1422  oss << GetXMLClose ("packet");
1423  WriteN (oss.str ());
1424 }
1425 
1426 void AnimationInterface::SetConstantPosition (Ptr <Node> n, double x, double y, double z)
1427 {
1428  NS_ASSERT (n);
1430  if (hubLoc == 0)
1431  {
1432  hubLoc = CreateObject<ConstantPositionMobilityModel> ();
1433  n->AggregateObject (hubLoc);
1434  }
1435  Vector hubVec (x, y, z);
1436  hubLoc->SetPosition (hubVec);
1437  NS_LOG_INFO ("Node:" << n->GetId () << " Position set to:(" << x << "," << y << "," << z << ")");
1438 
1439 }
1440 
1441 void AnimationInterface::SetNodeColor (Ptr <Node> n, uint8_t r, uint8_t g, uint8_t b)
1442 {
1443  if (initialized)
1444  NS_FATAL_ERROR ("SetNodeColor must be used prior to creating the AnimationInterface object");
1445  NS_ASSERT (n);
1446  NS_LOG_INFO ("Setting node color for Node Id:" << n->GetId ());
1447  struct Rgb rgb = {r, g, b};
1448  nodeColors[n->GetId ()] = rgb;
1449 }
1450 
1451 void AnimationInterface::ShowNode (uint32_t nodeId, bool show)
1452 {
1453  NS_ASSERT (NodeList::GetNode (nodeId));
1454  NS_LOG_INFO ("Setting node visibility for Node Id:" << nodeId);
1455  std::ostringstream oss;
1456  oss << GetXMLOpenClose_nodeupdate (nodeId, show);
1457  WriteN (oss.str ());
1458 
1459 }
1460 
1462 {
1463  ShowNode (n, show);
1464 }
1465 
1466 void AnimationInterface::UpdateNodeColor (Ptr <Node> n, uint8_t r, uint8_t g, uint8_t b)
1467 {
1468  UpdateNodeColor (n->GetId (), r, g, b);
1469 }
1470 
1471 void AnimationInterface::UpdateNodeColor (uint32_t nodeId, uint8_t r, uint8_t g, uint8_t b)
1472 {
1473  NS_ASSERT (NodeList::GetNode (nodeId));
1474  NS_LOG_INFO ("Setting node color for Node Id:" << nodeId);
1475  struct Rgb rgb = {r, g, b};
1476  nodeColors[nodeId] = rgb;
1477  std::ostringstream oss;
1478  oss << GetXMLOpenClose_nodeupdate (nodeId);
1479  WriteN (oss.str ());
1480 }
1481 
1482 
1483 
1484 void AnimationInterface::SetNodeColor (NodeContainer nc, uint8_t r, uint8_t g, uint8_t b)
1485 {
1486  for (uint32_t i = 0; i < nc.GetN (); ++i)
1487  {
1488  Ptr <Node> n = nc.Get (i);
1489  NS_ASSERT (n);
1490  SetNodeColor (n, r, g, b);
1491  }
1492 }
1493 
1494 
1495 void AnimationInterface::UpdateLinkDescription (uint32_t fromNode, uint32_t toNode,
1496  std::string linkDescription)
1497 {
1498  std::ostringstream oss;
1499  oss << GetXMLOpenClose_linkupdate (fromNode, toNode, linkDescription);
1500  WriteN (oss.str ());
1501 }
1502 
1504  std::string linkDescription)
1505 {
1506  NS_ASSERT (fromNode);
1507  NS_ASSERT (toNode);
1508  std::ostringstream oss;
1509  oss << GetXMLOpenClose_linkupdate (fromNode->GetId (), toNode->GetId (), linkDescription);
1510  WriteN (oss.str ());
1511 }
1512 
1513 void AnimationInterface::SetLinkDescription (uint32_t fromNode, uint32_t toNode,
1514  std::string linkDescription,
1515  std::string fromNodeDescription,
1516  std::string toNodeDescription)
1517 {
1518 
1519  P2pLinkNodeIdPair p2pPair;
1520  p2pPair.fromNode = fromNode;
1521  p2pPair.toNode = toNode;
1522  LinkProperties lp = { fromNodeDescription, toNodeDescription, linkDescription };
1523  linkProperties[p2pPair] = lp;
1524  /* DEBUG */
1525  /*
1526  for (std::map <P2pLinkNodeIdPair, LinkProperties>::const_iterator i = linkProperties.begin ();
1527  i != linkProperties.end(); ++i)
1528  {
1529  P2pLinkNodeIdPair ppair = i->first;
1530  LinkProperties l = i->second;
1531  NS_LOG_UNCOND ("A:" << ppair.fromNode << " B:" << ppair.toNode << " ad:" << l.fromNodeDescription << " bd:" << l.toNodeDescription << " ld:" << l.linkDescription);
1532 
1533  }
1534  */
1535 }
1536 
1538  std::string linkDescription,
1539  std::string fromNodeDescription,
1540  std::string toNodeDescription)
1541 {
1542  NS_ASSERT (fromNode);
1543  NS_ASSERT (toNode);
1544  SetLinkDescription (fromNode->GetId (), toNode->GetId (), linkDescription, fromNodeDescription, toNodeDescription);
1545 }
1546 
1547 
1549 {
1550  if (initialized)
1551  NS_FATAL_ERROR ("SetNodeDescription must be used prior to creating the AnimationInterface object");
1552  NS_ASSERT (n);
1553  nodeDescriptions[n->GetId ()] = descr;
1554 }
1555 
1557 {
1558  UpdateNodeDescription (n->GetId (), descr);
1559 }
1560 
1561 void AnimationInterface::UpdateNodeDescription (uint32_t nodeId, std::string descr)
1562 {
1563  NS_ASSERT (NodeList::GetNode (nodeId));
1564  nodeDescriptions[nodeId] = descr;
1565  std::ostringstream oss;
1566  oss << GetXMLOpenClose_nodeupdate (nodeId);
1567  WriteN (oss.str ());
1568 }
1569 
1570 
1571 
1573 {
1574  if (initialized)
1575  NS_FATAL_ERROR ("SetNodeDescription must be used prior to creating the AnimationInterface object");
1576  for (uint32_t i = 0; i < nc.GetN (); ++i)
1577  {
1578  Ptr <Node> n = nc.Get (i);
1579  NS_ASSERT (n);
1580  nodeDescriptions[n->GetId ()] = descr;
1581  }
1582 }
1583 
1584 
1585 // XML Private Helpers
1586 
1587 std::string AnimationInterface::GetXMLOpen_anim (uint32_t lp)
1588 {
1589  std::ostringstream oss;
1590  oss <<"<anim ver=\"" << GetNetAnimVersion () << "\">\n";
1591  return oss.str ();
1592 }
1593 std::string AnimationInterface::GetXMLOpen_topology (double minX, double minY, double maxX, double maxY)
1594 {
1595  std::ostringstream oss;
1596  oss << "<topology minX = \"" << minX << "\" minY = \"" << minY
1597  << "\" maxX = \"" << maxX << "\" maxY = \"" << maxY
1598  << "\">" << std::endl;
1599  return oss.str ();
1600 
1601 }
1602 
1603 std::string AnimationInterface::GetXMLOpenClose_nodeupdate (uint32_t id, bool visible)
1604 {
1605  struct Rgb rgb = nodeColors[id];
1606  uint8_t r = rgb.r;
1607  uint8_t g = rgb.g;
1608  uint8_t b = rgb.b;
1609  std::ostringstream oss;
1610  oss << "<nodeupdate id=\"" << id << "\"";
1611  oss << " t=\"" << Simulator::Now ().GetSeconds () << "\"";
1612  if (visible)
1613  oss << " visible=\"" << 1 << "\"";
1614  else
1615  oss << " visible=\"" << 0 << "\"";
1616  if (nodeDescriptions.find (id) != nodeDescriptions.end ())
1617  {
1618  oss << " descr=\""<< nodeDescriptions[id] << "\"";
1619  }
1620  else
1621  {
1622  oss << " descr=\"\"";
1623  }
1624  oss << " r=\"" << (uint32_t)r << "\" "
1625  << " g=\"" << (uint32_t)g << "\" b=\"" << (uint32_t)b <<"\"/>\n";
1626  return oss.str ();
1627 
1628 }
1629 
1630 std::string AnimationInterface::GetXMLOpenClose_node (uint32_t lp, uint32_t id, double locX, double locY)
1631 {
1632  std::ostringstream oss;
1633  oss <<"<node id=\"" << id << "\"";
1634  if (nodeDescriptions.find (id) != nodeDescriptions.end ())
1635  {
1636  oss << " descr=\""<< nodeDescriptions[id] << "\"";
1637  }
1638  else
1639  {
1640  oss << " descr=\"\"";
1641  }
1642  oss << " locX = \"" << locX << "\" " << "locY = \"" << locY << "\" />\n";
1643  return oss.str ();
1644 }
1645 
1646 std::string AnimationInterface::GetXMLOpenClose_node (uint32_t lp, uint32_t id, double locX, double locY, struct Rgb rgb)
1647 {
1648  uint8_t r = rgb.r;
1649  uint8_t g = rgb.g;
1650  uint8_t b = rgb.b;
1651  std::ostringstream oss;
1652  oss <<"<node id = \"" << id << "\"";
1653  if (nodeDescriptions.find (id) != nodeDescriptions.end ())
1654  {
1655  oss << " descr=\""<< nodeDescriptions[id] << "\"";
1656  }
1657  else
1658  {
1659  oss << " descr=\"\"";
1660  }
1661  oss << " locX=\"" << locX << "\" " << "locY=\"" << locY << "\"" << " r=\"" << (uint32_t)r << "\" "
1662  << " g=\"" << (uint32_t)g << "\" b=\"" << (uint32_t)b <<"\"/>\n";
1663  return oss.str ();
1664 }
1665 
1666 std::string AnimationInterface::GetXMLOpenClose_linkupdate (uint32_t fromId, uint32_t toId, std::string linkDescription)
1667 {
1668  std::ostringstream oss;
1669  oss << "<linkupdate t=\"" << Simulator::Now ().GetSeconds () << "\""
1670  << " fromId=\"" << fromId
1671  << "\" toId=\"" << toId
1672  << "\" ";
1673 
1674  oss << " ld=\"" << linkDescription << "\""
1675  << " />\n";
1676  return oss.str ();
1677 
1678 }
1679 
1680 std::string AnimationInterface::GetXMLOpenClose_link (uint32_t fromLp, uint32_t fromId, uint32_t toLp, uint32_t toId)
1681 {
1682  std::ostringstream oss;
1683  oss << "<link fromId=\"" << fromId
1684  << "\" toId=\"" << toId
1685  << "\" ";
1686 
1687  LinkProperties lprop ;
1688  lprop.fromNodeDescription = "";
1689  lprop.toNodeDescription = "";
1690  lprop.linkDescription = "";
1691 
1692  P2pLinkNodeIdPair p1 = { fromId, toId };
1693  P2pLinkNodeIdPair p2 = { toId, fromId };
1694  if (linkProperties.find (p1) != linkProperties.end())
1695  {
1696  lprop = linkProperties[p1];
1697  }
1698  else if (linkProperties.find (p2) != linkProperties.end())
1699  {
1700  lprop = linkProperties[p2];
1701  }
1702 
1703  oss << " fd=\"" << lprop.fromNodeDescription << "\""
1704  << " td=\"" << lprop.toNodeDescription << "\""
1705  << " ld=\"" << lprop.linkDescription << "\""
1706  << " />\n";
1707  return oss.str ();
1708 }
1709 
1710 
1711 std::string AnimationInterface::GetXMLOpen_packet (uint32_t fromLp, uint32_t fromId, double fbTx, double lbTx, std::string auxInfo)
1712 {
1713  std::ostringstream oss;
1714  oss << std::setprecision (10);
1715  oss << "<packet fromId=\"" << fromId
1716  << "\" fbTx=\"" << fbTx
1717  << "\" lbTx=\"" << lbTx
1718  << (auxInfo.empty()?"":"\" aux=\"") << auxInfo.c_str ()
1719  << "\">";
1720  return oss.str ();
1721 }
1722 
1723 std::string AnimationInterface::GetXMLOpen_wpacket (uint32_t fromLp, uint32_t fromId, double fbTx, double lbTx, double range)
1724 {
1725  std::ostringstream oss;
1726  oss << std::setprecision (10);
1727  oss << "<wpacket fromId=\"" << fromId
1728  << "\" fbTx=\"" << fbTx
1729  << "\" lbTx=\"" << lbTx
1730  << "\" range=\"" << range << "\">" << std::endl;
1731  return oss.str ();
1732 
1733 }
1734 
1735 std::string AnimationInterface::GetXMLOpenClose_rx (uint32_t toLp, uint32_t toId, double fbRx, double lbRx)
1736 {
1737  std::ostringstream oss;
1738  oss << std::setprecision (10);
1739  oss << "<rx toId=\"" << toId
1740  << "\" fbRx=\"" << fbRx
1741  << "\" lbRx=\"" << lbRx
1742  << "\"/>" << std::endl;
1743  return oss.str ();
1744 }
1745 
1746 std::string AnimationInterface::GetXMLOpenClose_meta (std::string metaInfo)
1747 {
1748  std::ostringstream oss;
1749  oss << "<meta info=\""
1750  << metaInfo << "\" />" << std::endl;
1751  return oss.str ();
1752 }
1753 
1754 std::vector<std::string> AnimationInterface::GetElementsFromContext (std::string context)
1755 {
1756  std::vector <std::string> elements;
1757  size_t pos1=0, pos2;
1758  while (pos1 != context.npos)
1759  {
1760  pos1 = context.find ("/",pos1);
1761  pos2 = context.find ("/",pos1+1);
1762  elements.push_back (context.substr (pos1+1,pos2-(pos1+1)));
1763  pos1 = pos2;
1764  pos2 = context.npos;
1765  }
1766  return elements;
1767 }
1768 
1769 TypeId
1771 {
1772  static TypeId tid = TypeId ("ns3::AnimByteTag")
1773  .SetParent<Tag> ()
1774  .AddConstructor<AnimByteTag> ()
1775  ;
1776  return tid;
1777 }
1778 TypeId
1780 {
1781  return GetTypeId ();
1782 }
1783 
1784 uint32_t
1786 {
1787  return sizeof (uint64_t);
1788 }
1789 void
1791 {
1792  i.WriteU64 (m_AnimUid);
1793 }
1794 void
1796 {
1797  m_AnimUid = i.ReadU64 ();
1798 }
1799 void
1800 AnimByteTag::Print (std::ostream &os) const
1801 {
1802  os << "AnimUid=" << m_AnimUid;
1803 }
1804 void
1805 AnimByteTag::Set (uint64_t AnimUid)
1806 {
1807  m_AnimUid = AnimUid;
1808 }
1809 
1810 uint64_t
1811 AnimByteTag::Get (void) const
1812 {
1813  return m_AnimUid;
1814 }
1815 
1816 
1817 } // namespace ns3