diff --git a/examples/wifi-ap.cc b/examples/wifi-ap.cc index 39d91ee7d..f7f169ab8 100644 --- a/examples/wifi-ap.cc +++ b/examples/wifi-ap.cc @@ -26,6 +26,7 @@ #include "ns3/mobility-module.h" #include "ns3/contrib-module.h" #include "ns3/wifi-module.h" +#include "ns3/athstats-helper.h" #include @@ -110,6 +111,9 @@ AdvancePosition (Ptr node) int main (int argc, char *argv[]) { + CommandLine cmd; + cmd.Parse (argc, argv); + Packet::EnablePrinting (); // enable rts cts all the time. @@ -175,6 +179,10 @@ int main (int argc, char *argv[]) Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/RxError", MakeCallback (&PhyRxErrorTrace)); Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/Tx", MakeCallback (&PhyTxTrace)); Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/State", MakeCallback (&PhyStateTrace)); + + AthstatsHelper athstats; + athstats.EnableAthstats("athstats-sta", stas); + athstats.EnableAthstats("athstats-ap", ap); Simulator::Run (); diff --git a/src/helper/athstats-helper.cc b/src/helper/athstats-helper.cc new file mode 100644 index 000000000..ff3acccee --- /dev/null +++ b/src/helper/athstats-helper.cc @@ -0,0 +1,309 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 CTTC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Nicola Baldo + */ + +#include "ns3/log.h" +#include "ns3/assert.h" +#include "ns3/abort.h" +#include "ns3/simulator.h" +#include "ns3/nstime.h" +#include "ns3/config.h" +#include "athstats-helper.h" +#include +#include +#include + + +NS_LOG_COMPONENT_DEFINE("Athstats"); + +namespace ns3 { + + +AthstatsHelper::AthstatsHelper () + : m_interval (Seconds (1.0)) +{ +} + +void +AthstatsHelper::EnableAthstats (std::string filename, uint32_t nodeid, uint32_t deviceid) +{ + Ptr athstats = CreateObject (); + std::ostringstream oss; + oss << filename + << "_" << std::setfill ('0') << std::setw (3) << std::right << nodeid + << "_" << std::setfill ('0') << std::setw (3) << std::right << deviceid; + athstats->Open (oss.str ()); + + oss.str (""); + oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid; + std::string devicepath = oss.str (); + + Config::Connect (devicepath + "/Mac/MacTx", MakeCallback (&AthstatsWifiTraceSink::DevTxTrace, athstats)); + Config::Connect (devicepath + "/Mac/MacRx", MakeCallback (&AthstatsWifiTraceSink::DevRxTrace, athstats)); + + Config::Connect (devicepath + "/RemoteStationManager/TxRtsFailed", MakeCallback (&AthstatsWifiTraceSink::TxRtsFailedTrace, athstats)); + Config::Connect (devicepath + "/RemoteStationManager/MacTxDataFailed", MakeCallback (&AthstatsWifiTraceSink::TxDataFailedTrace, athstats)); + Config::Connect (devicepath + "/RemoteStationManager/MacTxFinalRtsFailed", MakeCallback (&AthstatsWifiTraceSink::TxFinalRtsFailedTrace, athstats)); + Config::Connect (devicepath + "/RemoteStationManager/MacTxFinalDataFailed", MakeCallback (&AthstatsWifiTraceSink::TxFinalDataFailedTrace, athstats)); + + Config::Connect (devicepath + "/Phy/State/RxOk", MakeCallback (&AthstatsWifiTraceSink::PhyRxOkTrace, athstats)); + Config::Connect (devicepath + "/Phy/State/RxError", MakeCallback (&AthstatsWifiTraceSink::PhyRxErrorTrace, athstats)); + Config::Connect (devicepath + "/Phy/State/Tx", MakeCallback (&AthstatsWifiTraceSink::PhyTxTrace, athstats)); + Config::Connect (devicepath + "/Phy/State/State", MakeCallback (&AthstatsWifiTraceSink::PhyStateTrace, athstats)); +} + +void +AthstatsHelper::EnableAthstats (std::string filename, Ptr nd) +{ + EnableAthstats (filename, nd->GetNode ()->GetId (), nd->GetIfIndex ()); +} + + +void +AthstatsHelper::EnableAthstats (std::string filename, NetDeviceContainer d) +{ + for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i) + { + Ptr dev = *i; + EnableAthstats (filename, dev->GetNode ()->GetId (), dev->GetIfIndex ()); + } +} + + +void +AthstatsHelper::EnableAthstats (std::string filename, NodeContainer n) +{ + NetDeviceContainer devs; + for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i) + { + Ptr node = *i; + for (uint32_t j = 0; j < node->GetNDevices (); ++j) + { + devs.Add (node->GetDevice (j)); + } + } + EnableAthstats (filename, devs); +} + + + + + +NS_OBJECT_ENSURE_REGISTERED (AthstatsWifiTraceSink); + +TypeId +AthstatsWifiTraceSink::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::AthstatsWifiTraceSink") + .SetParent () + .AddConstructor () + .AddAttribute ("Interval", + "Time interval between reports", + TimeValue (Seconds(1.0)), + MakeTimeAccessor (&AthstatsWifiTraceSink::m_interval), + MakeTimeChecker ()) + ; + return tid; +} + +AthstatsWifiTraceSink::AthstatsWifiTraceSink () + : m_txCount (0), + m_rxCount (0), + m_shortRetryCount (0), + m_longRetryCount (0), + m_exceededRetryCount (0), + m_phyRxOkCount (0), + m_phyRxErrorCount (0), + m_phyTxCount (0), + m_writer (0) +{ + Simulator::ScheduleNow (&AthstatsWifiTraceSink::WriteStats, this); +} + +AthstatsWifiTraceSink::~AthstatsWifiTraceSink () +{ + NS_LOG_FUNCTION (this); + + if (m_writer != 0) + { + NS_LOG_LOGIC ("m_writer nonzero " << m_writer); + if (m_writer->is_open ()) + { + NS_LOG_LOGIC ("m_writer open. Closing " << m_writer); + m_writer->close (); + } + + NS_LOG_LOGIC ("Deleting writer " << m_writer); + delete m_writer; + + NS_LOG_LOGIC ("m_writer = 0"); + m_writer = 0; + } + else + { + NS_LOG_LOGIC ("m_writer == 0"); + } +} + +void +AthstatsWifiTraceSink::ResetCounters () +{ + m_txCount = 0; + m_rxCount = 0; + m_shortRetryCount = 0; + m_longRetryCount = 0; + m_exceededRetryCount = 0; + m_phyRxOkCount = 0; + m_phyRxErrorCount = 0; + m_phyTxCount = 0; +} + +void +AthstatsWifiTraceSink::DevTxTrace (std::string context, Ptr p) +{ + NS_LOG_FUNCTION (this << context < p) +{ + NS_LOG_FUNCTION (this << context < packet, double snr, WifiMode mode, enum WifiPreamble preamble) +{ + NS_LOG_FUNCTION (this << context <open (name.c_str (), std::ios_base::binary | std::ios_base::out); + NS_ABORT_MSG_IF (m_writer->fail (), "AthstatsWifiTraceSink::Open (): m_writer->open (" << name.c_str () << ") failed"); + + NS_ASSERT_MSG (m_writer->is_open (), "AthstatsWifiTraceSink::Open (): m_writer not open"); + + NS_LOG_LOGIC ("Writer opened successfully"); +} + + +void +AthstatsWifiTraceSink::WriteStats () +{ + NS_ABORT_MSG_UNLESS (this, "function called with null this pointer, now=" << Now () ); + // the comments below refer to how each value maps to madwifi's athstats + // I know C strings are ugly but that's the quickest way to use exactly the same format as in madwifi + char str[200]; + snprintf (str, 200, "%8u %8u %7u %7u %7u %6u %6u %6u %7u %4u %3uM\n", + m_txCount, // /proc/net/dev transmitted packets to which we should subract mgmt frames + m_rxCount, // /proc/net/dev received packets but subracts mgmt frames from it + 0, // ast_tx_altrate, + m_shortRetryCount, // ast_tx_shortretry, + m_longRetryCount, // ast_tx_longretry, + m_exceededRetryCount, // ast_tx_xretries, + m_phyRxErrorCount, // ast_rx_crcerr, + 0, // ast_rx_badcrypt, + 0, // ast_rx_phyerr, + 0, // ast_rx_rssi, + 0 // rate + ); + + if (m_writer) + { + + *m_writer << str; + + ResetCounters (); + Simulator::Schedule (m_interval, &AthstatsWifiTraceSink::WriteStats, this); + } +} + + + + +} // namespace ns3 + + diff --git a/src/helper/athstats-helper.h b/src/helper/athstats-helper.h new file mode 100644 index 000000000..3f64bcd84 --- /dev/null +++ b/src/helper/athstats-helper.h @@ -0,0 +1,226 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 CTTC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Nicola Baldo + */ + +#ifndef ATHSTATS_HELPER_H +#define ATHSTATS_HELPER_H + +#include +#include "ns3/object.h" +#include "ns3/attribute.h" +#include "ns3/object-factory.h" +#include "ns3/node-container.h" +#include "ns3/net-device-container.h" +#include "ns3/nstime.h" +#include "ns3/wifi-phy.h" +#include "ns3/double.h" +#include "ns3/mac48-address.h" + +namespace ns3 { + + +class NetDevice; + +/** + * @brief create AthstatsWifiTraceSink instances and connect them to wifi devices + * + * + */ +class AthstatsHelper +{ +public: + AthstatsHelper (); + void EnableAthstats (std::string filename, uint32_t nodeid, uint32_t deviceid); + void EnableAthstats (std::string filename, Ptr nd); + void EnableAthstats (std::string filename, NetDeviceContainer d); + void EnableAthstats (std::string filename, NodeContainer n); + +private: + Time m_interval; +}; + + + + +/** + * @brief trace sink for wifi device that mimics madwifi's athstats tool. + * + * The AthstatsWifiTraceSink class is a trace sink to be connected to several of the traces + * available within a wifi device. The purpose of AthstatsWifiTraceSink is to + * mimic the behavior of the athstats tool distributed wih the madwifi + * driver. In particular, the reproduced behavior is that obtained + * when executing athstats without parameters: a report written in + * text format is produced every fixed interval, based on the events + * observed by the wifi device. + * + * Differences with the "real" athstats: + * + * - AthstatsWifiTraceSink is expected to write its output to a file + * (not to stdout). + * + * - only a subset of the metrics supported by athstats is supported + * by AthstatsWifiTraceSink + * + * - AthstatsWifiTraceSink does never produce a cumulative report. + */ +class AthstatsWifiTraceSink : public Object +{ +public: + static TypeId GetTypeId (void); + AthstatsWifiTraceSink (); + virtual ~AthstatsWifiTraceSink (); + + + /** + * function to be called when the net device transmittes a packet + * + * @param context + * @param p the packet being transmitted + */ + void DevTxTrace (std::string context, Ptr p); + + /** + * function to be called when the net device receives a packet + * + * @param context + * @param p the packet being received + */ + void DevRxTrace (std::string context, Ptr p); + + /** + * Function to be called when a RTS frame transmission by the considered + * device has failed + * + * @param context + * @param address the MAC address of the remote station + */ + void TxRtsFailedTrace (std::string context, Mac48Address address); + + /** + * Function to be called when a data frame transmission by the considered + * device has failed + * + * @param context + * @param address the MAC address of the remote station + */ + void TxDataFailedTrace (std::string context, Mac48Address address); + + /** + * Function to be called when the transmission of a RTS frame has + * exceeded the retry limit + * + * @param context + * @param address the MAC address of the remote station + */ + void TxFinalRtsFailedTrace (std::string context, Mac48Address address); + + /** + * Function to be called when the transmission of a data frame has + * exceeded the retry limit + * + * @param context + * @param address the MAC address of the remote station + */ + void TxFinalDataFailedTrace (std::string context, Mac48Address address); + + + /** + * Function to be called when the PHY layer of the considered + * device receives a frame + * + * @param context + * @param packet + * @param snr + * @param mode + * @param preamble + */ + void PhyRxOkTrace (std::string context, Ptr packet, double snr, WifiMode mode, enum WifiPreamble preamble); + + /** + * Function to be called when a frame reception by the PHY + * layer of the considered device resulted in an error due to a failure in the CRC check of + * the frame + * + * @param context + * @param packet + * @param snr + */ + void PhyRxErrorTrace (std::string context, Ptr packet, double snr); + + /** + * Function to be called when a frame is being transmitted by the + * PHY layer of the considered device + * + * @param context + * @param packet + * @param mode + * @param preamble + * @param txPower + */ + void PhyTxTrace (std::string context, Ptr packet, WifiMode mode, WifiPreamble preamble, uint8_t txPower); + + /** + * Function to be called when the PHY layer of the considered device + * changes state + * + * @param context + * @param start + * @param duration + * @param state + */ + void PhyStateTrace (std::string context, Time start, Time duration, enum WifiPhy::State state); + + /** + * Open a file for output + * + * @param name the name of the file to be opened. + */ + void Open (std::string const& name); + +private: + + void WriteStats (); + void ResetCounters (); + + + uint32_t m_txCount; + uint32_t m_rxCount; + uint32_t m_shortRetryCount; + uint32_t m_longRetryCount; + uint32_t m_exceededRetryCount; + uint32_t m_phyRxOkCount; + uint32_t m_phyRxErrorCount; + uint32_t m_phyTxCount; + + std::ofstream *m_writer; + + Time m_interval; + + +}; // class AthstatsWifiTraceSink + + + + +} // namespace ns3 + + + + +#endif /* ATHSTATS_HELPER_H */ diff --git a/src/helper/wscript b/src/helper/wscript index 7a7ca59ff..3ced3f13a 100644 --- a/src/helper/wscript +++ b/src/helper/wscript @@ -28,6 +28,7 @@ def build(bld): 'ipv4-global-routing-helper.cc', 'ipv4-list-routing-helper.cc', 'ipv4-routing-helper.cc', + 'athstats-helper.cc', 'ipv6-address-helper.cc', 'ipv6-interface-container.cc', 'ipv6-static-routing-helper.cc', @@ -64,6 +65,7 @@ def build(bld): 'ipv4-global-routing-helper.h', 'ipv4-list-routing-helper.h', 'ipv4-routing-helper.h', + 'athstats-helper.h', 'ipv6-address-helper.h', 'ipv6-interface-container.h', 'ipv6-static-routing-helper.h',