54 bool Active()
const {
return m_out.is_open(); }
60 void Start(
const std::string& path,
const std::string& header,
const NodeContainer& nodes,
61 Ptr<FlowMonitor> monitor, Ptr<Ipv4FlowClassifier> classifier, uint16_t dataPort,
62 double step,
double stop,
double scale) {
67 m_classifier = classifier;
72 for (uint32_t i = 0; i < nodes.GetN(); ++i) {
73 Ptr<Ipv4> ip = nodes.Get(i)->GetObject<Ipv4>();
74 for (uint32_t k = 0; ip && k < ip->GetNInterfaces(); ++k) {
75 for (uint32_t a = 0; a < ip->GetNAddresses(k); ++a) {
76 const Ipv4Address addr = ip->GetAddress(k, a).GetLocal();
77 if (addr != Ipv4Address::GetLoopback()) m_index[addr.Get()] = i;
80 Ptr<anthocnet::RoutingProtocol> rp =
81 ip ? DynamicCast<anthocnet::RoutingProtocol>(ip->GetRoutingProtocol()) :
nullptr;
83 if (rp) rp->TraceConnectWithoutContext(
"Tx", MakeCallback(&VizTrace::AntTx,
this));
85 m_out <<
"{\"v\":1,\"kind\":\"header\"," << header <<
",\"nodes\":" << nodes.GetN()
86 <<
",\"step\":" << step <<
",\"time\":" << stop <<
",\"scale\":" << scale <<
"}\n";
87 Simulator::Schedule(Seconds(step), &VizTrace::Sample,
this);
91 void Finish(uint64_t tx, uint64_t rx,
double pdr) {
97 if (m_lastT < m_stop - 1e-9) WriteStep(m_stop);
98 m_out <<
"{\"kind\":\"end\",\"tx\":" << tx <<
",\"rx\":" << rx <<
",\"pdr\":" << pdr
104 bool Done()
const {
return m_done; }
107 void AntTx(uint8_t, uint8_t,
bool) { ++m_ants; }
109 int IndexOf(Ipv4Address a)
const {
110 auto it = m_index.find(a.Get());
111 return it == m_index.end() ? -1 :
static_cast<int>(it->second);
115 const double now = Simulator::Now().GetSeconds();
117 if (now + m_step <= m_stop + 1e-9)
118 Simulator::Schedule(Seconds(m_step), &VizTrace::Sample,
this);
121 void WriteStep(
double now) {
123 m_out <<
"{\"t\":" << now;
126 for (uint32_t i = 0; i < m_nodes.GetN(); ++i) {
127 if (m_nodes.Get(i)->GetObject<MobilityModel>()) any =
true;
131 for (uint32_t i = 0; i < m_nodes.GetN(); ++i) {
132 Ptr<MobilityModel> m = m_nodes.Get(i)->GetObject<MobilityModel>();
133 const Vector v = m ? m->GetPosition() : Vector();
134 m_out << (i ?
"," :
"") <<
'[' << std::lround(v.x / m_scale) <<
','
135 << std::lround(v.y / m_scale) <<
',' << std::lround(v.z / m_scale) <<
']';
140 uint64_t tx = 0, rx = 0, dRoute = 0, dTtl = 0, dQueue = 0;
141 std::vector<std::pair<std::pair<int, int>, Ipv4Address>> flows;
142 for (
const auto& kv : m_monitor->GetFlowStats()) {
143 const Ipv4FlowClassifier::FiveTuple t = m_classifier->FindFlow(kv.first);
144 if (t.destinationPort != m_port)
continue;
145 tx += kv.second.txPackets;
146 rx += kv.second.rxPackets;
147 const std::vector<uint32_t>& pd = kv.second.packetsDropped;
148 auto reason = [&pd](std::size_t i) -> uint64_t {
return i < pd.size() ? pd[i] : 0u; };
150 reason(Ipv4FlowProbe::DROP_NO_ROUTE) + reason(Ipv4FlowProbe::DROP_ROUTE_ERROR);
151 dTtl += reason(Ipv4FlowProbe::DROP_TTL_EXPIRE);
152 dQueue += reason(Ipv4FlowProbe::DROP_QUEUE) + reason(Ipv4FlowProbe::DROP_QUEUE_DISC);
153 const int s = IndexOf(t.sourceAddress), d = IndexOf(t.destinationAddress);
154 if (s >= 0 && d >= 0) flows.push_back({{s, d}, t.destinationAddress});
156 m_out <<
",\"tx\":" << tx <<
",\"rx\":" << rx <<
",\"ants\":" << m_ants
157 <<
",\"drop\":{\"route\":" << dRoute <<
",\"ttl\":" << dTtl <<
",\"queue\":" << dQueue
161 std::set<std::pair<int, int>> seen;
162 m_out <<
",\"paths\":[";
164 for (
const auto& fl : flows) {
165 const std::pair<int, int>& f = fl.first;
166 if (!seen.insert(f).second)
continue;
167 m_out << (first ?
"" :
",") <<
"{\"f\":[" << f.first <<
',' << f.second <<
"],\"p\":["
171 std::set<int> visited{cur};
173 const Ipv4Address dest = fl.second;
174 for (
int hop = 0; hop < 64 && cur != f.second; ++hop) {
175 Ptr<anthocnet::RoutingProtocol> rp = m_rp[cur];
176 const int nb = rp ? IndexOf(rp->StrongestNextHop(dest)) : -1;
177 if (nb < 0 || !visited.insert(nb).second)
break;
187 NodeContainer m_nodes;
188 Ptr<FlowMonitor> m_monitor;
189 Ptr<Ipv4FlowClassifier> m_classifier;
191 double m_step = 1.0, m_stop = 0.0, m_scale = 1.0;
192 std::map<uint32_t, uint32_t> m_index;
193 std::vector<Ptr<anthocnet::RoutingProtocol>> m_rp;
195 double m_lastT = 0.0;