1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #ifndef INTERFERENCE_HELPER_H
22 #define INTERFERENCE_HELPER_H
23 
24 #include "phy-entity.h"
25 
26 namespace ns3 {
27 
28 class WifiPpdu;
29 class WifiPsdu;
30 class ErrorRateModel;
31 
32 /**
33  * \ingroup wifi
34  * \brief handles interference calculations
35  * \brief signal event for a PPDU.
36  */
37 class Event : public SimpleRefCount<Event>
38 {
39 public:
40   /**
41    * Create an Event with the given parameters. Note that <i>rxPower</i> will
42    * be moved into this object.
43    *
44    * \param ppdu the PPDU
45    * \param txVector the TXVECTOR
46    * \param duration duration of the PPDU
47    * \param rxPower the received power per band (W)
48    */
49   Event (Ptr<const WifiPpdu> ppdu, const WifiTxVector& txVector, Time duration,  RxPowerWattPerChannelBand&& rxPower);
50   ~Event ();
51 
52   /**
53    * Return the PPDU.
54    *
55    * \return the PPDU
56    */
57   Ptr<const WifiPpdu> GetPpdu (void) const;
58   /**
59    * Return the start time of the signal.
60    *
61    * \return the start time of the signal
62    */
63   Time GetStartTime (void) const;
64   /**
65    * Return the end time of the signal.
66    *
67    * \return the end time of the signal
68    */
69   Time GetEndTime (void) const;
70   /**
71    * Return the duration of the signal.
72    *
73    * \return the duration of the signal
74    */
75   Time GetDuration (void) const;
76   /**
77    * Return the total received power (W).
78    *
79    * \return the total received power (W)
80    */
81   double GetRxPowerW (void) const;
82   /**
83    * Return the received power (W) for a given band.
84    *
85    * \param band the band for which the power should be returned
86    * \return the received power (W) for a given band
87    */
88   double GetRxPowerW (WifiSpectrumBand band) const;
89   /**
90    * Return the received power (W) for all bands.
91    *
92    * \return the received power (W) for all bands.
93    */
94   const RxPowerWattPerChannelBand& GetRxPowerWPerBand (void) const;
95   /**
96    * Return the TXVECTOR of the PPDU.
97    *
98    * \return the TXVECTOR of the PPDU
99    */
100   const WifiTxVector& GetTxVector (void) const;
101   /**
102    * Update the received power (W) for all bands, i.e. add up the received power
103    * to the current received power, for each band.
104    *
105    * \param rxPower the received power (W) for all bands.
106    */
107   void UpdateRxPowerW (const RxPowerWattPerChannelBand& rxPower);
108 
109 
110 private:
111   Ptr<const WifiPpdu> m_ppdu;           //!< PPDU
112   WifiTxVector m_txVector;              //!< TXVECTOR
113   Time m_startTime;                     //!< start time
114   Time m_endTime;                       //!< end time
115   RxPowerWattPerChannelBand m_rxPowerW; //!< received power in watts per band
116 };
117 
118 /**
119  * \brief Stream insertion operator.
120  *
121  * \param os the stream
122  * \param event the event
123  * \returns a reference to the stream
124  */
125 std::ostream& operator<< (std::ostream& os, const Event &event);
126 
127 
128 /**
129  * \ingroup wifi
130  * \brief handles interference calculations
131  */
132 class InterferenceHelper
133 {
134 public:
135   InterferenceHelper ();
136   ~InterferenceHelper ();
137 
138   /**
139    * Add a frequency band.
140    *
141    * \param band the band to be created
142    */
143   void AddBand (WifiSpectrumBand band);
144 
145   /**
146    * Remove the frequency bands.
147    */
148   void RemoveBands (void);
149 
150   /**
151    * Set the noise figure.
152    *
153    * \param value noise figure in linear scale
154    */
155   void SetNoiseFigure (double value);
156   /**
157    * Set the error rate model for this interference helper.
158    *
159    * \param rate Error rate model
160    */
161   void SetErrorRateModel (const Ptr<ErrorRateModel> rate);
162 
163   /**
164    * Return the error rate model.
165    *
166    * \return Error rate model
167    */
168   Ptr<ErrorRateModel> GetErrorRateModel (void) const;
169   /**
170    * Set the number of RX antennas in the receiver corresponding to this
171    * interference helper.
172    *
173    * \param rx the number of RX antennas
174    */
175   void SetNumberOfReceiveAntennas (uint8_t rx);
176 
177   /**
178    * \param energyW the minimum energy (W) requested
179    * \param band identify the requested band
180    *
181    * \returns the expected amount of time the observed
182    *          energy on the medium for a given band will
183    *          be higher than the requested threshold.
184    */
185   Time GetEnergyDuration (double energyW, WifiSpectrumBand band);
186 
187   /**
188    * Add the PPDU-related signal to interference helper.
189    *
190    * \param ppdu the PPDU
191    * \param txVector the TXVECTOR
192    * \param duration the PPDU duration
193    * \param rxPower received power per band (W)
194    * \param isStartOfdmaRxing flag whether the event corresponds to the start of the OFDMA payload reception (only used for UL-OFDMA) //TODO simplify this once WifiPpdu is subclassed by adding an attribute
195    *
196    * \return Event
197    */
198   Ptr<Event> Add (Ptr<const WifiPpdu> ppdu, const WifiTxVector& txVector, Time duration, RxPowerWattPerChannelBand& rxPower, bool isStartOfdmaRxing = false);
199 
200   /**
201    * Add a non-Wifi signal to interference helper.
202    * \param duration the duration of the signal
203    * \param rxPower received power per band (W)
204    */
205   void AddForeignSignal (Time duration, RxPowerWattPerChannelBand& rxPower);
206   /**
207    * Calculate the SNIR at the start of the payload and accumulate
208    * all SNIR changes in the SNIR vector for each MPDU of an A-MPDU.
209    * This workaround is required in order to provide one PER per MPDU, for
210    * reception success/failure evaluation, while hiding aggregation details from
211    * this class.
212    *
213    * \param event the event corresponding to the first time the corresponding PPDU arrives
214    * \param channelWidth the channel width used to transmit the PSDU (in MHz)
215    * \param band identify the band used by the PSDU
216    * \param staId the station ID of the PSDU (only used for MU)
217    * \param relativeMpduStartStop the time window (pair of start and end times) of PHY payload to focus on
218    *
219    * \return struct of SNR and PER (with PER being evaluated over the provided time window)
220    */
221   struct PhyEntity::SnrPer CalculatePayloadSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band,
222                                                             uint16_t staId, std::pair<Time, Time> relativeMpduStartStop) const;
223   /**
224    * Calculate the SNIR for the event (starting from now until the event end).
225    *
226    * \param event the event corresponding to the first time the corresponding PPDU arrives
227    * \param channelWidth the channel width (in MHz)
228    * \param nss the number of spatial streams
229    * \param band identify the band used by the PSDU
230    *
231    * \return the SNR for the PPDU in linear scale
232    */
233   double CalculateSnr (Ptr<Event> event, uint16_t channelWidth, uint8_t nss, WifiSpectrumBand band) const;
234   /**
235    * Calculate the SNIR at the start of the PHY header and accumulate
236    * all SNIR changes in the SNIR vector.
237    *
238    * \param event the event corresponding to the first time the corresponding PPDU arrives
239    * \param channelWidth the channel width (in MHz) for header measurement
240    * \param band identify the band used by the PSDU
241    * \param header the PHY header to consider
242    *
243    * \return struct of SNR and PER
244    */
245   struct PhyEntity::SnrPer CalculatePhyHeaderSnrPer (Ptr<Event> event, uint16_t channelWidth, WifiSpectrumBand band,
246                                                               WifiPpduField header) const;
247 
248   /**
249    * Notify that RX has started.
250    */
251   void NotifyRxStart ();
252   /**
253    * Notify that RX has ended.
254    *
255    * \param endTime the end time of the signal
256    */
257   void NotifyRxEnd (Time endTime);
258   /**
259    * Erase all events.
260    */
261   void EraseEvents (void);
262 
263   /**
264    * Update event to scale its received power (W) per band.
265    *
266    * \param event the event to be updated
267    * \param rxPower the received power (W) per band to be added to the current event
268    */
269   void UpdateEvent (Ptr<Event> event, const RxPowerWattPerChannelBand& rxPower);
270 
271 
272 protected:
273   /**
274    * Calculate SNR (linear ratio) from the given signal power and noise+interference power.
275    *
276    * \param signal signal power, W
277    * \param noiseInterference noise and interference power, W
278    * \param channelWidth signal width (MHz)
279    * \param nss the number of spatial streams
280    *
281    * \return SNR in linear scale
282    */
283   double CalculateSnr (double signal, double noiseInterference, uint16_t channelWidth, uint8_t nss) const;
284   /**
285    * Calculate the success rate of the chunk given the SINR, duration, and TXVECTOR.
286    * The duration and TXVECTOR are used to calculate how many bits are present in the chunk.
287    *
288    * \param snir the SINR
289    * \param duration the duration of the chunk
290    * \param mode the WifiMode
291    * \param txVector the TXVECTOR
292    * \param field the PPDU field to which the chunk belongs to
293    *
294    * \return the success rate
295    */
296   double CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode, const WifiTxVector& txVector, WifiPpduField field) const;
297   /**
298    * Calculate the success rate of the payload chunk given the SINR, duration, and TXVECTOR.
299    * The duration and TXVECTOR are used to calculate how many bits are present in the payload chunk.
300    *
301    * \param snir the SINR
302    * \param duration the duration of the chunk
303    * \param txVector the TXVECTOR
304    * \param staId the station ID of the PSDU (only used for MU)
305    *
306    * \return the success rate
307    */
308   double CalculatePayloadChunkSuccessRate (double snir, Time duration, const WifiTxVector& txVector, uint16_t staId = SU_STA_ID) const;
309 
310 private:
311   /**
312    * Noise and Interference (thus Ni) event.
313    */
314   class NiChange
315   {
316 public:
317     /**
318      * Create a NiChange at the given time and the amount of NI change.
319      *
320      * \param power the power in watts
321      * \param event causes this NI change
322      */
323     NiChange (double power, Ptr<Event> event);
324     ~NiChange ();
325     /**
326      * Return the power
327      *
328      * \return the power in watts
329      */
330     double GetPower (void) const;
331     /**
332      * Add a given amount of power.
333      *
334      * \param power the power to be added to the existing value in watts
335      */
336     void AddPower (double power);
337     /**
338      * Return the event causes the corresponding NI change
339      *
340      * \return the event
341      */
342     Ptr<Event> GetEvent (void) const;
343 
344 
345 private:
346     double m_power; ///< power in watts
347     Ptr<Event> m_event; ///< event
348   };
349 
350   /**
351    * typedef for a multimap of NiChange
352    */
353   typedef std::multimap<Time, NiChange> NiChanges;
354 
355   /**
356    * Map of NiChanges per band
357    */
358   typedef std::map <WifiSpectrumBand, NiChanges> NiChangesPerBand;
359 
360   /**
361    * Append the given Event.
362    *
363    * \param event the event to be appended
364    * \param isStartOfdmaRxing flag whether event corresponds to the start of the OFDMA payload reception (only used for UL-OFDMA)
365    */
366   void AppendEvent (Ptr<Event> event, bool isStartOfdmaRxing);
367 
368   /**
369    * Calculate noise and interference power in W.
370    *
371    * \param event the event
372    * \param nis the NiChanges
373    * \param band the band
374    *
375    * \return noise and interference power
376    */
377   double CalculateNoiseInterferenceW (Ptr<Event> event, NiChangesPerBand *nis, WifiSpectrumBand band) const;
378   /**
379    * Calculate the error rate of the given PHY payload only in the provided time
380    * window (thus enabling per MPDU PER information). The PHY payload can be divided into
381    * multiple chunks (e.g. due to interference from other transmissions).
382    *
383    * \param event the event
384    * \param channelWidth the channel width used to transmit the PSDU (in MHz)
385    * \param nis the NiChanges
386    * \param band identify the band used by the PSDU
387    * \param staId the station ID of the PSDU (only used for MU)
388    * \param window time window (pair of start and end times) of PHY payload to focus on
389    *
390    * \return the error rate of the payload
391    */
392   double CalculatePayloadPer (Ptr<const Event> event, uint16_t channelWidth, NiChangesPerBand *nis, WifiSpectrumBand band,
393                               uint16_t staId, std::pair<Time, Time> window) const;
394   /**
395    * Calculate the error rate of the PHY header. The PHY header
396    * can be divided into multiple chunks (e.g. due to interference from other transmissions).
397    *
398    * \param event the event
399    * \param nis the NiChanges
400    * \param channelWidth the channel width (in MHz) for header measurement
401    * \param band the band
402    * \param header the PHY header to consider
403    *
404    * \return the error rate of the HT PHY header
405    */
406   double CalculatePhyHeaderPer (Ptr<const Event> event, NiChangesPerBand *nis,
407                                 uint16_t channelWidth, WifiSpectrumBand band,
408                                 WifiPpduField header) const;
409   /**
410    * Calculate the success rate of the PHY header sections for the provided event.
411    *
412    * \param event the event
413    * \param nis the NiChanges
414    * \param channelWidth the channel width (in MHz) for header measurement
415    * \param band the band
416    * \param phyHeaderSections the map of PHY header sections (\see PhyEntity::PhyHeaderSections)
417    *
418    * \return the success rate of the PHY header sections
419    */
420   double CalculatePhyHeaderSectionPsr (Ptr<const Event> event, NiChangesPerBand *nis,
421                                        uint16_t channelWidth, WifiSpectrumBand band,
422                                        PhyEntity::PhyHeaderSections phyHeaderSections) const;
423 
424   double m_noiseFigure;                                    //!< noise figure (linear)
425   Ptr<ErrorRateModel> m_errorRateModel;                    //!< error rate model
426   uint8_t m_numRxAntennas;                                 //!< the number of RX antennas in the corresponding receiver
427   NiChangesPerBand m_niChangesPerBand;                     //!< NI Changes for each band
428   std::map <WifiSpectrumBand, double> m_firstPowerPerBand; //!< first power of each band in watts
429   bool m_rxing;                                            //!< flag whether it is in receiving state
430 
431   /**
432    * Returns an iterator to the first NiChange that is later than moment
433    *
434    * \param moment time to check from
435    * \param niIt iterator of the band to check
436    * \returns an iterator to the list of NiChanges
437    */
438   NiChanges::iterator GetNextPosition (Time moment, NiChangesPerBand::iterator niIt);
439   /**
440    * Returns an iterator to the last NiChange that is before than moment
441    *
442    * \param moment time to check from
443    * \param niIt iterator of the band to check
444    * \returns an iterator to the list of NiChanges
445    */
446   NiChanges::iterator GetPreviousPosition (Time moment, NiChangesPerBand::iterator niIt);
447 
448   /**
449    * Add NiChange to the list at the appropriate position and
450    * return the iterator of the new event.
451    *
452    * \param moment time to check from
453    * \param change the NiChange to add
454    * \param niIt iterator of the band to check
455    * \returns the iterator of the new event
456    */
457   NiChanges::iterator AddNiChangeEvent (Time moment, NiChange change, NiChangesPerBand::iterator niIt);
458 };
459 
460 } //namespace ns3
461 
462 #endif /* INTERFERENCE_HELPER_H */
463