Routing decoupled from class Ipv4
All calls of the form "Ipv4::AddHostRouteTo ()" etc. (i.e. to
add static routes, both unicast and multicast) have been moved to a new
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index 1edbeadca..df99fd29d 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -25,6 +25,7 @@ New user-visible features
b) 802.11 PHY:
- 802.11b PHY support (Gary Pei)
- Nakagami propagation loss model (Timo Bingmann)
+ - radiotap and prism headers for PCAP output (Nicola Baldo)
c) GammaVariable and ErlangVariable (Timo Bingmann)
API changes from ns-3.4
diff --git a/examples/mixed-wireless.cc b/examples/mixed-wireless.cc
index eafe01a67..fa72f3ec0 100644
--- a/examples/mixed-wireless.cc
+++ b/examples/mixed-wireless.cc
@@ -392,9 +392,9 @@ main (int argc, char *argv[])
// Let's do a pcap trace on the application source and sink, ifIndex 0
// Csma captures in non-promiscuous mode
CsmaHelper::EnablePcap ("mixed-wireless", appSource->GetId (), 0, false);
- YansWifiPhyHelper::EnablePcap ("mixed-wireless", appSink->GetId (), 0);
- YansWifiPhyHelper::EnablePcap ("mixed-wireless", 9, 2);
- YansWifiPhyHelper::EnablePcap ("mixed-wireless", 9, 0);
+ wifiPhy.EnablePcap ("mixed-wireless", appSink->GetId (), 0);
+ wifiPhy.EnablePcap ("mixed-wireless", 9, 2);
+ wifiPhy.EnablePcap ("mixed-wireless", 9, 0);
}
if (useCourseChangeCallback == true)
diff --git a/examples/simple-wifi-frame-aggregation.cc b/examples/simple-wifi-frame-aggregation.cc
index 765b108ca..d1bf74266 100644
--- a/examples/simple-wifi-frame-aggregation.cc
+++ b/examples/simple-wifi-frame-aggregation.cc
@@ -141,7 +141,7 @@ int main (int argc, char *argv[])
Simulator::Stop (Seconds (10.0));
- YansWifiPhyHelper::EnablePcap ("test-802.11n",
+ phy.EnablePcap ("test-802.11n",
wifiNodes.Get (nWifi - 1)->GetId (), 0);
Simulator::Run ();
diff --git a/examples/third.cc b/examples/third.cc
index f655dc21d..656ef1560 100644
--- a/examples/third.cc
+++ b/examples/third.cc
@@ -164,7 +164,7 @@ main (int argc, char *argv[])
Simulator::Stop (Seconds (10.0));
PointToPointHelper::EnablePcapAll ("third");
- YansWifiPhyHelper::EnablePcap ("third", apDevices.Get (0));
+ phy.EnablePcap ("third", apDevices.Get (0));
CsmaHelper::EnablePcap ("third", csmaDevices.Get (0), true);
Simulator::Run ();
diff --git a/examples/wifi-wired-bridging.cc b/examples/wifi-wired-bridging.cc
index 78e968c60..a08e8d12e 100644
--- a/examples/wifi-wired-bridging.cc
+++ b/examples/wifi-wired-bridging.cc
@@ -89,6 +89,10 @@ int main (int argc, char *argv[])
backboneDevices = csma.Install (backboneNodes);
double wifiX = 0.0;
+
+ YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+ wifiPhy.SetPcapFormat(YansWifiPhyHelper::PCAP_FORMAT_80211_RADIOTAP);
+
for (uint32_t i = 0; i < nWifis; ++i)
{
// calculate ssid for wifi subnetwork
@@ -105,7 +109,6 @@ int main (int argc, char *argv[])
BridgeHelper bridge;
WifiHelper wifi = WifiHelper::Default ();
NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
- YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
wifiPhy.SetChannel (wifiChannel.Create ());
@@ -182,8 +185,8 @@ int main (int argc, char *argv[])
apps.Start (Seconds (0.5));
apps.Stop (Seconds (3.0));
- YansWifiPhyHelper::EnablePcap ("wifi-wired-bridging", apDevices[0]);
- YansWifiPhyHelper::EnablePcap ("wifi-wired-bridging", apDevices[1]);
+ wifiPhy.EnablePcap ("wifi-wired-bridging", apDevices[0]);
+ wifiPhy.EnablePcap ("wifi-wired-bridging", apDevices[1]);
std::ofstream os;
os.open ("wifi-wired-bridging.mob");
diff --git a/src/common/pcap-writer.cc b/src/common/pcap-writer.cc
index 0c8175fa5..09f49de2e 100644
--- a/src/common/pcap-writer.cc
+++ b/src/common/pcap-writer.cc
@@ -41,6 +41,8 @@ enum {
PCAP_PPP = 9,
PCAP_RAW_IP = 101,
PCAP_80211 = 105,
+ PCAP_80211_PRISM = 119,
+ PCAP_80211_RADIOTAP = 127,
};
PcapWriter::PcapWriter ()
@@ -115,6 +117,20 @@ PcapWriter::WriteWifiHeader (void)
WriteHeader (PCAP_80211);
}
+void
+PcapWriter::WriteWifiRadiotapHeader (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ WriteHeader (PCAP_80211_RADIOTAP);
+}
+
+void
+PcapWriter::WriteWifiPrismHeader (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ WriteHeader (PCAP_80211_PRISM);
+}
+
void
PcapWriter::WritePppHeader (void)
{
@@ -133,6 +149,7 @@ PcapWriter::WriteHeader (uint32_t network)
Write32 (0);
Write32 (0xffff);
Write32 (network);
+ m_pcapMode = network;
}
void
@@ -151,12 +168,296 @@ PcapWriter::WritePacket (Ptr packet)
}
}
+
+void PcapWriter::WriteWifiMonitorPacket(Ptr packet, uint16_t channelFreqMhz, uint32_t rate, bool isShortPreamble, bool isTx, double signalDbm, double noiseDbm)
+{
+ NS_LOG_FUNCTION (this << packet->GetSize() << channelFreqMhz << rate << isShortPreamble << isTx << signalDbm << noiseDbm);
+
+ if (m_writer == 0)
+ {
+ return;
+ }
+
+ if (m_pcapMode == PCAP_80211)
+ {
+ WritePacket (packet);
+ return;
+ }
+
+ /* the following is common between PRISM and RADIOTAP */
+
+ uint64_t current = Simulator::Now ().GetMicroSeconds ();
+ uint64_t s = current / 1000000;
+ uint64_t us = current % 1000000;
+ Write32 (s & 0xffffffff);
+ Write32 (us & 0xffffffff);
+
+
+ // MAC timestamp. Actually according to radiotap specifications
+ // (http://www.radiotap.org/defined-fields/TSFT) this should be
+ // the time "when the first bit of the MPDU arrived at the
+ // MAC". This is not exactly what we're doing here, but to handle
+ // this properly we would need to first of all investigate how
+ // real devices (e.g. madwifi) handle this case, especially for TX
+ // packets (radiotap specs says TSFT is not used for TX packets,
+ // but madwifi actually uses it).
+ uint64_t tsft = current;
+
+ if (m_pcapMode == PCAP_80211_PRISM)
+ {
+
+#define PRISM_MSG_CODE 0x00000044
+#define PRISM_MSG_LENGTH 144
+#define PRISM_DID_HOSTTIME 0x00010044
+#define PRISM_DID_MACTIME 0x00020044
+#define PRISM_DID_CHANNEL 0x00030044
+#define PRISM_DID_RSSI 0x00040044
+#define PRISM_DID_SQ 0x00050044
+#define PRISM_DID_SIGNAL 0x00060044
+#define PRISM_DID_NOISE 0x00070044
+#define PRISM_DID_RATE 0x00080044
+#define PRISM_DID_ISTX 0x00090044
+#define PRISM_DID_FRMLEN 0x000A0044
+
+#define PRISM_STATUS_PRESENT 0
+#define PRISM_STATUS_ABSENT 1
+#define PRISM_ITEM_LENGTH 4
+
+
+
+ uint32_t size = packet->GetSize () + PRISM_MSG_LENGTH;
+ Write32 (size); // total packet size
+ Write32 (size); // captured size
+
+ Write32(PRISM_MSG_CODE);
+ Write32(PRISM_MSG_LENGTH);
+ WriteData((const uint8_t *)"unknown wifi device!!!!!!!!", 16);
+
+ Write32(PRISM_DID_HOSTTIME);
+ Write16(PRISM_STATUS_PRESENT);
+ Write16(PRISM_ITEM_LENGTH);
+ // madwifi reports hosttime in jiffies.
+ // We calculate jiffies assuming HZ = 10
+ Write32((uint32_t) (Now ().GetMilliSeconds () / 10 ) );
+
+ Write32(PRISM_DID_MACTIME);
+ Write16(PRISM_STATUS_PRESENT);
+ Write16(PRISM_ITEM_LENGTH);
+ // This looses precision, which is a well-known issue of the prism
+ // header format.
+ Write32((uint32_t) tsft);
+
+ Write32(PRISM_DID_CHANNEL);
+ Write16(PRISM_STATUS_PRESENT);
+ Write16(PRISM_ITEM_LENGTH);
+ // convert from frequency to channel number. This conversion is
+ // correct only for IEEE 802.11b/g channels 1-13.
+ Write32((channelFreqMhz - 2407) / 5);
+
+ Write32(PRISM_DID_RSSI);
+ Write16(PRISM_STATUS_PRESENT);
+ Write16(PRISM_ITEM_LENGTH);
+ // madwifi here reports a value which is said to be "the value in
+ // dBm above noise". Apart from the fact that this is incorrect
+ // (if it is relative to a value in dBm, then it must be in dB,
+ // not in dBm again), this means that in fact it is not a RSSI
+ // (which stands for Received Signal Strength Indicator) but it is
+ // rather a Signal to Noise Ratio (SNR), of course in dB.
+ // Anyway, in the end we calculate the value exactly as madwifi does.
+ Write32(round(signalDbm - noiseDbm));
+
+ // SQ field not used. I would expect a PRISM_STATUS_ABSENT to be
+ // needed here, but if you look at the prism header that madwifi
+ // produces you'll just see that the whole field structure is
+ // zeroed.
+ Write32(0);
+ Write16(0);
+ Write16(0);
+ Write32(0);
+
+ Write32(PRISM_DID_SIGNAL);
+ Write16(PRISM_STATUS_PRESENT);
+ Write16(PRISM_ITEM_LENGTH);
+ Write32(round(signalDbm));
+
+ Write32(PRISM_DID_NOISE);
+ Write16(PRISM_STATUS_PRESENT);
+ Write16(PRISM_ITEM_LENGTH);
+ Write32(round(noiseDbm));
+
+ Write32(PRISM_DID_RATE);
+ Write16(PRISM_STATUS_PRESENT);
+ Write16(PRISM_ITEM_LENGTH);
+ Write32(rate);
+
+ Write32(PRISM_DID_ISTX);
+ Write16(PRISM_STATUS_PRESENT);
+ Write16(PRISM_ITEM_LENGTH);
+ Write32(isTx ? 1 : 0);
+
+ Write32(PRISM_DID_FRMLEN);
+ Write16(PRISM_STATUS_ABSENT);
+ Write16(PRISM_ITEM_LENGTH);
+ Write32(packet->GetSize ());
+
+
+
+ } // PCAP_80211_PRISM
+
+ else if (m_pcapMode == PCAP_80211_RADIOTAP)
+ {
+ NS_LOG_LOGIC("writing radiotap packet");
+
+#define RADIOTAP_TSFT 0x00000001
+#define RADIOTAP_FLAGS 0x00000002
+#define RADIOTAP_RATE 0x00000004
+#define RADIOTAP_CHANNEL 0x00000008
+#define RADIOTAP_FHSS 0x00000010
+#define RADIOTAP_DBM_ANTSIGNAL 0x00000020
+#define RADIOTAP_DBM_ANTNOISE 0x00000040
+#define RADIOTAP_LOCK_QUALITY 0x00000080
+#define RADIOTAP_TX_ATTENUATION 0x00000100
+#define RADIOTAP_DB_TX_ATTENUATION 0x00000200
+#define RADIOTAP_DBM_TX_POWER 0x00000200
+#define RADIOTAP_ANTENNA 0x00000400
+#define RADIOTAP_DB_ANTSIGNAL 0x00000800
+#define RADIOTAP_DB_ANTNOISE 0x00001000
+#define RADIOTAP_EXT 0x10000000
+
+#define RADIOTAP_FLAG_NONE 0x00
+#define RADIOTAP_FLAG_CFP 0x01
+#define RADIOTAP_FLAG_SHORTPRE 0x02
+#define RADIOTAP_FLAG_WEP 0x04
+#define RADIOTAP_FLAG_FRAG 0x08
+#define RADIOTAP_FLAG_FCS 0x10
+#define RADIOTAP_FLAG_DATAPAD 0x20
+#define RADIOTAP_FLAG_BADFCS 0x40
+
+#define RADIOTAP_CHANNEL_TURBO 0x0010
+#define RADIOTAP_CHANNEL_CCK 0x0020
+#define RADIOTAP_CHANNEL_OFDM 0x0040
+#define RADIOTAP_CHANNEL_2GHZ 0x0080
+#define RADIOTAP_CHANNEL_5GHZ 0x0100
+#define RADIOTAP_CHANNEL_PASSIVE 0x0200
+#define RADIOTAP_CHANNEL_DYN 0x0400
+#define RADIOTAP_CHANNEL_GFSK 0x0800
+
+#define RADIOTAP_RX_PRESENT (RADIOTAP_TSFT | RADIOTAP_FLAGS | RADIOTAP_RATE | RADIOTAP_CHANNEL | RADIOTAP_DBM_ANTSIGNAL | RADIOTAP_DBM_ANTNOISE)
+#define RADIOTAP_RX_LENGTH (8+8+1+1+2+2+1+1)
+
+#define RADIOTAP_TX_PRESENT (RADIOTAP_TSFT | RADIOTAP_FLAGS | RADIOTAP_RATE | RADIOTAP_CHANNEL)
+#define RADIOTAP_TX_LENGTH (8+8+1+1+2+2)
+
+ uint32_t size;
+ if (isTx)
+ {
+ size = packet->GetSize () + RADIOTAP_TX_LENGTH;
+ }
+ else
+ {
+ size = packet->GetSize () + RADIOTAP_RX_LENGTH;
+ }
+ Write32 (size); // total packet size
+ Write32 (size); // captured size
+
+ Write8(0); // radiotap version
+ Write8(0); // padding
+
+ if (isTx)
+ {
+ Write16(RADIOTAP_TX_LENGTH);
+ Write32(RADIOTAP_TX_PRESENT);
+ }
+ else
+ {
+ Write16(RADIOTAP_RX_LENGTH);
+ Write32(RADIOTAP_RX_PRESENT);
+ }
+
+ Write64(tsft);
+
+ uint8_t flags = RADIOTAP_FLAG_NONE;
+ if (isShortPreamble)
+ {
+ flags |= RADIOTAP_FLAG_SHORTPRE;
+ }
+ Write8(flags);
+
+
+ Write8(rate);
+
+ Write16((uint16_t) channelFreqMhz);
+
+ // we might want to make this setting depend on the WifiMode and
+ // on the ChannelFrequency at some time in the future. But for now
+ // I think a fixed setting is more than enough for most purposes.
+ Write16(RADIOTAP_CHANNEL_OFDM | RADIOTAP_CHANNEL_2GHZ);
+
+ if (!isTx)
+ {
+
+ Write8 (RoundToInt8 (signalDbm));
+ Write8 (RoundToInt8 (noiseDbm));
+ }
+
+ } // PCAP_80211_RADIOTAP
+
+
+ else
+ {
+ NS_LOG_ERROR("unknown PCAP mode");
+ return;
+ }
+
+ // finally, write rest of packet
+ WriteData (packet->PeekData (), packet->GetSize ());
+}
+
+
+
+
+int8_t
+PcapWriter::RoundToInt8 (double value)
+{
+ if (value < -128)
+ {
+ return -128;
+ }
+ if (value > 127)
+ {
+ return 127;
+ }
+ return ((int8_t) round(value));
+}
+
+
+
+
+
+
void
PcapWriter::WriteData (uint8_t const*buffer, uint32_t size)
{
+ NS_LOG_FUNCTION(this << size);
m_writer->write ((char const *)buffer, size);
}
+
+void
+PcapWriter::Write64 (uint64_t data)
+{
+ uint8_t buffer[8];
+ buffer[0] = (data >> 0) & 0xff;
+ buffer[1] = (data >> 8) & 0xff;
+ buffer[2] = (data >> 16) & 0xff;
+ buffer[3] = (data >> 24) & 0xff;
+ buffer[4] = (data >> 32) & 0xff;
+ buffer[5] = (data >> 40) & 0xff;
+ buffer[6] = (data >> 48) & 0xff;
+ buffer[7] = (data >> 56) & 0xff;
+ WriteData (buffer, 8);
+}
+
void
PcapWriter::Write32 (uint32_t data)
{
@@ -177,4 +478,12 @@ PcapWriter::Write16 (uint16_t data)
WriteData (buffer, 2);
}
+void
+PcapWriter::Write8 (uint8_t data)
+{
+ WriteData (&data, 1);
+}
+
+
+
} // namespace ns3
diff --git a/src/common/pcap-writer.h b/src/common/pcap-writer.h
index 10a6528d7..7a819593d 100644
--- a/src/common/pcap-writer.h
+++ b/src/common/pcap-writer.h
@@ -74,6 +74,24 @@ public:
*/
void WriteWifiHeader (void);
+ /**
+ * Write a pcap header in the output file which specifies
+ * that the content of the file will be 802.11 Packets preceded by a
+ * radiotap header providing PHY layer info. This method should be
+ * invoked before ns3::PcapWriter::WritePacket and after
+ * ns3::PcapWriter::Open.
+ */
+ void WriteWifiRadiotapHeader (void);
+
+ /**
+ * Write a pcap header in the output file which specifies
+ * that the content of the file will be 802.11 Packets preceded by a
+ * prism header providing PHY layer info. This method should be
+ * invoked before ns3::PcapWriter::WritePacket and after
+ * ns3::PcapWriter::Open.
+ */
+ void WriteWifiPrismHeader (void);
+
/**
* Write a pcap header in the output file which specifies
* that the content of the file will be ppp Packets. This
@@ -87,12 +105,40 @@ public:
*/
void WritePacket (Ptr packet);
+ /**
+ * Write a Packet, possibly adding wifi PHY layer information to it
+ *
+ * @param packet the packet being received
+ * @param channelFreqMhz the frequency in MHz at which the packet is
+ * received. Note that in real devices this is normally the
+ * frequency to which the receiver is tuned, and this can be
+ * different than the frequency at which the packet was originally
+ * transmitted. This is because it is possible to have the receiver
+ * tuned on a given channel and still to be able to receive packets
+ * on a nearby channel.
+ * @param rate the PHY data rate in units of 500kbps (i.e., the same
+ * units used both for the radiotap and for the prism header)
+ * @param isPreambleShort true if short preamble is used, false otherwise
+ * @param isTx true if packet is being transmitted, false when
+ * packet is being received
+ * @param signalDbm signal power in dBm
+ * @param noiseDbm noise power in dBm
+ */
+ void WriteWifiMonitorPacket(Ptr packet, uint16_t channelFreqMhz, uint32_t rate, bool isShortPreamble, bool isTx, double signalDbm, double noiseDbm);
+
+
+
+
private:
void WriteData (uint8_t const*buffer, uint32_t size);
+ void Write64 (uint64_t data);
void Write32 (uint32_t data);
void Write16 (uint16_t data);
+ void Write8 (uint8_t data);
void WriteHeader (uint32_t network);
+ int8_t RoundToInt8 (double value);
std::ofstream *m_writer;
+ uint32_t m_pcapMode;
};
} // namespace ns3
diff --git a/src/devices/wifi/wifi-phy.cc b/src/devices/wifi/wifi-phy.cc
index 3e8eee998..617610c8d 100644
--- a/src/devices/wifi/wifi-phy.cc
+++ b/src/devices/wifi/wifi-phy.cc
@@ -73,9 +73,12 @@ WifiPhy::GetTypeId (void)
.AddTraceSource ("PhyRxDrop",
"Trace source indicating a packet has been dropped by the device during reception",
MakeTraceSourceAccessor (&WifiPhy::m_phyRxDropTrace))
- .AddTraceSource ("PromiscSniffer",
- "Trace source simulating a promiscuous packet sniffer attached to the device",
- MakeTraceSourceAccessor (&WifiPhy::m_phyPromiscSnifferTrace))
+ .AddTraceSource ("PromiscSnifferRx",
+ "Trace source simulating a wifi device in monitor mode sniffing all received frames",
+ MakeTraceSourceAccessor (&WifiPhy::m_phyPromiscSniffRxTrace))
+ .AddTraceSource ("PromiscSnifferTx",
+ "Trace source simulating the capability of a wifi device in monitor mode to sniff all frames being transmitted",
+ MakeTraceSourceAccessor (&WifiPhy::m_phyPromiscSniffTxTrace))
;
return tid;
}
@@ -194,9 +197,15 @@ WifiPhy::NotifyRxDrop (Ptr packet)
}
void
-WifiPhy::NotifyPromiscSniff (Ptr packet)
+WifiPhy::NotifyPromiscSniffRx (Ptr packet, uint16_t channelFreqMhz, uint32_t rate, bool isShortPreamble, double signalDbm, double noiseDbm)
{
- m_phyPromiscSnifferTrace (packet);
+ m_phyPromiscSniffRxTrace (packet, channelFreqMhz, rate, isShortPreamble, signalDbm, noiseDbm);
+}
+
+void
+WifiPhy::NotifyPromiscSniffTx (Ptr packet, uint16_t channelFreqMhz, uint32_t rate, bool isShortPreamble)
+{
+ m_phyPromiscSniffTxTrace (packet, channelFreqMhz, rate, isShortPreamble);
}
WifiMode
diff --git a/src/devices/wifi/wifi-phy.h b/src/devices/wifi/wifi-phy.h
index 544bba317..6ce1167e5 100644
--- a/src/devices/wifi/wifi-phy.h
+++ b/src/devices/wifi/wifi-phy.h
@@ -294,11 +294,46 @@ public:
*/
void NotifyRxDrop (Ptr packet);
- /**
- * Public method used to fire a PromiscSniffer trace. Implemented for encapsulation
+ /**
+ *
+ * Public method used to fire a PromiscSniffer trace for a wifi packet being received. Implemented for encapsulation
* purposes.
+ *
+ * @param packet the packet being received
+ * @param channelFreqMhz the frequency in MHz at which the packet is
+ * received. Note that in real devices this is normally the
+ * frequency to which the receiver is tuned, and this can be
+ * different than the frequency at which the packet was originally
+ * transmitted. This is because it is possible to have the receiver
+ * tuned on a given channel and still to be able to receive packets
+ * on a nearby channel.
+ * @param rate the PHY data rate in units of 500kbps (i.e., the same
+ * units used both for the radiotap and for the prism header)
+ * @param isPreambleShort true if short preamble is used, false otherwise
+ * @param signalDbm signal power in dBm
+ * @param noiseDbm noise power in dBm
*/
- void NotifyPromiscSniff (Ptr packet);
+ void NotifyPromiscSniffRx (Ptr packet, uint16_t channelFreqMhz, uint32_t rate, bool isShortPreamble, double signalDbm, double noiseDbm);
+
+ /**
+ *
+ * Public method used to fire a PromiscSniffer trace for a wifi packet being transmitted. Implemented for encapsulation
+ * purposes.
+ *
+ * @param packet the packet being received
+ * @param channelFreqMhz the frequency in MHz at which the packet is
+ * received. Note that in real devices this is normally the
+ * frequency to which the receiver is tuned, and this can be
+ * different than the frequency at which the packet was originally
+ * transmitted. This is because it is possible to have the receiver
+ * tuned on a given channel and still to be able to receive packets
+ * on a nearby channel.
+ * @param rate the PHY data rate in units of 500kbps (i.e., the same
+ * units used both for the radiotap and for the prism header)
+ * @param isPreambleShort true if short preamble is used, false otherwise
+ */
+ void NotifyPromiscSniffTx (Ptr packet, uint16_t channelFreqMhz, uint32_t rate, bool isShortPreamble);
+
private:
/**
@@ -349,24 +384,29 @@ private:
TracedCallback > m_phyRxDropTrace;
/**
- * A trace source that emulates a promiscuous mode protocol sniffer connected
- * to the device. This trace source fire on packets destined for any host
- * just like your average everyday packet sniffer.
- *
- * On the transmit size, this trace hook will fire after a packet is dequeued
- * from the device queue for transmission. In Linux, for example, this would
- * correspond to the point just before a device hard_start_xmit where
- * dev_queue_xmit_nit is called to dispatch the packet to the PF_PACKET
- * ETH_P_ALL handlers.
- *
- * On the receive side, this trace hook will fire when a packet is received,
- * just before the receive callback is executed. In Linux, for example,
- * this would correspond to the point at which the packet is dispatched to
- * packet sniffers in netif_receive_skb.
+ * A trace source that emulates a wifi device in monitor mode
+ * sniffing a packet being received.
+ *
+ * As a reference with the real world, firing this trace
+ * corresponds in the madwifi driver to calling the function
+ * ieee80211_input_monitor()
*
* \see class CallBackTraceSource
*/
- TracedCallback > m_phyPromiscSnifferTrace;
+ TracedCallback, uint16_t, uint32_t, bool, double, double> m_phyPromiscSniffRxTrace;
+
+ /**
+ * A trace source that emulates a wifi device in monitor mode
+ * sniffing a packet being transmitted.
+ *
+ * As a reference with the real world, firing this trace
+ * corresponds in the madwifi driver to calling the function
+ * ieee80211_input_monitor()
+ *
+ * \see class CallBackTraceSource
+ */
+ TracedCallback, uint16_t, uint32_t, bool> m_phyPromiscSniffTxTrace;
+
};
} // namespace ns3
diff --git a/src/devices/wifi/yans-wifi-phy.cc b/src/devices/wifi/yans-wifi-phy.cc
index 38ea922ae..389a631f6 100644
--- a/src/devices/wifi/yans-wifi-phy.cc
+++ b/src/devices/wifi/yans-wifi-phy.cc
@@ -121,8 +121,10 @@ YansWifiPhy::GetTypeId (void)
}
YansWifiPhy::YansWifiPhy ()
- : m_endSyncEvent (),
- m_random (0.0, 1.0)
+ : m_channelFreqMhz(2437),
+ m_endSyncEvent (),
+ m_random (0.0, 1.0)
+
{
NS_LOG_FUNCTION (this);
m_state = CreateObject ();
@@ -408,7 +410,9 @@ YansWifiPhy::SendPacket (Ptr packet, WifiMode txMode, WifiPreamble
m_endSyncEvent.Cancel ();
}
NotifyTxBegin (packet);
- NotifyPromiscSniff (packet);
+ uint32_t dataRate500KbpsUnits = txMode.GetDataRate () / 500000;
+ bool isShortPreamble = (WIFI_PREAMBLE_SHORT == preamble);
+ NotifyPromiscSniffTx (packet, m_channelFreqMhz, dataRate500KbpsUnits, isShortPreamble);
m_state->SwitchToTx (txDuration, packet, txMode, preamble, txPower);
m_channel->Send (this, packet, GetPowerDbm (txPower) + m_txGainDb, txMode, preamble);
}
@@ -577,11 +581,14 @@ YansWifiPhy::EndSync (Ptr packet, Ptr event)
NS_LOG_DEBUG ("mode="<<(event->GetPayloadMode ().GetDataRate ())<<
", snr="< node, Ptr device) const
return phy;
}
+
+void
+YansWifiPhyHelper::SetPcapFormat (enum PcapFormat format)
+{
+ m_pcapFormat = format;
+}
+
+
void
YansWifiPhyHelper::EnablePcap (std::string filename, uint32_t nodeid, uint32_t deviceid)
{
@@ -218,11 +236,28 @@ YansWifiPhyHelper::EnablePcap (std::string filename, uint32_t nodeid, uint32_t d
// with the locally-defined WifiPhyHelper::Create method.
Ptr pcap = ::ns3::Create ();
pcap->Open (oss.str ());
- pcap->WriteWifiHeader ();
+
+ switch (m_pcapFormat) {
+ case PCAP_FORMAT_80211:
+ pcap->WriteWifiHeader ();
+ break;
+ case PCAP_FORMAT_80211_RADIOTAP:
+ pcap->WriteWifiRadiotapHeader ();
+ break;
+ case PCAP_FORMAT_80211_PRISM:
+ pcap->WriteWifiPrismHeader ();
+ break;
+ }
+
oss.str ("");
oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid;
- oss << "/$ns3::WifiNetDevice/Phy/PromiscSniffer";
- Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&PcapSnifferEvent, pcap));
+ oss << "/$ns3::WifiNetDevice/Phy/PromiscSnifferTx";
+ Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&PcapSniffTxEvent, pcap));
+
+ oss.str ("");
+ oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid;
+ oss << "/$ns3::WifiNetDevice/Phy/PromiscSnifferRx";
+ Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&PcapSniffRxEvent, pcap));
}
void
diff --git a/src/helper/yans-wifi-helper.h b/src/helper/yans-wifi-helper.h
index 5d4cbe50b..1fdf52ea6 100644
--- a/src/helper/yans-wifi-helper.h
+++ b/src/helper/yans-wifi-helper.h
@@ -197,6 +197,30 @@ public:
std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+ /**
+ * PCAP formats
+ *
+ */
+ enum PcapFormat {
+ PCAP_FORMAT_80211 = 1,
+ PCAP_FORMAT_80211_PRISM = 2,
+ PCAP_FORMAT_80211_RADIOTAP = 3,
+ };
+
+ /**
+ * Set the format of PCAP traces to be used. This function has to be
+ * called before EnablePcap(), so that the header of the pcap file
+ * can be written correctly.
+ *
+ * In madwifi, this corresponds to setting
+ * /proc/sys/net/ath0/dev_type to a particular value. See
+ * http://madwifi-project.org/wiki/UserDocs/MonitorModeInterface for
+ * more information.
+ *
+ * @param format the PcapFormat to be used
+ */
+ void SetPcapFormat (enum PcapFormat format);
+
/**
* \param filename filename prefix to use for pcap files.
* \param nodeid the id of the node to generate pcap output for.
@@ -204,12 +228,15 @@ public:
*
* Generate a pcap file which contains the link-level data observed
* by the specified deviceid within the specified nodeid. The pcap
- * data is stored in the file prefix-nodeid-deviceid.pcap.
+ * data is stored in the file prefix-nodeid-deviceid.pcap. By
+ * default, no PHY layer information is provided. An optional header
+ * with PHY layer information, such as the radiotap or the prism
+ * header, can be used by invoking SetPcapFormat().
*
* This method should be invoked after the network topology has
* been fully constructed.
*/
- static void EnablePcap (std::string filename, uint32_t nodeid, uint32_t deviceid);
+ void EnablePcap (std::string filename, uint32_t nodeid, uint32_t deviceid);
/**
* \param filename filename prefix to use for pcap files.
@@ -218,7 +245,7 @@ public:
* Enable pcap output on each input device which is of the
* ns3::WifiNetDevice type.
*/
- static void EnablePcap (std::string filename, Ptr nd);
+ void EnablePcap (std::string filename, Ptr nd);
/**
* \param filename filename prefix to use for pcap files.
@@ -227,7 +254,7 @@ public:
* Enable pcap output on each input device which is of the
* ns3::WifiNetDevice type.
*/
- static void EnablePcap (std::string filename, std::string ndName);
+ void EnablePcap (std::string filename, std::string ndName);
/**
* \param filename filename prefix to use for pcap files.
@@ -236,7 +263,7 @@ public:
* Enable pcap output on each input device which is of the
* ns3::WifiNetDevice type.
*/
- static void EnablePcap (std::string filename, NetDeviceContainer d);
+ void EnablePcap (std::string filename, NetDeviceContainer d);
/**
* \param filename filename prefix to use for pcap files.
@@ -246,7 +273,7 @@ public:
* ns3::WifiNetDevice type and which is located in one of the
* input nodes.
*/
- static void EnablePcap (std::string filename, NodeContainer n);
+ void EnablePcap (std::string filename, NodeContainer n);
/**
* \param filename filename prefix to use for pcap files.
@@ -254,7 +281,7 @@ public:
* Enable pcap output on each device which is of the
* ns3::WifiNetDevice type
*/
- static void EnablePcapAll (std::string filename);
+ void EnablePcapAll (std::string filename);
/**
* \param os output stream
@@ -311,6 +338,7 @@ private:
ObjectFactory m_phy;
ObjectFactory m_errorRateModel;
Ptr m_channel;
+ enum PcapFormat m_pcapFormat;
};
} // namespace ns3