1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
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: Stefano Avallone <stavallo@unina.it>
19  */
20 
21 #ifndef FRAME_EXCHANGE_MANAGER_H
22 #define FRAME_EXCHANGE_MANAGER_H
23 
24 #include "ns3/object.h"
25 #include "qos-txop.h"
26 #include "wifi-tx-vector.h"
27 #include "wifi-psdu.h"
28 #include "regular-wifi-mac.h"
29 #include "mac-rx-middle.h"
30 #include "mac-tx-middle.h"
31 #include "wifi-phy.h"
32 #include "wifi-tx-timer.h"
33 #include "wifi-tx-parameters.h"
34 // Needed to compile wave bindings
35 #include "ns3/wifi-protection-manager.h"
36 #include "ns3/wifi-ack-manager.h"
37 #include "channel-access-manager.h"
38 
39 namespace ns3 {
40 
41 struct RxSignalInfo;
42 struct WifiProtection;
43 struct WifiAcknowledgment;
44 
45 /**
46  * \ingroup wifi
47  *
48  * FrameExchangeManager is a base class handling the basic frame exchange
49  * sequences for non-QoS stations.
50  */
51 class FrameExchangeManager : public Object
52 {
53 public:
54   /**
55    * \brief Get the type ID.
56    * \return the object TypeId
57    */
58   static TypeId GetTypeId (void);
59   FrameExchangeManager ();
60   virtual ~FrameExchangeManager ();
61 
62   /**
63    * typedef for a callback to invoke when an MPDU is dropped.
64    */
65   typedef Callback <void, WifiMacDropReason, Ptr<const WifiMacQueueItem>> DroppedMpdu;
66   /**
67    * typedef for a callback to invoke when an MPDU is successfully acknowledged.
68    */
69   typedef Callback <void, Ptr<const WifiMacQueueItem>> AckedMpdu;
70 
71   /**
72    * Request the FrameExchangeManager to start a frame exchange sequence.
73    *
74    * \param dcf the channel access function that gained channel access. It is
75    *            the DCF on non-QoS stations and an EDCA on QoS stations.
76    * \return true if a frame exchange sequence was started, false otherwise
77    */
78   virtual bool StartTransmission (Ptr<Txop> dcf);
79 
80   /**
81    * This method is intended to be called by the PHY layer every time an MPDU
82    * is received and also when the reception of an A-MPDU is completed. In case
83    * the PSDU contains multiple MPDUs, the <i>perMpduStatus</i> vector is empty
84    * when receiving the individual MPDUs.
85    *
86    * \param psdu the received PSDU
87    * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
88    * \param txVector TxVector of the received PSDU
89    * \param perMpduStatus per MPDU reception status
90    */
91   void Receive (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
92                 WifiTxVector txVector, std::vector<bool> perMpduStatus);
93 
94   /**
95    * Set the MAC layer to use.
96    *
97    * \param mac the MAC layer to use
98    */
99   virtual void SetWifiMac (const Ptr<RegularWifiMac> mac);
100   /**
101    * Set the MAC TX Middle to use.
102    *
103    * \param txMiddle the MAC TX Middle to use
104    */
105   virtual void SetMacTxMiddle (const Ptr<MacTxMiddle> txMiddle);
106   /**
107    * Set the MAC RX Middle to use.
108    *
109    * \param rxMiddle the MAC RX Middle to use
110    */
111   virtual void SetMacRxMiddle (const Ptr<MacRxMiddle> rxMiddle);
112   /**
113    * Set the channel access manager to use
114    *
115    * \param channelAccessManager the channel access manager to use
116    */
117   virtual void SetChannelAccessManager (const Ptr<ChannelAccessManager> channelAccessManager);
118   /**
119    * Set the PHY layer to use.
120    *
121    * \param phy the PHY layer to use
122    */
123   virtual void SetWifiPhy (const Ptr<WifiPhy> phy);
124   /**
125    * Remove WifiPhy associated with this FrameExchangeManager.
126    */
127   virtual void ResetPhy (void);
128   /**
129    * Set the Protection Manager to use
130    *
131    * \param protectionManager the Protection Manager to use
132    */
133   virtual void SetProtectionManager (Ptr<WifiProtectionManager> protectionManager);
134   /**
135    * Set the Acknowledgment Manager to use
136    *
137    * \param ackManager the Acknowledgment Manager to use
138    */
139   virtual void SetAckManager (Ptr<WifiAckManager> ackManager);
140   /**
141    * Set the MAC address.
142    *
143    * \param address the MAC address
144    */
145   virtual void SetAddress (Mac48Address address);
146   /**
147    * Set the Basic Service Set Identification.
148    *
149    * \param bssid the BSSID
150    */
151   virtual void SetBssid (Mac48Address bssid);
152   /**
153    * Set the callback to invoke when an MPDU is dropped.
154    *
155    * \param callback the callback to invoke when an MPDU is dropped
156    */
157   virtual void SetDroppedMpduCallback (DroppedMpdu callback);
158   /**
159    * Set the callback to invoke when an MPDU is successfully acked.
160    *
161    * \param callback the callback to invoke when an MPDU is successfully acked
162    */
163   void SetAckedMpduCallback (AckedMpdu callback);
164   /**
165    * Enable promiscuous mode.
166    */
167   void SetPromisc (void);
168   /**
169    * Check if the device is operating in promiscuous mode.
170    *
171    * \return true if the device is operating in promiscuous mode,
172    *         false otherwise
173    */
174   bool IsPromisc (void) const;
175 
176   /**
177    * Get a const reference to the WifiTxTimer object.
178    *
179    * \return a const reference to the WifiTxTimer object
180    */
181   const WifiTxTimer& GetWifiTxTimer (void) const;
182 
183   /**
184    * Get the Protection Manager used by this node.
185    *
186    * \return the Protection Manager used by this node
187    */
188   Ptr<WifiProtectionManager> GetProtectionManager (void) const;
189 
190   /**
191    * Calculate the time required to protect a frame according to the given
192    * protection method. The protection time is stored in the protection
193    * object itself.
194    *
195    * \param protection the protection method
196    */
197   virtual void CalculateProtectionTime (WifiProtection* protection) const;
198 
199   /**
200    * Get the Acknowledgment Manager used by this node.
201    *
202    * \return the Acknowledgment Manager used by this node
203    */
204   Ptr<WifiAckManager> GetAckManager (void) const;
205 
206   /**
207    * Calculate the time required to acknowledge a frame according to the given
208    * acknowledgment method. The acknowledgment time is stored in the acknowledgment
209    * object itself.
210    *
211    * \param acknowledgment the acknowledgment method
212    */
213   virtual void CalculateAcknowledgmentTime (WifiAcknowledgment* acknowledgment) const;
214 
215   /**
216    * Notify that an internal collision has occurred for the given Txop
217    *
218    * \param txop the Txop for which an internal collision has occurred
219    */
220   virtual void NotifyInternalCollision (Ptr<Txop> txop);
221 
222   /**
223    * \param duration switching delay duration.
224    *
225    * This method is typically invoked by the PhyListener to notify
226    * the MAC layer that a channel switching occurred. When a channel switching
227    * occurs, pending MAC transmissions (RTS, CTS, Data and Ack) are cancelled.
228    */
229   void NotifySwitchingStartNow (Time duration);
230 
231   /**
232    * This method is typically invoked by the PhyListener to notify
233    * the MAC layer that the device has been put into sleep mode. When the device is put
234    * into sleep mode, pending MAC transmissions (RTS, CTS, Data and Ack) are cancelled.
235    */
236   void NotifySleepNow (void);
237 
238   /**
239    * This method is typically invoked by the PhyListener to notify
240    * the MAC layer that the device has been put into off mode. When the device is put
241    * into off mode, pending MAC transmissions (RTS, CTS, Data and Ack) are cancelled.
242    */
243   void NotifyOffNow (void);
244 
245 protected:
246   void DoDispose () override;
247 
248   /**
249    * Fragment the given MPDU if needed. If fragmentation is needed, return the
250    * first fragment; otherwise, return the given MPDU. Note that, if fragmentation
251    * is applied, the given MPDU is dequeued from the MAC queue and the first
252    * fragment is enqueued in its place.
253    *
254    * \param mpdu the given MPDU
255    * \return the first fragment if fragmentation is needed, the given MPDU otherwise
256    */
257   Ptr<WifiMacQueueItem> GetFirstFragmentIfNeeded (Ptr<WifiMacQueueItem> mpdu);
258 
259   /**
260    * Send an MPDU with the given TX parameters (with the specified protection).
261    * Note that <i>txParams</i> is moved to m_txParams and hence is left in an
262    * undefined state.
263    *
264    * \param mpdu the MPDU to send
265    * \param txParams the TX parameters to use to transmit the MPDU
266    */
267   void SendMpduWithProtection (Ptr<WifiMacQueueItem> mpdu, WifiTxParameters& txParams);
268 
269   /**
270    * Update the NAV, if needed, based on the Duration/ID of the given <i>psdu</i>.
271    *
272    * \param psdu the received PSDU
273    * \param txVector TxVector of the received PSDU
274    */
275   virtual void UpdateNav (Ptr<const WifiPsdu> psdu, const WifiTxVector& txVector);
276 
277   /**
278    * Reset the NAV upon expiration of the NAV reset timer.
279    */
280   virtual void NavResetTimeout (void);
281 
282   /**
283    * This method handles the reception of an MPDU (possibly included in an A-MPDU)
284    *
285    * \param mpdu the received MPDU
286    * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
287    * \param txVector TxVector of the received PSDU
288    * \param inAmpdu true if the MPDU is part of an A-MPDU
289    */
290   virtual void ReceiveMpdu (Ptr<WifiMacQueueItem> mpdu, RxSignalInfo rxSignalInfo,
291                             const WifiTxVector& txVector, bool inAmpdu);
292 
293   /**
294    * This method is called when the reception of an A-MPDU including multiple
295    * MPDUs is completed.
296    *
297    * \param psdu the received PSDU
298    * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
299    * \param txVector TxVector of the received PSDU
300    * \param perMpduStatus per MPDU reception status
301    */
302   virtual void EndReceiveAmpdu (Ptr<const WifiPsdu> psdu, const RxSignalInfo& rxSignalInfo,
303                                 const WifiTxVector& txVector, const std::vector<bool>& perMpduStatus);
304 
305   /**
306    * Perform the actions needed when a Normal Ack is received.
307    *
308    * \param mpdu the MPDU that was acknowledged
309    * \param txVector the TXVECTOR used to transmit the MPDU that was acknowledged
310    * \param ackTxVector the TXVECTOR used to transmit the Normal Ack frame
311    * \param rxInfo the info on the received signal (\see RxSignalInfo)
312    * \param snr the SNR at the receiver for the MPDU that was acknowledged
313    */
314   virtual void ReceivedNormalAck (Ptr<WifiMacQueueItem> mpdu, const WifiTxVector& txVector,
315                                   const WifiTxVector& ackTxVector, const RxSignalInfo& rxInfo, double snr);
316 
317   /**
318    * Notify other components that an MPDU was acknowledged.
319    *
320    * \param mpdu the MPDU that was acknowledged
321    */
322   virtual void NotifyReceivedNormalAck (Ptr<WifiMacQueueItem> mpdu);
323 
324   /**
325    * Retransmit an MPDU that was not acknowledged.
326    *
327    * \param mpdu the MPDU to retransmit
328    */
329   virtual void RetransmitMpduAfterMissedAck (Ptr<WifiMacQueueItem> mpdu) const;
330 
331   /**
332    * Retransmit an MPDU that was not sent because a CTS was not received.
333    *
334    * \param mpdu the MPDU to retransmit
335    */
336   virtual void RetransmitMpduAfterMissedCts (Ptr<WifiMacQueueItem> mpdu) const;
337 
338   /**
339    * Pass the given MPDU, discarded because of the max retry limit was reached,
340    * to the MPDU dropped callback.
341    *
342    * \param mpdu the discarded MPDU
343    */
344   virtual void NotifyPacketDiscarded (Ptr<const WifiMacQueueItem> mpdu);
345 
346   /**
347    * Perform actions that are possibly needed when receiving any frame,
348    * independently of whether the frame is addressed to this station
349    * (e.g., setting the NAV or the TXOP holder).
350    *
351    * \param psdu the received PSDU
352    * \param txVector TX vector of the received PSDU
353    */
354   virtual void PreProcessFrame (Ptr<const WifiPsdu> psdu, const WifiTxVector& txVector);
355 
356   /**
357    * Get the updated TX duration of the frame associated with the given TX
358    * parameters if the size of the PSDU addressed to the given receiver
359    * becomes <i>ppduPayloadSize</i>.
360    *
361    * \param ppduPayloadSize the new PSDU size
362    * \param receiver the MAC address of the receiver of the PSDU
363    * \param txParams the TX parameters
364    * \return the updated TX duration
365    */
366   virtual Time GetTxDuration (uint32_t ppduPayloadSize, Mac48Address receiver,
367                                  const WifiTxParameters& txParams) const;
368 
369   /**
370    * Update the TX duration field of the given TX parameters after that the PSDU
371    * addressed to the given receiver has changed.
372    *
373    * \param receiver the MAC address of the receiver of the PSDU
374    * \param txParams the TX parameters
375    */
376   void UpdateTxDuration (Mac48Address receiver, WifiTxParameters& txParams) const;
377 
378   Ptr<Txop> m_dcf;                                  //!< the DCF/EDCAF that gained channel access
379   WifiTxTimer m_txTimer;                            //!< the timer set upon frame transmission
380   EventId m_navResetEvent;                          //!< the event to reset the NAV after an RTS
381   Ptr<RegularWifiMac> m_mac;                        //!< the MAC layer on this station
382   Ptr<MacTxMiddle> m_txMiddle;                      //!< the MAC TX Middle on this station
383   Ptr<MacRxMiddle> m_rxMiddle;                      //!< the MAC RX Middle on this station
384   Ptr<ChannelAccessManager> m_channelAccessManager; //!< the channel access manager
385   Ptr<WifiPhy> m_phy;                               //!< the PHY layer on this station
386   Mac48Address m_self;                              //!< the MAC address of this device
387   Mac48Address m_bssid;                             //!< BSSID address (Mac48Address)
388   Time m_navEnd;                                    //!< NAV expiration time
389   bool m_promisc;                                   //!< Flag if the device is operating in promiscuous mode
390   DroppedMpdu m_droppedMpduCallback;                //!< the dropped MPDU callback
391   AckedMpdu m_ackedMpduCallback;                    //!< the acknowledged MPDU callback
392 
393   /**
394    * Forward an MPDU down to the PHY layer.
395    *
396    * \param mpdu the MPDU to forward down
397    * \param txVector the TXVECTOR used to transmit the MPDU
398    */
399   virtual void ForwardMpduDown (Ptr<WifiMacQueueItem> mpdu, WifiTxVector& txVector);
400 
401   /**
402    * Dequeue the given MPDU from the queue in which it is stored.
403    *
404    * \param mpdu the given MPDU
405    */
406   virtual void DequeueMpdu (Ptr<const WifiMacQueueItem> mpdu);
407 
408   /**
409    * Compute how to set the Duration/ID field of a frame being transmitted with
410    * the given TX parameters
411    *
412    * \param header the MAC header of the frame
413    * \param size the size of the frame in bytes
414    * \param txParams the TX parameters used to send the frame
415    * \param fragmentedPacket the packet that originated the frame to transmit, in case
416    *                         the latter is a fragment
417    * \return the computed Duration/ID value
418    */
419   virtual Time GetFrameDurationId (const WifiMacHeader& header, uint32_t size,
420                                    const WifiTxParameters& txParams,
421                                    Ptr<Packet> fragmentedPacket) const;
422 
423   /**
424    * Compute how to set the Duration/ID field of an RTS frame to send to protect
425    * a frame transmitted with the given TX vector.
426    *
427    * \param rtsTxVector the TX vector used to send the RTS frame
428    * \param txDuration the TX duration of the data frame
429    * \param response the time taken by the response (acknowledgment) to the data frame
430    * \return the computed Duration/ID value for the RTS frame
431    */
432   virtual Time GetRtsDurationId (const WifiTxVector& rtsTxVector, Time txDuration, Time response) const;
433 
434   /**
435    * Send RTS to begin RTS-CTS-Data-Ack transaction.
436    *
437    * \param txParams the TX parameters for the data frame
438    */
439   void SendRts (const WifiTxParameters& txParams);
440 
441   /**
442    * Send CTS after receiving RTS.
443    *
444    * \param rtsHdr the header of the received RTS
445    * \param rtsTxMode the TX mode used to transmit the RTS
446    * \param rtsSnr the SNR of the RTS in linear scale
447    */
448   void SendCtsAfterRts (const WifiMacHeader& rtsHdr, WifiMode rtsTxMode, double rtsSnr);
449 
450   /**
451    * Send CTS after receiving RTS.
452    *
453    * \param rtsHdr the header of the received RTS
454    * \param ctsTxVector the TXVECTOR to use to transmit the CTS
455    * \param rtsSnr the SNR of the RTS in linear scale
456    */
457   void DoSendCtsAfterRts (const WifiMacHeader& rtsHdr, WifiTxVector& ctsTxVector, double rtsSnr);
458 
459   /**
460    * Compute how to set the Duration/ID field of a CTS-to-self frame to send to
461    * protect a frame transmitted with the given TX vector.
462    *
463    * \param ctsTxVector the TX vector used to send the CTS-to-self frame
464    * \param txDuration the TX duration of the data frame
465    * \param response the time taken by the response (acknowledgment) to the data frame
466    * \return the computed Duration/ID value for the CTS-to-self frame
467    */
468   virtual Time GetCtsToSelfDurationId (const WifiTxVector& ctsTxVector, Time txDuration,
469                                        Time response) const;
470 
471   /**
472    * Send CTS for a CTS-to-self mechanism.
473    *
474    * \param txParams the TX parameters for the data frame
475    */
476   void SendCtsToSelf (const WifiTxParameters& txParams);
477 
478   /**
479    * Send Normal Ack.
480    *
481    * \param hdr the header of the frame soliciting the Normal Ack
482    * \param dataTxVector the TXVECTOR used to transmit the frame soliciting the Normal Ack
483    * \param dataSnr the SNR of the frame soliciting the Normal Ack in linear scale
484    */
485   void SendNormalAck (const WifiMacHeader& hdr, const WifiTxVector& dataTxVector, double dataSnr);
486 
487   /**
488    * Get the next fragment of the current MSDU.
489    * Only called for fragmented MSDUs.
490    *
491    * \return the next fragment of the current MSDU.
492    */
493   Ptr<WifiMacQueueItem> GetNextFragment (void);
494 
495   /**
496    * Take necessary actions upon a transmission success. A non-QoS station
497    * transmits the next fragment, if any, or releases the channel, otherwise.
498    */
499   virtual void TransmissionSucceeded (void);
500 
501   /**
502    * Take necessary actions upon a transmission failure. A non-QoS station
503    * releases the channel when this method is called.
504    */
505   virtual void TransmissionFailed (void);
506 
507   /**
508    * Called when the Ack timeout expires.
509    *
510    * \param mpdu the MPDU that solicited a Normal Ack response
511    * \param txVector the TXVECTOR used to transmit the frame soliciting the Normal Ack
512    */
513   void NormalAckTimeout (Ptr<WifiMacQueueItem> mpdu, const WifiTxVector& txVector);
514 
515   /**
516    * Called when the CTS timeout expires.
517    *
518    * \param rts the RTS that solicited a CTS response
519    * \param txVector the TXVECTOR used to transmit the RTS frame
520    */
521   virtual void CtsTimeout (Ptr<WifiMacQueueItem> rts, const WifiTxVector& txVector);
522 
523 private:
524   /**
525    * \param txVector the TXVECTOR decoded from PHY header.
526    * \param psduDuration the duration of the PSDU that is about to be received.
527    *
528    * This method is typically invoked by the lower PHY layer to notify
529    * the MAC layer that the reception of a PSDU is starting.
530    * This is equivalent to the PHY-RXSTART primitive.
531    * If the reception is correct for at least one MPDU of the PSDU
532    * the Receive method will be called after \p psduDuration.
533    */
534   void RxStartIndication (WifiTxVector txVector, Time psduDuration);
535 
536   /**
537    * Send the current MPDU, which can be acknowledged by a Normal Ack.
538    */
539   void SendMpdu (void);
540 
541   /**
542    * Reset this frame exchange manager.
543    */
544   virtual void Reset (void);
545 
546   Ptr<WifiMacQueueItem> m_mpdu;                   //!< the MPDU being transmitted
547   WifiTxParameters m_txParams;                    //!< the TX parameters for the current frame
548   Ptr<Packet> m_fragmentedPacket;                 //!< the MSDU being fragmented
549   bool m_moreFragments;                           //!< true if a fragment has to be sent after a SIFS
550   Ptr<WifiProtectionManager> m_protectionManager; //!< Protection manager
551   Ptr<WifiAckManager> m_ackManager;               //!< Acknowledgment manager
552 };
553 
554 } //namespace ns3
555 
556 #endif /* FRAME_EXCHANGE_MANAGER_H */
557