added support for radiotap and prism headers default tip
authorNicola Baldo <nbaldo@cttc.es>
Tue Jun 02 10:52:56 2009 +0200 (8 months ago)
changeset 4483c3c5e598802b
parent 4482 0a92e073bf7b
added support for radiotap and prism headers
examples/mixed-wireless.cc
examples/simple-wifi-frame-aggregation.cc
examples/third.cc
examples/wifi-wired-bridging.cc
src/common/pcap-writer.cc
src/common/pcap-writer.h
src/devices/wifi/wifi-phy.cc
src/devices/wifi/wifi-phy.h
src/devices/wifi/yans-wifi-phy.cc
src/devices/wifi/yans-wifi-phy.h
src/helper/yans-wifi-helper.cc
src/helper/yans-wifi-helper.h
     1.1 --- a/examples/mixed-wireless.cc	Sun May 31 22:11:52 2009 -0700
     1.2 +++ b/examples/mixed-wireless.cc	Tue Jun 02 10:52:56 2009 +0200
     1.3 @@ -392,9 +392,9 @@
     1.4        // Let's do a pcap trace on the application source and sink, ifIndex 0
     1.5        // Csma captures in non-promiscuous mode
     1.6        CsmaHelper::EnablePcap ("mixed-wireless", appSource->GetId (), 0, false);
     1.7 -      YansWifiPhyHelper::EnablePcap ("mixed-wireless", appSink->GetId (), 0);
     1.8 -      YansWifiPhyHelper::EnablePcap ("mixed-wireless", 9, 2);
     1.9 -      YansWifiPhyHelper::EnablePcap ("mixed-wireless", 9, 0);
    1.10 +      wifiPhy.EnablePcap ("mixed-wireless", appSink->GetId (), 0);
    1.11 +      wifiPhy.EnablePcap ("mixed-wireless", 9, 2);
    1.12 +      wifiPhy.EnablePcap ("mixed-wireless", 9, 0);
    1.13      }
    1.14  
    1.15    if (useCourseChangeCallback == true)
     2.1 --- a/examples/simple-wifi-frame-aggregation.cc	Sun May 31 22:11:52 2009 -0700
     2.2 +++ b/examples/simple-wifi-frame-aggregation.cc	Tue Jun 02 10:52:56 2009 +0200
     2.3 @@ -141,7 +141,7 @@
     2.4  
     2.5    Simulator::Stop (Seconds (10.0));
     2.6    
     2.7 -  YansWifiPhyHelper::EnablePcap ("test-802.11n", 
     2.8 +  phy.EnablePcap ("test-802.11n", 
     2.9      wifiNodes.Get (nWifi - 1)->GetId (), 0);
    2.10  
    2.11    Simulator::Run ();
     3.1 --- a/examples/third.cc	Sun May 31 22:11:52 2009 -0700
     3.2 +++ b/examples/third.cc	Tue Jun 02 10:52:56 2009 +0200
     3.3 @@ -164,7 +164,7 @@
     3.4    Simulator::Stop (Seconds (10.0));
     3.5  
     3.6    PointToPointHelper::EnablePcapAll ("third");
     3.7 -  YansWifiPhyHelper::EnablePcap ("third", apDevices.Get (0));
     3.8 +  phy.EnablePcap ("third", apDevices.Get (0));
     3.9    CsmaHelper::EnablePcap ("third", csmaDevices.Get (0), true);
    3.10  
    3.11    Simulator::Run ();
     4.1 --- a/examples/wifi-wired-bridging.cc	Sun May 31 22:11:52 2009 -0700
     4.2 +++ b/examples/wifi-wired-bridging.cc	Tue Jun 02 10:52:56 2009 +0200
     4.3 @@ -89,6 +89,10 @@
     4.4    backboneDevices = csma.Install (backboneNodes);
     4.5  
     4.6    double wifiX = 0.0;
     4.7 +
     4.8 +  YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
     4.9 +  wifiPhy.SetPcapFormat(YansWifiPhyHelper::PCAP_FORMAT_80211_RADIOTAP);
    4.10 +
    4.11    for (uint32_t i = 0; i < nWifis; ++i)
    4.12      {
    4.13        // calculate ssid for wifi subnetwork
    4.14 @@ -105,7 +109,6 @@
    4.15        BridgeHelper bridge;
    4.16        WifiHelper wifi = WifiHelper::Default ();
    4.17        NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
    4.18 -      YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
    4.19        YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
    4.20        wifiPhy.SetChannel (wifiChannel.Create ());
    4.21  
    4.22 @@ -182,8 +185,8 @@
    4.23    apps.Start (Seconds (0.5));
    4.24    apps.Stop (Seconds (3.0));
    4.25    
    4.26 -  YansWifiPhyHelper::EnablePcap ("wifi-wired-bridging", apDevices[0]);
    4.27 -  YansWifiPhyHelper::EnablePcap ("wifi-wired-bridging", apDevices[1]);
    4.28 +  wifiPhy.EnablePcap ("wifi-wired-bridging", apDevices[0]);
    4.29 +  wifiPhy.EnablePcap ("wifi-wired-bridging", apDevices[1]);
    4.30  
    4.31    std::ofstream os;
    4.32    os.open ("wifi-wired-bridging.mob");
     5.1 --- a/src/common/pcap-writer.cc	Sun May 31 22:11:52 2009 -0700
     5.2 +++ b/src/common/pcap-writer.cc	Tue Jun 02 10:52:56 2009 +0200
     5.3 @@ -41,6 +41,8 @@
     5.4    PCAP_PPP      = 9,
     5.5    PCAP_RAW_IP   = 101,
     5.6    PCAP_80211    = 105,
     5.7 +  PCAP_80211_PRISM = 119,
     5.8 +  PCAP_80211_RADIOTAP  = 127,
     5.9  };
    5.10  
    5.11  PcapWriter::PcapWriter ()
    5.12 @@ -115,6 +117,20 @@
    5.13    WriteHeader (PCAP_80211);
    5.14  }
    5.15  
    5.16 +void
    5.17 +PcapWriter::WriteWifiRadiotapHeader (void)
    5.18 +{
    5.19 +  NS_LOG_FUNCTION_NOARGS ();
    5.20 +  WriteHeader (PCAP_80211_RADIOTAP);
    5.21 +}
    5.22 +
    5.23 +void
    5.24 +PcapWriter::WriteWifiPrismHeader (void)
    5.25 +{
    5.26 +  NS_LOG_FUNCTION_NOARGS ();
    5.27 +  WriteHeader (PCAP_80211_PRISM);
    5.28 +}
    5.29 +
    5.30  void 
    5.31  PcapWriter::WritePppHeader (void)
    5.32  {
    5.33 @@ -133,6 +149,7 @@
    5.34    Write32 (0);
    5.35    Write32 (0xffff);
    5.36    Write32 (network);
    5.37 +  m_pcapMode = network;
    5.38  }
    5.39  
    5.40  void 
    5.41 @@ -151,12 +168,296 @@
    5.42      }
    5.43  }
    5.44  
    5.45 +
    5.46 +void PcapWriter::WriteWifiMonitorPacket(Ptr<const Packet> packet, uint16_t channelFreqMhz, uint32_t rate, bool isShortPreamble, bool isTx, double signalDbm, double noiseDbm)
    5.47 +{  
    5.48 +  NS_LOG_FUNCTION (this << packet->GetSize() << channelFreqMhz << rate << isShortPreamble << isTx << signalDbm << noiseDbm);
    5.49 +
    5.50 +  if (m_writer == 0) 
    5.51 +    {
    5.52 +      return;
    5.53 +    }
    5.54 +
    5.55 +  if (m_pcapMode == PCAP_80211)
    5.56 +    {
    5.57 +      WritePacket (packet);    
    5.58 +      return;
    5.59 +    }
    5.60 +  
    5.61 +  /* the following is common between PRISM and RADIOTAP */
    5.62 +  
    5.63 +  uint64_t current = Simulator::Now ().GetMicroSeconds ();
    5.64 +  uint64_t s = current / 1000000;
    5.65 +  uint64_t us = current % 1000000;
    5.66 +  Write32 (s & 0xffffffff);
    5.67 +  Write32 (us & 0xffffffff);
    5.68 +    
    5.69 +
    5.70 +  // MAC timestamp. Actually according to radiotap specifications
    5.71 +  // (http://www.radiotap.org/defined-fields/TSFT) this should be
    5.72 +  // the time "when the first bit of the MPDU arrived at the
    5.73 +  // MAC". This is not exactly what we're doing here, but to handle
    5.74 +  // this properly we would need to first of all investigate how
    5.75 +  // real devices (e.g. madwifi) handle this case, especially for TX
    5.76 +  // packets (radiotap specs says TSFT is not used for TX packets,
    5.77 +  // but madwifi actually uses it).
    5.78 +  uint64_t tsft = current;      
    5.79 +    
    5.80 +  if (m_pcapMode == PCAP_80211_PRISM)
    5.81 +    {
    5.82 +      
    5.83 +#define PRISM_MSG_CODE		 0x00000044
    5.84 +#define PRISM_MSG_LENGTH         144
    5.85 +#define PRISM_DID_HOSTTIME	 0x00010044
    5.86 +#define PRISM_DID_MACTIME	 0x00020044
    5.87 +#define PRISM_DID_CHANNEL	 0x00030044
    5.88 +#define PRISM_DID_RSSI	         0x00040044
    5.89 +#define PRISM_DID_SQ		 0x00050044
    5.90 +#define PRISM_DID_SIGNAL	 0x00060044
    5.91 +#define PRISM_DID_NOISE	         0x00070044
    5.92 +#define PRISM_DID_RATE	         0x00080044
    5.93 +#define PRISM_DID_ISTX	         0x00090044
    5.94 +#define PRISM_DID_FRMLEN	 0x000A0044
    5.95 +
    5.96 +#define PRISM_STATUS_PRESENT    0
    5.97 +#define PRISM_STATUS_ABSENT     1
    5.98 +#define PRISM_ITEM_LENGTH       4
    5.99 +
   5.100 +
   5.101 +
   5.102 +      uint32_t size = packet->GetSize () + PRISM_MSG_LENGTH;
   5.103 +      Write32 (size); // total packet size
   5.104 +      Write32 (size); // captured size
   5.105 +
   5.106 +      Write32(PRISM_MSG_CODE);
   5.107 +      Write32(PRISM_MSG_LENGTH);
   5.108 +      WriteData((const uint8_t *)"unknown wifi device!!!!!!!!", 16);
   5.109 +    
   5.110 +      Write32(PRISM_DID_HOSTTIME);
   5.111 +      Write16(PRISM_STATUS_PRESENT);
   5.112 +      Write16(PRISM_ITEM_LENGTH); 
   5.113 +      // madwifi reports hosttime in jiffies. 
   5.114 +      // We calculate jiffies assuming HZ = 10
   5.115 +      Write32((uint32_t) (Now ().GetMilliSeconds () / 10 ) ); 
   5.116 +
   5.117 +      Write32(PRISM_DID_MACTIME);
   5.118 +      Write16(PRISM_STATUS_PRESENT);
   5.119 +      Write16(PRISM_ITEM_LENGTH); 
   5.120 +      // This looses precision, which is a well-known issue of the prism
   5.121 +      // header format.
   5.122 +      Write32((uint32_t) tsft);
   5.123 +
   5.124 +      Write32(PRISM_DID_CHANNEL);
   5.125 +      Write16(PRISM_STATUS_PRESENT);
   5.126 +      Write16(PRISM_ITEM_LENGTH); 
   5.127 +      // convert from frequency to channel number. This conversion is
   5.128 +      // correct only for IEEE 802.11b/g channels 1-13.
   5.129 +      Write32((channelFreqMhz - 2407) / 5);
   5.130 +
   5.131 +      Write32(PRISM_DID_RSSI);
   5.132 +      Write16(PRISM_STATUS_PRESENT);
   5.133 +      Write16(PRISM_ITEM_LENGTH); 
   5.134 +      // madwifi here reports a value which is said to be "the value in
   5.135 +      // dBm above noise". Apart from the fact that this is incorrect
   5.136 +      // (if it is relative to a value in dBm, then it must be in dB,
   5.137 +      // not in dBm again), this means that in fact it is not a RSSI
   5.138 +      // (which stands for Received Signal Strength Indicator) but it is
   5.139 +      // rather a Signal to Noise Ratio (SNR), of course in dB.
   5.140 +      // Anyway, in the end we calculate the value exactly as madwifi does.
   5.141 +      Write32(round(signalDbm - noiseDbm));
   5.142 +
   5.143 +      // SQ field not used. I would expect a PRISM_STATUS_ABSENT to be
   5.144 +      // needed here, but if you look at the prism header that madwifi
   5.145 +      // produces you'll just see that the whole field structure is
   5.146 +      // zeroed. 
   5.147 +      Write32(0);
   5.148 +      Write16(0);
   5.149 +      Write16(0); 
   5.150 +      Write32(0);
   5.151 +
   5.152 +      Write32(PRISM_DID_SIGNAL);
   5.153 +      Write16(PRISM_STATUS_PRESENT);
   5.154 +      Write16(PRISM_ITEM_LENGTH); 
   5.155 +      Write32(round(signalDbm));
   5.156 +
   5.157 +      Write32(PRISM_DID_NOISE);
   5.158 +      Write16(PRISM_STATUS_PRESENT);
   5.159 +      Write16(PRISM_ITEM_LENGTH); 
   5.160 +      Write32(round(noiseDbm));
   5.161 +            
   5.162 +      Write32(PRISM_DID_RATE);    
   5.163 +      Write16(PRISM_STATUS_PRESENT);
   5.164 +      Write16(PRISM_ITEM_LENGTH); 
   5.165 +      Write32(rate);
   5.166 + 
   5.167 +      Write32(PRISM_DID_ISTX);
   5.168 +      Write16(PRISM_STATUS_PRESENT);
   5.169 +      Write16(PRISM_ITEM_LENGTH); 
   5.170 +      Write32(isTx ? 1 : 0);
   5.171 +
   5.172 +      Write32(PRISM_DID_FRMLEN);
   5.173 +      Write16(PRISM_STATUS_ABSENT);
   5.174 +      Write16(PRISM_ITEM_LENGTH); 
   5.175 +      Write32(packet->GetSize ());    
   5.176 +      
   5.177 +    
   5.178 +
   5.179 +    } // PCAP_80211_PRISM
   5.180 +
   5.181 +  else if (m_pcapMode == PCAP_80211_RADIOTAP)
   5.182 +    {      
   5.183 +      NS_LOG_LOGIC("writing radiotap packet");
   5.184 +      
   5.185 +#define	RADIOTAP_TSFT               0x00000001
   5.186 +#define	RADIOTAP_FLAGS              0x00000002
   5.187 +#define	RADIOTAP_RATE               0x00000004
   5.188 +#define RADIOTAP_CHANNEL            0x00000008
   5.189 +#define	RADIOTAP_FHSS               0x00000010
   5.190 +#define RADIOTAP_DBM_ANTSIGNAL      0x00000020
   5.191 +#define RADIOTAP_DBM_ANTNOISE       0x00000040
   5.192 +#define RADIOTAP_LOCK_QUALITY       0x00000080
   5.193 +#define RADIOTAP_TX_ATTENUATION     0x00000100    
   5.194 +#define RADIOTAP_DB_TX_ATTENUATION  0x00000200
   5.195 +#define RADIOTAP_DBM_TX_POWER       0x00000200
   5.196 +#define RADIOTAP_ANTENNA            0x00000400
   5.197 +#define RADIOTAP_DB_ANTSIGNAL       0x00000800
   5.198 +#define RADIOTAP_DB_ANTNOISE        0x00001000
   5.199 +#define RADIOTAP_EXT                0x10000000
   5.200 +
   5.201 +#define	RADIOTAP_FLAG_NONE	   0x00	
   5.202 +#define	RADIOTAP_FLAG_CFP	   0x01	
   5.203 +#define	RADIOTAP_FLAG_SHORTPRE	   0x02	
   5.204 +#define	RADIOTAP_FLAG_WEP	   0x04	
   5.205 +#define	RADIOTAP_FLAG_FRAG	   0x08	
   5.206 +#define	RADIOTAP_FLAG_FCS	   0x10	
   5.207 +#define	RADIOTAP_FLAG_DATAPAD	   0x20	
   5.208 +#define	RADIOTAP_FLAG_BADFCS	   0x40	
   5.209 +
   5.210 +#define	RADIOTAP_CHANNEL_TURBO	  0x0010
   5.211 +#define	RADIOTAP_CHANNEL_CCK	  0x0020
   5.212 +#define	RADIOTAP_CHANNEL_OFDM	  0x0040
   5.213 +#define	RADIOTAP_CHANNEL_2GHZ	  0x0080
   5.214 +#define	RADIOTAP_CHANNEL_5GHZ	  0x0100
   5.215 +#define	RADIOTAP_CHANNEL_PASSIVE  0x0200
   5.216 +#define	RADIOTAP_CHANNEL_DYN	  0x0400
   5.217 +#define	RADIOTAP_CHANNEL_GFSK	  0x0800
   5.218 +
   5.219 +#define RADIOTAP_RX_PRESENT (RADIOTAP_TSFT | RADIOTAP_FLAGS | RADIOTAP_RATE | RADIOTAP_CHANNEL | RADIOTAP_DBM_ANTSIGNAL | RADIOTAP_DBM_ANTNOISE)
   5.220 +#define RADIOTAP_RX_LENGTH (8+8+1+1+2+2+1+1)
   5.221 +
   5.222 +#define RADIOTAP_TX_PRESENT (RADIOTAP_TSFT | RADIOTAP_FLAGS  | RADIOTAP_RATE | RADIOTAP_CHANNEL)
   5.223 +#define RADIOTAP_TX_LENGTH (8+8+1+1+2+2)
   5.224 +
   5.225 +      uint32_t size;
   5.226 +      if (isTx)
   5.227 +        {
   5.228 +          size = packet->GetSize () + RADIOTAP_TX_LENGTH;
   5.229 +        }
   5.230 +      else
   5.231 +        {
   5.232 +          size = packet->GetSize () + RADIOTAP_RX_LENGTH;
   5.233 +        }
   5.234 +      Write32 (size); // total packet size
   5.235 +      Write32 (size); // captured size
   5.236 +
   5.237 +      Write8(0); // radiotap version
   5.238 +      Write8(0); // padding
   5.239 +
   5.240 +      if (isTx)
   5.241 +        {
   5.242 +          Write16(RADIOTAP_TX_LENGTH); 
   5.243 +          Write32(RADIOTAP_TX_PRESENT); 
   5.244 +        }
   5.245 +      else
   5.246 +        {
   5.247 +          Write16(RADIOTAP_RX_LENGTH); 
   5.248 +          Write32(RADIOTAP_RX_PRESENT); 
   5.249 +        }
   5.250 +
   5.251 +      Write64(tsft); 
   5.252 +      
   5.253 +      uint8_t flags = RADIOTAP_FLAG_NONE;
   5.254 +      if (isShortPreamble)
   5.255 +        {
   5.256 +          flags |= RADIOTAP_FLAG_SHORTPRE; 
   5.257 +        }
   5.258 +      Write8(flags);
   5.259 +      
   5.260 +
   5.261 +      Write8(rate); 
   5.262 +
   5.263 +      Write16((uint16_t) channelFreqMhz); 
   5.264 +
   5.265 +      // we might want to make this setting depend on the WifiMode and
   5.266 +      // on the ChannelFrequency at some time in the future. But for now
   5.267 +      // I think a fixed setting is more than enough for most purposes.
   5.268 +      Write16(RADIOTAP_CHANNEL_OFDM | RADIOTAP_CHANNEL_2GHZ); 
   5.269 +    
   5.270 +      if (!isTx)
   5.271 +        {
   5.272 +          
   5.273 +          Write8 (RoundToInt8 (signalDbm)); 
   5.274 +          Write8 (RoundToInt8 (noiseDbm)); 
   5.275 +        }
   5.276 +
   5.277 +    } // PCAP_80211_RADIOTAP
   5.278 +
   5.279 +    
   5.280 +  else
   5.281 +    {
   5.282 +      NS_LOG_ERROR("unknown PCAP mode");      
   5.283 +      return;
   5.284 +    }    
   5.285 +
   5.286 +  // finally, write rest of packet
   5.287 +  WriteData (packet->PeekData (), packet->GetSize ());
   5.288 +}
   5.289 +    
   5.290 +  
   5.291 +
   5.292 +
   5.293 +int8_t 
   5.294 +PcapWriter::RoundToInt8 (double value)
   5.295 +{
   5.296 +  if (value < -128)
   5.297 +    {
   5.298 +      return -128;
   5.299 +    }
   5.300 +  if (value > 127)
   5.301 +    {
   5.302 +      return 127;
   5.303 +    }
   5.304 +  return ((int8_t) round(value));
   5.305 +}
   5.306 +
   5.307 +
   5.308 +
   5.309 +
   5.310 +
   5.311 +
   5.312  void
   5.313  PcapWriter::WriteData (uint8_t const*buffer, uint32_t size)
   5.314  {
   5.315 +  NS_LOG_FUNCTION(this << size);
   5.316    m_writer->write ((char const *)buffer, size);
   5.317  }
   5.318  
   5.319 +
   5.320 +void
   5.321 +PcapWriter::Write64 (uint64_t data)
   5.322 +{
   5.323 +  uint8_t buffer[8];
   5.324 +  buffer[0] = (data >> 0) & 0xff;
   5.325 +  buffer[1] = (data >> 8) & 0xff;
   5.326 +  buffer[2] = (data >> 16) & 0xff;
   5.327 +  buffer[3] = (data >> 24) & 0xff;
   5.328 +  buffer[4] = (data >> 32) & 0xff;
   5.329 +  buffer[5] = (data >> 40) & 0xff;
   5.330 +  buffer[6] = (data >> 48) & 0xff;
   5.331 +  buffer[7] = (data >> 56) & 0xff;
   5.332 +  WriteData (buffer, 8);
   5.333 +}
   5.334 +
   5.335  void
   5.336  PcapWriter::Write32 (uint32_t data)
   5.337  {
   5.338 @@ -177,4 +478,12 @@
   5.339    WriteData (buffer, 2);
   5.340  }
   5.341  
   5.342 +void
   5.343 +PcapWriter::Write8 (uint8_t data)
   5.344 +{
   5.345 +  WriteData (&data, 1);
   5.346 +}
   5.347 +
   5.348 +
   5.349 +
   5.350  } // namespace ns3
     6.1 --- a/src/common/pcap-writer.h	Sun May 31 22:11:52 2009 -0700
     6.2 +++ b/src/common/pcap-writer.h	Tue Jun 02 10:52:56 2009 +0200
     6.3 @@ -76,6 +76,24 @@
     6.4  
     6.5    /**
     6.6     * Write a pcap header in the output file which specifies
     6.7 +   * that the content of the file will be 802.11 Packets preceded by a
     6.8 +   * radiotap header providing PHY layer info. This method should be
     6.9 +   * invoked before ns3::PcapWriter::WritePacket and after
    6.10 +   * ns3::PcapWriter::Open. 
    6.11 +   */
    6.12 +  void WriteWifiRadiotapHeader (void);
    6.13 +
    6.14 +  /**
    6.15 +   * Write a pcap header in the output file which specifies
    6.16 +   * that the content of the file will be 802.11 Packets preceded by a
    6.17 +   * prism header providing PHY layer info. This method should be
    6.18 +   * invoked before ns3::PcapWriter::WritePacket and after
    6.19 +   * ns3::PcapWriter::Open. 
    6.20 +   */
    6.21 +  void WriteWifiPrismHeader (void);
    6.22 +
    6.23 +  /**
    6.24 +   * Write a pcap header in the output file which specifies
    6.25     * that the content of the file will be ppp Packets. This 
    6.26     * method should be invoked before ns3::PcapWriter::WritePacket 
    6.27     * and after ns3::PcapWriter::Open.
    6.28 @@ -87,12 +105,40 @@
    6.29     */
    6.30    void WritePacket (Ptr<const Packet> packet);
    6.31  
    6.32 +  /** 
    6.33 +   * Write a Packet, possibly adding wifi PHY layer information to it
    6.34 +   *
    6.35 +   * @param packet the packet being received
    6.36 +   * @param channelFreqMhz the frequency in MHz at which the packet is
    6.37 +   * received. Note that in real devices this is normally the
    6.38 +   * frequency to which  the receiver is tuned, and this can be
    6.39 +   * different than the frequency at which the packet was originally
    6.40 +   * transmitted. This is because it is possible to have the receiver
    6.41 +   * tuned on a given channel and still to be able to receive packets
    6.42 +   * on a nearby channel.
    6.43 +   * @param rate the PHY data rate in units of 500kbps (i.e., the same
    6.44 +   * units used both for the radiotap and for the prism header) 
    6.45 +   * @param isPreambleShort true if short preamble is used, false otherwise
    6.46 +   * @param isTx true if packet is being transmitted, false when
    6.47 +   * packet is being received
    6.48 +   * @param signalDbm signal power in dBm
    6.49 +   * @param noiseDbm  noise power in dBm
    6.50 +   */
    6.51 +  void WriteWifiMonitorPacket(Ptr<const Packet> packet, uint16_t channelFreqMhz, uint32_t rate, bool isShortPreamble, bool isTx, double signalDbm, double noiseDbm);
    6.52 +
    6.53 +
    6.54 +
    6.55 +
    6.56  private:
    6.57    void WriteData (uint8_t const*buffer, uint32_t size);
    6.58 +  void Write64 (uint64_t data);
    6.59    void Write32 (uint32_t data);
    6.60    void Write16 (uint16_t data);
    6.61 +  void Write8 (uint8_t data);
    6.62    void WriteHeader (uint32_t network);
    6.63 +  int8_t RoundToInt8 (double value);
    6.64    std::ofstream *m_writer;
    6.65 +  uint32_t m_pcapMode;
    6.66  };
    6.67  
    6.68  } // namespace ns3
     7.1 --- a/src/devices/wifi/wifi-phy.cc	Sun May 31 22:11:52 2009 -0700
     7.2 +++ b/src/devices/wifi/wifi-phy.cc	Tue Jun 02 10:52:56 2009 +0200
     7.3 @@ -73,9 +73,12 @@
     7.4      .AddTraceSource ("PhyRxDrop", 
     7.5                       "Trace source indicating a packet has been dropped by the device during reception",
     7.6                       MakeTraceSourceAccessor (&WifiPhy::m_phyRxDropTrace))
     7.7 -    .AddTraceSource ("PromiscSniffer", 
     7.8 -                     "Trace source simulating a promiscuous packet sniffer attached to the device",
     7.9 -                     MakeTraceSourceAccessor (&WifiPhy::m_phyPromiscSnifferTrace))
    7.10 +    .AddTraceSource ("PromiscSnifferRx", 
    7.11 +                     "Trace source simulating a wifi device in monitor mode sniffing all received frames",
    7.12 +                     MakeTraceSourceAccessor (&WifiPhy::m_phyPromiscSniffRxTrace))
    7.13 +    .AddTraceSource ("PromiscSnifferTx", 
    7.14 +                     "Trace source simulating the capability of a wifi device in monitor mode to sniff all frames being transmitted",
    7.15 +                     MakeTraceSourceAccessor (&WifiPhy::m_phyPromiscSniffTxTrace))
    7.16      ;
    7.17    return tid;
    7.18  }
    7.19 @@ -194,9 +197,15 @@
    7.20  }
    7.21  
    7.22  void 
    7.23 -WifiPhy::NotifyPromiscSniff (Ptr<const Packet> packet) 
    7.24 +WifiPhy::NotifyPromiscSniffRx (Ptr<const Packet> packet, uint16_t channelFreqMhz, uint32_t rate, bool isShortPreamble, double signalDbm, double noiseDbm)
    7.25  {
    7.26 -  m_phyPromiscSnifferTrace (packet);
    7.27 +  m_phyPromiscSniffRxTrace (packet, channelFreqMhz, rate, isShortPreamble, signalDbm, noiseDbm);
    7.28 +}
    7.29 +
    7.30 +void 
    7.31 +WifiPhy::NotifyPromiscSniffTx (Ptr<const Packet> packet, uint16_t channelFreqMhz, uint32_t rate, bool isShortPreamble)
    7.32 +{
    7.33 +  m_phyPromiscSniffTxTrace (packet, channelFreqMhz, rate, isShortPreamble);
    7.34  }
    7.35  
    7.36  WifiMode 
     8.1 --- a/src/devices/wifi/wifi-phy.h	Sun May 31 22:11:52 2009 -0700
     8.2 +++ b/src/devices/wifi/wifi-phy.h	Tue Jun 02 10:52:56 2009 +0200
     8.3 @@ -294,11 +294,46 @@
     8.4     */
     8.5    void NotifyRxDrop (Ptr<const Packet> packet);
     8.6  
     8.7 -  /**
     8.8 -   * Public method used to fire a PromiscSniffer trace.  Implemented for encapsulation 
     8.9 +  /** 
    8.10 +   * 
    8.11 +   * Public method used to fire a PromiscSniffer trace for a wifi packet being received.  Implemented for encapsulation 
    8.12     * purposes.
    8.13 +   * 
    8.14 +   * @param packet the packet being received
    8.15 +   * @param channelFreqMhz the frequency in MHz at which the packet is
    8.16 +   * received. Note that in real devices this is normally the
    8.17 +   * frequency to which  the receiver is tuned, and this can be
    8.18 +   * different than the frequency at which the packet was originally
    8.19 +   * transmitted. This is because it is possible to have the receiver
    8.20 +   * tuned on a given channel and still to be able to receive packets
    8.21 +   * on a nearby channel.
    8.22 +   * @param rate the PHY data rate in units of 500kbps (i.e., the same
    8.23 +   * units used both for the radiotap and for the prism header) 
    8.24 +   * @param isPreambleShort true if short preamble is used, false otherwise
    8.25 +   * @param signalDbm signal power in dBm
    8.26 +   * @param noiseDbm  noise power in dBm
    8.27     */
    8.28 -  void NotifyPromiscSniff (Ptr<const Packet> packet);
    8.29 +  void NotifyPromiscSniffRx (Ptr<const Packet> packet, uint16_t channelFreqMhz, uint32_t rate, bool isShortPreamble, double signalDbm, double noiseDbm);
    8.30 +
    8.31 +  /** 
    8.32 +   * 
    8.33 +   * Public method used to fire a PromiscSniffer trace for a wifi packet being transmitted.  Implemented for encapsulation 
    8.34 +   * purposes.
    8.35 +   * 
    8.36 +   * @param packet the packet being received
    8.37 +   * @param channelFreqMhz the frequency in MHz at which the packet is
    8.38 +   * received. Note that in real devices this is normally the
    8.39 +   * frequency to which  the receiver is tuned, and this can be
    8.40 +   * different than the frequency at which the packet was originally
    8.41 +   * transmitted. This is because it is possible to have the receiver
    8.42 +   * tuned on a given channel and still to be able to receive packets
    8.43 +   * on a nearby channel.
    8.44 +   * @param rate the PHY data rate in units of 500kbps (i.e., the same
    8.45 +   * units used both for the radiotap and for the prism header) 
    8.46 +   * @param isPreambleShort true if short preamble is used, false otherwise
    8.47 +   */
    8.48 +  void NotifyPromiscSniffTx (Ptr<const Packet> packet, uint16_t channelFreqMhz, uint32_t rate, bool isShortPreamble);
    8.49 +  
    8.50  
    8.51  private:
    8.52    /**
    8.53 @@ -349,24 +384,29 @@
    8.54    TracedCallback<Ptr<const Packet> > m_phyRxDropTrace;
    8.55  
    8.56    /**
    8.57 -   * A trace source that emulates a promiscuous mode protocol sniffer connected
    8.58 -   * to the device.  This trace source fire on packets destined for any host
    8.59 -   * just like your average everyday packet sniffer.
    8.60 -   *
    8.61 -   * On the transmit size, this trace hook will fire after a packet is dequeued
    8.62 -   * from the device queue for transmission.  In Linux, for example, this would
    8.63 -   * correspond to the point just before a device hard_start_xmit where 
    8.64 -   * dev_queue_xmit_nit is called to dispatch the packet to the PF_PACKET 
    8.65 -   * ETH_P_ALL handlers.
    8.66 -   *
    8.67 -   * On the receive side, this trace hook will fire when a packet is received,
    8.68 -   * just before the receive callback is executed.  In Linux, for example, 
    8.69 -   * this would correspond to the point at which the packet is dispatched to 
    8.70 -   * packet sniffers in netif_receive_skb.
    8.71 +   * A trace source that emulates a wifi device in monitor mode
    8.72 +   * sniffing a packet being received. 
    8.73 +   * 
    8.74 +   * As a reference with the real world, firing this trace
    8.75 +   * corresponds in the madwifi driver to calling the function
    8.76 +   * ieee80211_input_monitor()
    8.77     *
    8.78     * \see class CallBackTraceSource
    8.79     */
    8.80 -  TracedCallback<Ptr<const Packet> > m_phyPromiscSnifferTrace;
    8.81 +  TracedCallback<Ptr<const Packet>, uint16_t, uint32_t, bool, double, double> m_phyPromiscSniffRxTrace;
    8.82 +
    8.83 +  /**
    8.84 +   * A trace source that emulates a wifi device in monitor mode
    8.85 +   * sniffing a packet being transmitted. 
    8.86 +   * 
    8.87 +   * As a reference with the real world, firing this trace
    8.88 +   * corresponds in the madwifi driver to calling the function
    8.89 +   * ieee80211_input_monitor()
    8.90 +   *
    8.91 +   * \see class CallBackTraceSource
    8.92 +   */
    8.93 +  TracedCallback<Ptr<const Packet>, uint16_t, uint32_t, bool> m_phyPromiscSniffTxTrace;
    8.94 +
    8.95  };
    8.96  
    8.97  } // namespace ns3
     9.1 --- a/src/devices/wifi/yans-wifi-phy.cc	Sun May 31 22:11:52 2009 -0700
     9.2 +++ b/src/devices/wifi/yans-wifi-phy.cc	Tue Jun 02 10:52:56 2009 +0200
     9.3 @@ -121,8 +121,10 @@
     9.4  }
     9.5  
     9.6  YansWifiPhy::YansWifiPhy ()
     9.7 - : m_endSyncEvent (),
     9.8 -   m_random (0.0, 1.0)
     9.9 +  :  m_channelFreqMhz(2437),
    9.10 +     m_endSyncEvent (),
    9.11 +     m_random (0.0, 1.0)
    9.12 +
    9.13  {
    9.14    NS_LOG_FUNCTION (this);
    9.15    m_state = CreateObject<WifiPhyStateHelper> ();
    9.16 @@ -408,7 +410,9 @@
    9.17        m_endSyncEvent.Cancel ();
    9.18      }
    9.19    NotifyTxBegin (packet);
    9.20 -  NotifyPromiscSniff (packet);
    9.21 +  uint32_t dataRate500KbpsUnits = txMode.GetDataRate () / 500000;   
    9.22 +  bool isShortPreamble = (WIFI_PREAMBLE_SHORT == preamble);
    9.23 +  NotifyPromiscSniffTx (packet, m_channelFreqMhz, dataRate500KbpsUnits, isShortPreamble);
    9.24    m_state->SwitchToTx (txDuration, packet, txMode, preamble, txPower);
    9.25    m_channel->Send (this, packet, GetPowerDbm (txPower) + m_txGainDb, txMode, preamble);
    9.26  }
    9.27 @@ -577,11 +581,14 @@
    9.28  
    9.29    NS_LOG_DEBUG ("mode="<<(event->GetPayloadMode ().GetDataRate ())<<
    9.30                  ", snr="<<snrPer.snr<<", per="<<snrPer.per<<", size="<<packet->GetSize ());
    9.31 -  
    9.32    if (m_random.GetValue () > snrPer.per) 
    9.33      {
    9.34 -      NotifyRxEnd (packet);
    9.35 -      NotifyPromiscSniff (packet);
    9.36 +      NotifyRxEnd (packet); 
    9.37 +      uint32_t dataRate500KbpsUnits = event->GetPayloadMode ().GetDataRate () / 500000;   
    9.38 +      bool isShortPreamble = (WIFI_PREAMBLE_SHORT == event->GetPreambleType ());  
    9.39 +      double signalDbm = RatioToDb (event->GetRxPowerW ()) + 30;
    9.40 +      double noiseDbm = RatioToDb(event->GetRxPowerW() / snrPer.snr) - GetRxNoiseFigure() + 30 ;
    9.41 +      NotifyPromiscSniffRx (packet, m_channelFreqMhz, dataRate500KbpsUnits, isShortPreamble, signalDbm, noiseDbm);
    9.42        m_state->SwitchFromSyncEndOk (packet, snrPer.snr, event->GetPayloadMode (), event->GetPreambleType ());
    9.43      } 
    9.44    else 
    9.45 @@ -591,5 +598,4 @@
    9.46        m_state->SwitchFromSyncEndError (packet, snrPer.snr);
    9.47      }
    9.48  }
    9.49 -
    9.50  } // namespace ns3
    10.1 --- a/src/devices/wifi/yans-wifi-phy.h	Sun May 31 22:11:52 2009 -0700
    10.2 +++ b/src/devices/wifi/yans-wifi-phy.h	Tue Jun 02 10:52:56 2009 +0200
    10.3 @@ -142,6 +142,7 @@
    10.4    double   m_txPowerBaseDbm;
    10.5    double   m_txPowerEndDbm;
    10.6    uint32_t m_nTxPower;
    10.7 +  uint16_t m_channelFreqMhz;
    10.8  
    10.9    Ptr<YansWifiChannel> m_channel;
   10.10    Ptr<Object> m_device;
    11.1 --- a/src/helper/yans-wifi-helper.cc	Sun May 31 22:11:52 2009 -0700
    11.2 +++ b/src/helper/yans-wifi-helper.cc	Tue Jun 02 10:52:56 2009 +0200
    11.3 @@ -31,11 +31,19 @@
    11.4  
    11.5  namespace ns3 {
    11.6  
    11.7 -static void PcapSnifferEvent (Ptr<PcapWriter> writer, Ptr<const Packet> packet)
    11.8 +static void PcapSniffTxEvent (Ptr<PcapWriter> writer, Ptr<const Packet> packet, uint16_t channelFreqMhz,  uint32_t rate, bool isShortPreamble)
    11.9  {
   11.10 -  writer->WritePacket (packet);
   11.11 +  const double unusedValue = 0;
   11.12 +  writer->WriteWifiMonitorPacket(packet, channelFreqMhz, rate, isShortPreamble, true, unusedValue, unusedValue); 
   11.13  }
   11.14  
   11.15 +
   11.16 +static void PcapSniffRxEvent (Ptr<PcapWriter> writer, Ptr<const Packet> packet, uint16_t channelFreqMhz,  uint32_t rate, bool isShortPreamble, double signalDbm, double noiseDbm)
   11.17 +{
   11.18 +  writer->WriteWifiMonitorPacket(packet, channelFreqMhz, rate, isShortPreamble, false, signalDbm, noiseDbm); 
   11.19 +}
   11.20 +
   11.21 +
   11.22  static void AsciiPhyTxEvent (std::ostream *os, std::string context, 
   11.23                               Ptr<const Packet> packet,
   11.24                               WifiMode mode, WifiPreamble preamble, 
   11.25 @@ -137,7 +145,9 @@
   11.26  
   11.27  
   11.28  YansWifiPhyHelper::YansWifiPhyHelper ()
   11.29 -  : m_channel (0)
   11.30 +  : m_channel (0),
   11.31 +    m_pcapFormat(PCAP_FORMAT_80211)
   11.32 +    
   11.33  {
   11.34    m_phy.SetTypeId ("ns3::YansWifiPhy");
   11.35  }
   11.36 @@ -202,6 +212,14 @@
   11.37    return phy;
   11.38  }
   11.39  
   11.40 +
   11.41 +void 
   11.42 +YansWifiPhyHelper::SetPcapFormat (enum PcapFormat format)
   11.43 +{
   11.44 +  m_pcapFormat = format;
   11.45 +}
   11.46 +
   11.47 +
   11.48  void 
   11.49  YansWifiPhyHelper::EnablePcap (std::string filename, uint32_t nodeid, uint32_t deviceid)
   11.50  {
   11.51 @@ -218,11 +236,28 @@
   11.52    // with the locally-defined WifiPhyHelper::Create method.
   11.53    Ptr<PcapWriter> pcap = ::ns3::Create<PcapWriter> ();
   11.54    pcap->Open (oss.str ());
   11.55 -  pcap->WriteWifiHeader ();
   11.56 +
   11.57 +  switch (m_pcapFormat) {
   11.58 +  case PCAP_FORMAT_80211:
   11.59 +    pcap->WriteWifiHeader ();  
   11.60 +    break;
   11.61 +  case PCAP_FORMAT_80211_RADIOTAP:
   11.62 +    pcap->WriteWifiRadiotapHeader ();  
   11.63 +    break;
   11.64 +  case PCAP_FORMAT_80211_PRISM:
   11.65 +    pcap->WriteWifiPrismHeader ();  
   11.66 +    break;
   11.67 +  }
   11.68 +  
   11.69    oss.str ("");
   11.70    oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid;
   11.71 -  oss << "/$ns3::WifiNetDevice/Phy/PromiscSniffer";
   11.72 -  Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&PcapSnifferEvent, pcap));
   11.73 +  oss << "/$ns3::WifiNetDevice/Phy/PromiscSnifferTx";
   11.74 +  Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&PcapSniffTxEvent, pcap));
   11.75 +
   11.76 +  oss.str ("");
   11.77 +  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid;
   11.78 +  oss << "/$ns3::WifiNetDevice/Phy/PromiscSnifferRx";
   11.79 +  Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&PcapSniffRxEvent, pcap));  
   11.80  }
   11.81  
   11.82  void 
    12.1 --- a/src/helper/yans-wifi-helper.h	Sun May 31 22:11:52 2009 -0700
    12.2 +++ b/src/helper/yans-wifi-helper.h	Tue Jun 02 10:52:56 2009 +0200
    12.3 @@ -198,18 +198,45 @@
    12.4                            std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
    12.5  
    12.6    /**
    12.7 +   * PCAP formats 
    12.8 +   * 
    12.9 +   */
   12.10 +  enum PcapFormat {   
   12.11 +    PCAP_FORMAT_80211          = 1,
   12.12 +    PCAP_FORMAT_80211_PRISM    = 2,
   12.13 +    PCAP_FORMAT_80211_RADIOTAP = 3,
   12.14 +  };
   12.15 +  
   12.16 +  /** 
   12.17 +   * Set the format of PCAP traces to be used. This function has to be
   12.18 +   * called before EnablePcap(), so that the header of the pcap file
   12.19 +   * can be written correctly.
   12.20 +   *
   12.21 +   * In madwifi, this corresponds to setting
   12.22 +   * /proc/sys/net/ath0/dev_type to a particular value. See
   12.23 +   * http://madwifi-project.org/wiki/UserDocs/MonitorModeInterface for
   12.24 +   * more information.
   12.25 +   * 
   12.26 +   * @param format the PcapFormat to be used
   12.27 +   */
   12.28 +  void SetPcapFormat (enum PcapFormat format);
   12.29 +
   12.30 +  /**
   12.31     * \param filename filename prefix to use for pcap files.
   12.32     * \param nodeid the id of the node to generate pcap output for.
   12.33     * \param deviceid the id of the device to generate pcap output for.
   12.34     *
   12.35     * Generate a pcap file which contains the link-level data observed
   12.36     * by the specified deviceid within the specified nodeid. The pcap
   12.37 -   * data is stored in the file prefix-nodeid-deviceid.pcap.
   12.38 +   * data is stored in the file prefix-nodeid-deviceid.pcap. By
   12.39 +   * default, no PHY layer information is provided. An optional header
   12.40 +   * with PHY layer information, such as the radiotap or the prism
   12.41 +   * header, can be used by invoking SetPcapFormat().
   12.42     *
   12.43     * This method should be invoked after the network topology has 
   12.44     * been fully constructed.
   12.45     */
   12.46 -  static void EnablePcap (std::string filename, uint32_t nodeid, uint32_t deviceid);
   12.47 +  void EnablePcap (std::string filename, uint32_t nodeid, uint32_t deviceid);
   12.48  
   12.49    /**
   12.50     * \param filename filename prefix to use for pcap files.
   12.51 @@ -218,7 +245,7 @@
   12.52     * Enable pcap output on each input device which is of the
   12.53     * ns3::WifiNetDevice type.
   12.54     */
   12.55 -  static void EnablePcap (std::string filename, Ptr<NetDevice> nd);
   12.56 +   void EnablePcap (std::string filename, Ptr<NetDevice> nd);
   12.57  
   12.58    /**
   12.59     * \param filename filename prefix to use for pcap files.
   12.60 @@ -227,7 +254,7 @@
   12.61     * Enable pcap output on each input device which is of the
   12.62     * ns3::WifiNetDevice type.
   12.63     */
   12.64 -  static void EnablePcap (std::string filename, std::string ndName);
   12.65 +   void EnablePcap (std::string filename, std::string ndName);
   12.66  
   12.67    /**
   12.68     * \param filename filename prefix to use for pcap files.
   12.69 @@ -236,7 +263,7 @@
   12.70     * Enable pcap output on each input device which is of the
   12.71     * ns3::WifiNetDevice type.
   12.72     */
   12.73 -  static void EnablePcap (std::string filename, NetDeviceContainer d);
   12.74 +   void EnablePcap (std::string filename, NetDeviceContainer d);
   12.75  
   12.76    /**
   12.77     * \param filename filename prefix to use for pcap files.
   12.78 @@ -246,7 +273,7 @@
   12.79     * ns3::WifiNetDevice type and which is located in one of the 
   12.80     * input nodes.
   12.81     */
   12.82 -  static void EnablePcap (std::string filename, NodeContainer n);
   12.83 +   void EnablePcap (std::string filename, NodeContainer n);
   12.84  
   12.85    /**
   12.86     * \param filename filename prefix to use for pcap files.
   12.87 @@ -254,7 +281,7 @@
   12.88     * Enable pcap output on each device which is of the
   12.89     * ns3::WifiNetDevice type
   12.90     */
   12.91 -  static void EnablePcapAll (std::string filename);
   12.92 +   void EnablePcapAll (std::string filename);
   12.93  
   12.94    /**
   12.95     * \param os output stream
   12.96 @@ -311,6 +338,7 @@
   12.97    ObjectFactory m_phy;
   12.98    ObjectFactory m_errorRateModel;
   12.99    Ptr<YansWifiChannel> m_channel;
  12.100 +  enum PcapFormat m_pcapFormat;
  12.101  };
  12.102  
  12.103  } // namespace ns3