Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(551)

Unified Diff: src/helper/animation-interface.cc

Issue 3374041: NetAnim wireless hooks
Patch Set: NetAnim wireless hooks Created 13 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/helper/animation-interface.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/helper/animation-interface.cc
===================================================================
--- a/src/helper/animation-interface.cc
+++ b/src/helper/animation-interface.cc
@@ -18,8 +18,11 @@
// Interface between ns3 and the network animator
+#include <iomanip>
#include <stdio.h>
#include <sstream>
+#include <string>
+#include <map>
#include "ns3/net-anim-config.h"
@@ -39,6 +42,7 @@
#include "ns3/canvas-location.h"
#include "ns3/packet.h"
#include "ns3/simulator.h"
+#include "ns3/mobility-model.h"
using namespace std;
@@ -47,12 +51,13 @@
namespace ns3 {
AnimationInterface::AnimationInterface ()
- : m_fHandle (STDOUT_FILENO), m_model (0)
+ : m_fHandle (STDOUT_FILENO), m_xml(false), m_model (0)
{
}
AnimationInterface::~AnimationInterface ()
{
+ StopAnimation();
}
bool AnimationInterface::SetOutputFile (const std::string& fn)
@@ -66,6 +71,11 @@
return true;
}
+void AnimationInterface::SetXMLOutput()
+{
+ m_xml = true;
+}
+
bool AnimationInterface::SetServerPort (uint16_t port)
{
#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_NETINET_IN_H)
@@ -95,20 +105,94 @@
void AnimationInterface::StartAnimation ()
{
+ // Find the min/max x/y for the xml topology element
+ double minX = 0;
+ double minY = 0;
+ double maxX = 0;
+ double maxY = 0;
+ bool first = true;
+ for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
+ {
+ Ptr<Node> n = *i;
+ Ptr<CanvasLocation> loc = n->GetObject<CanvasLocation> ();
+ Ptr<MobilityModel> mobility = 0;
+ Vector v;
+ if (loc)
+ {
+ v = loc->GetLocation();
+ }
+ else
+ { // No canvas location, try position from mobility model
+ mobility = n->GetObject<MobilityModel>();
+ if (mobility) v = mobility->GetPosition();
+ }
+ if (!loc && !mobility) continue;
+ if (first)
+ {
+ minX = v.x;
+ minY = v.y;
+ maxX = v.x;
+ maxY = v.y;
+ first = false;
+ }
+ else
+ {
+ minX = min(minX, v.x);
+ minY = min(minY, v.y);
+ maxX = max(maxX, v.x);
+ maxY = max(maxY, v.y);
+ }
+ }
+
+ if (m_xml)
+ { // output the xml headers
+ // Compute width/height, and add a small margin
+ double w = maxX - minX;
+ double h = maxY - minY;
+ minX -= w * 0.05;
+ minY -= h * 0.05;
+ maxX = minX + w * 1.10;
+ maxY = minY + h * 1.10;
+ ostringstream oss;
+ oss << "<anim lp = \"0\">" << endl << "<topology";
+ oss << " minX = \"" << minX << "\" minY = \"" << minY
+ << "\" maxX = \"" << maxX << "\" maxY = \"" << maxY
+ << "\">" << endl;
+ WriteN (m_fHandle, oss.str ());
+ }
+
// Dump the topology
for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
{
Ptr<Node> n = *i;
Ptr<CanvasLocation> loc = n->GetObject<CanvasLocation> ();
+ Ptr<MobilityModel> mobility = 0;
+
+ Vector v;
if (loc)
{
- // Location exists, dump it
- Vector v = loc->GetLocation ();
- ostringstream oss;
+ v = loc->GetLocation();
+ }
+ else
+ { // No canvas location, try position from mobility model
+ mobility = n->GetObject<MobilityModel>();
+ if (mobility) v = mobility->GetPosition();
+ }
+ if (!loc && !mobility) continue; // Can't find a position
+ // Location exists, dump it
+ ostringstream oss;
+ if (m_xml)
+ {
+ oss << "<node lp = \"0\" id = \"" << n->GetId ()
+ << "\" locX = \"" << v.x
+ << "\" locY = \"" << v.y << "\"/>" << endl;
+ }
+ else
+ {
oss << "0.0 N " << n->GetId ()
- << " " << v.x << " " << v.y << endl;
- WriteN (m_fHandle, oss.str ().c_str (), oss.str ().length ());
+ << " " << v.x << " " << v.y << endl;
}
+ WriteN (m_fHandle, oss.str ());
}
// Now dump the p2p links
for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
@@ -136,29 +220,51 @@
if (n1Id < n2Id)
{ // ouptut the p2p link
ostringstream oss;
- oss << "0.0 L " << n1Id << " " << n2Id << endl;
- WriteN (m_fHandle, oss.str ().c_str (),
- oss.str ().length ());
+ if (m_xml)
+ {
+ oss << "<link fromLP = \"0\" fromId = \"" << n1Id
+ << "\" toLp = \"0\" toId = \"" << n2Id
+ << "\"/>" << endl;
+ }
+ else
+ {
+ oss << "0.0 L " << n1Id << " " << n2Id << endl;
+ }
+ WriteN (m_fHandle, oss.str ());
}
}
}
- else
- {
- NS_FATAL_ERROR ("Net animation currently only supports point-to-point links.");
- }
}
}
-
+ if (m_xml)
+ {
+ string endTopo("</topology>\n");
+ WriteN(m_fHandle, endTopo);
+ }
// Connect the callback for packet tx events
Config::Connect ("/ChannelList/*/TxRxPointToPoint",
MakeCallback (&AnimationInterface::DevTxTrace, this));
+ Config::Connect ("NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxBegin",
+ MakeCallback (&AnimationInterface::PhyTxBeginTrace, this));
+ Config::Connect ("NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxBegin",
+ MakeCallback (&AnimationInterface::PhyRxBeginTrace, this));
+ Config::Connect ("NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxEnd",
+ MakeCallback (&AnimationInterface::PhyRxEndTrace, this));
+ Config::Connect ("NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxDrop",
+ MakeCallback (&AnimationInterface::PhyRxDropTrace, this));
}
void AnimationInterface::StopAnimation ()
{
if (m_fHandle > 0)
{
+ if (m_xml)
+ { // Terminate the anim element
+ string endAnim("</anim>\n");
+ WriteN (m_fHandle, endAnim);
+ }
close (m_fHandle);
+ m_fHandle = 0;
}
}
@@ -183,20 +289,209 @@
}
return written;
}
-
+
+ int AnimationInterface::WriteN(int h, const string& st)
+ {
+ return WriteN(h, st.c_str(), st.length());
+ }
+
+
+ //Trace callbacks
void AnimationInterface::DevTxTrace (std::string context, Ptr<const Packet> p,
Ptr<NetDevice> tx, Ptr<NetDevice> rx,
Time txTime, Time rxTime)
{
Time now = Simulator::Now ();
ostringstream oss;
- oss << now.GetSeconds() << " P "
- << tx->GetNode ()->GetId () << " "
- << rx->GetNode ()->GetId () << " "
- << (now + txTime).GetSeconds () << " " // last bit tx time
- << (now + rxTime - txTime).GetSeconds() << " " // first bit rx time
- << (now + rxTime).GetSeconds () << endl; // last bit rx time
- WriteN (m_fHandle, oss.str ().c_str (), oss.str ().length ());
+ double fbTx = now.GetSeconds();
+ double lbTx = (now + txTime).GetSeconds();
+ double fbRx = (now + rxTime - txTime).GetSeconds();
+ double lbRx = (now + rxTime).GetSeconds();
+
+ if (m_xml)
+ {
+ oss << setprecision(10);
+ oss << "<packet fromLp = \"0\" fromId = \"" << tx->GetNode()->GetId()
+ << "\" fbTx = \"" << fbTx
+ << "\" lbTx = \"" << lbTx
+ << "\">" << endl;
+ oss << "<rx toLp = \"0\" toId = \"" << rx->GetNode()->GetId()
+ << "\" fbRx = \"" << fbRx
+ << "\" lbRx = \"" << lbRx
+ << "\"/>" << endl;
+ oss << "</packet>" << endl;
+ }
+ else
+ {
+ oss << setprecision(10);
+ oss << now.GetSeconds() << " P "
+ << tx->GetNode ()->GetId () << " "
+ << rx->GetNode ()->GetId () << " "
+ << (now + txTime).GetSeconds () << " " // last bit tx time
+ << (now + rxTime - txTime).GetSeconds() << " " // first bit rx time
+ << (now + rxTime).GetSeconds () << endl; // last bit rx time
+ }
+ WriteN (m_fHandle, oss.str ());
+}
+
+// We use a PacketInfo structure for wireless traces to keep up
+// when each receiver has received packets. Also a PacketRxInfo
+// to keep up with each receiver and the time it received the packet
+class RxInfo
+{
+public:
+ RxInfo(Ptr<const NetDevice> nd, const Time& fbRx)
+ : m_nd(nd), m_fbRx(fbRx.GetSeconds()), m_lbRx(0) {}
+
+public:
+ Ptr<const NetDevice> m_nd; // The receiving net device
+ double m_fbRx; // First bit rx time
+ double m_lbRx; // Last bit rx time
+};
+
+class PacketInfo
+{
+public:
+ PacketInfo();
+ PacketInfo(Ptr<const NetDevice> nd, uint32_t nRx,
+ const Time& fbTx, const Time& lbTx);
+ //void AddTxEnd(const Time& lbTx); // Not needed
+ void AddRxBegin(Ptr<const NetDevice> nd, const Time& fbRx);
+ bool AddRxEnd(Ptr<const NetDevice> nd, const Time& fbRx);
+ void AddRxDrop();
+public:
+ Ptr<const NetDevice> m_nd;
+ uint32_t m_nRx; // Number of receivers expected
+ uint32_t m_nDrop; // Number of drops
+ uint32_t m_nRxEnd; // Number of rxEnd callbacks
+ double m_fbTx; // Time of first bit tx
+ double m_lbTx; // Time of first bit tx
+ vector<RxInfo> m_rx;
+};
+
+PacketInfo::PacketInfo()
+ : m_nd(0), m_nRx(0), m_nDrop(0), m_nRxEnd(0), m_fbTx(0), m_lbTx(0)
+{
+}
+
+PacketInfo::PacketInfo(Ptr<const NetDevice> nd, uint32_t nRx,
+ const Time& fbTx, const Time& lbTx)
+ : m_nd(nd), m_nRx(nRx), m_nDrop(0), m_nRxEnd(0),
+ m_fbTx(fbTx.GetSeconds()), m_lbTx(lbTx.GetSeconds())
+{
+}
+
+void PacketInfo::AddRxBegin(Ptr<const NetDevice> nd, const Time& fbRx)
+{
+ m_rx.push_back(RxInfo(nd, fbRx));
+}
+
+bool PacketInfo::AddRxEnd(Ptr<const NetDevice> nd, const Time& lbRx)
+{
+ // Find the RxInfo
+ for (uint32_t i = 0; i < m_rx.size(); ++i)
+ {
+ if (m_rx[i].m_nd == nd)
+ { // Found it
+ m_rx[i].m_lbRx = lbRx.GetSeconds();
+ m_nRxEnd++;
+ if ((m_nRxEnd + m_nDrop) == m_nRx) return true; // Got them all
+ return false; // Still more rxEnd expected
+ }
+ }
+ // This should not happen, but if so we just bump the drop count
+ m_nDrop++;
+ if ((m_nRxEnd + m_nDrop) == m_nRx) return true; // Got them all
+ return false; // Still more rxEnd expected
+}
+
+void PacketInfo::AddRxDrop()
+{
+ m_nDrop++;
+}
+static map<uint32_t, PacketInfo> pendingWirelessPackets;
+
+void AnimationInterface::PhyTxBeginTrace (std::string context,
+ Ptr<const Packet> p,
+ Ptr<const NetDevice> nd,
+ const Time& txTime,
+ uint32_t nReceivers)
+{
+ // Add a new pending wireless
+ pendingWirelessPackets[p->GetUid()] =
+ PacketInfo(nd, nReceivers,
+ Simulator::Now(),
+ Simulator::Now() + txTime);
+}
+
+void AnimationInterface::PhyRxBeginTrace (std::string context,
+ Ptr<const Packet> p,
+ Ptr<const NetDevice> nd)
+{
+ pendingWirelessPackets[p->GetUid()].AddRxBegin(nd, Simulator::Now());
+}
+
+void AnimationInterface::PhyRxEndTrace (std::string context,
+ Ptr<const Packet> p,
+ Ptr<const NetDevice> nd)
+{
+ uint32_t uid = p->GetUid();
+ PacketInfo& pkt = pendingWirelessPackets[uid];
+ if (pkt.AddRxEnd(nd, Simulator::Now()))
+ {
+ OutputWirelessPacket(uid, pkt);
+ pendingWirelessPackets.erase(pendingWirelessPackets.find(uid));;
+ }
+}
+
+void AnimationInterface::PhyRxDropTrace (std::string context,
+ Ptr<const Packet> p,
+ Ptr<const NetDevice> nd)
+{
+ pendingWirelessPackets[p->GetUid()].AddRxDrop();
+}
+
+// Helper to output a wireless packet.
+// For now, only the XML interface is supported
+void AnimationInterface::OutputWirelessPacket(uint32_t uid, PacketInfo& pktInfo)
+{
+ if (!m_xml) return;
+ ostringstream oss;
+ uint32_t nodeId = pktInfo.m_nd->GetNode ()->GetId ();
+ double lbTx = pktInfo.m_lbTx;
+#ifdef REMOVE_LATER
+ // This is a hack until the notify tx end is working
+ if (lbTx == 0)
+ {
+ if (pktInfo.m_rx.empty())
+ {
+ lbTx = pktInfo.m_fbTx + 100E-6; // 100 microsec
+ }
+ else
+ {
+ lbTx = pktInfo.m_fbTx +
+ pktInfo.m_rx[0].m_lbRx - pktInfo.m_rx[0].m_fbRx;
+ }
+ }
+#endif
+ // Need to figure out about range
+ oss << setprecision(10);
+ oss << "<wpacket fromLp = \"0\" fromId = \"" << nodeId
+ << "\" fbTx = \"" << pktInfo.m_fbTx
+ << "\" lbTx = \"" << lbTx
+ << "\" range = \"500\">" << endl;
+ // Now add each rx
+ for (uint32_t i = 0; i < pktInfo.m_rx.size(); ++i)
+ {
+ RxInfo& rx = pktInfo.m_rx[i];
+ uint32_t rxId = rx.m_nd->GetNode ()->GetId ();
+ oss << "<rx toLp = \"0\" toId = \"" << rxId
+ << "\" fbRx = \"" << rx.m_fbRx
+ << "\" lbRx = \"" << rx.m_lbRx
+ << "\"/>" << endl;
+ }
+ oss << "</wpacket>" << endl;
+ WriteN (m_fHandle, oss.str ());
}
} // namespace ns3
« no previous file with comments | « src/helper/animation-interface.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b