diff --git a/src/devices/wifi/dcf-manager.h b/src/devices/wifi/dcf-manager.h index 001abb759..b2e91a11a 100644 --- a/src/devices/wifi/dcf-manager.h +++ b/src/devices/wifi/dcf-manager.h @@ -6,8 +6,15 @@ namespace ns3 { -class MacParameters; - +/** + * \brief keep track of the state needed for a single DCF + * function. + * + * Multiple instances of a DcfState can be registered in a single + * DcfManager to implement 802.11e-style relative QoS. + * DcfState::SetAifsn and DcfState::SetCwBounds allow the user to + * control the relative QoS differentiation. + */ class DcfState { public: @@ -15,12 +22,49 @@ public: virtual ~DcfState (); + /** + * \param aifsn the number of slots which make up an AIFS for a specific DCF. + * a DIFS corresponds to an AIFSN = 2. + * + * Calling this method after DcfManager::Add has been called is not recommended. + */ void SetAifsn (uint32_t aifsn); + /** + * \param minCw the minimum value for the CW variable. + * \param maxCw the maximum value for the CW variable. + * + * Calling this method after DcfManager::Add has been called is not recommended. + */ void SetCwBounds (uint32_t minCw, uint32_t maxCw); + /** + * Update the value of the CW variable to take into account + * a transmission success or a transmission abort (stop transmission + * of a packet after the maximum number of retransmissions has been + * reached). By default, this resets the CW variable to minCW. + */ void ResetCw (void); + /** + * Update the value of the CW variable to take into account + * a transmission failure. By default, this triggers a doubling + * of CW (capped by maxCW). + */ void UpdateFailedCw (void); + /** + * \param nSlots the number of slots of the backoff. + * + * Start a backoff by initializing the backoff counter to the number of + * slots specified. + */ void StartBackoffNow (uint32_t nSlots); + /** + * \returns the current value of the CW variable. The initial value is + * minCW. + */ uint32_t GetCw (void) const; + /** + * \returns true if access has been requested for this DcfState and + * has not been granted already, false otherwise. + */ bool IsAccessRequested (void) const; private: @@ -36,8 +80,33 @@ private: void NotifyInternalCollision (void); + /** + * Called by DcfManager to notify a DcfState subclass + * that access to the medium is granted and can + * start immediately. + */ virtual void DoNotifyAccessGranted (void) = 0; + /** + * Called by DcfManager to notify a DcfState subclass + * that an 'internal' collision occured, that is, that + * the backoff timer of a higher priority DcfState expired + * at the same time and that access was granted to this + * higher priority DcfState. + * + * The subclass is expected to start a new backoff by + * calling DcfState::StartBackoffNow and DcfManager::RequestAccess + * is access is still needed. + */ virtual void DoNotifyInternalCollision (void) = 0; + /** + * Called by DcfManager to notify a DcfState subclass + * that a normal collision occured, that is, that + * the medium was busy when access was requested. + * + * The subclass is expected to start a new backoff by + * calling DcfState::StartBackoffNow and DcfManager::RequestAccess + * is access is still needed. + */ virtual void DoNotifyCollision (void) = 0; uint32_t m_aifsn; @@ -52,20 +121,69 @@ private: bool m_accessRequested; }; +/** + * \brief Manage a set of ns3::DcfState + * + * Handle a set of independent ns3::DcfState, each of which represents + * a single DCF within a MAC stack. Each ns3::DcfState has a priority + * implicitely associated with it (the priority is determined when the + * ns3::DcfState is added to the DcfManager: the first DcfState to be + * added gets the highest priority, the second, the second highest + * priority, and so on.) which is used to handle "internal" collisions. + * i.e., when two local DcfState are expected to get access to the + * medium at the same time, the highest priority local DcfState wins + * access to the medium and the other DcfState suffers a "internal" + * collision. + */ class DcfManager { public: DcfManager (); + /** + * \param slotTime the duration of a slot. + * + * It is a bad idea to call this method after RequestAccess or + * one of the Notify methods has been invoked. + */ void SetSlotTime (Time slotTime); + /** + * \param sifs the duration of a SIFS. + * + * It is a bad idea to call this method after RequestAccess or + * one of the Notify methods has been invoked. + */ void SetSifs (Time sifs); - // at the lowest mandatory rate. - // used for EIFS calculation. + /** + * \param ackTxDuration time to transmit an ACK at the lowest mandatory rate + * + * This value is used for the calculation of the EIFS duration. + * It is a bad idea to call this method after RequestAccess or + * one of the Notify methods has been invoked. + */ void SetAckTxDuration (Time ackTxDuration); + /** + * \param dcf a new DcfState. + * + * The DcfManager does not take ownership of this pointer so, the callee + * must make sure that the DcfState pointer will stay valid as long + * as the DcfManager is valid. Note that the order in which DcfState + * objects are added to a DcfManager matters: the first DcfState added + * has the highest priority, the second DcfState added, has the second + * highest priority, etc. + */ void Add (DcfState *dcf); + /** + * \param state a DcfState + * + * Notify the DcfManager that a specific DcfState needs access to the + * medium. The DcfManager is then responsible for starting an access + * timer and, invoking DcfState::DoNotifyAccessGranted when the access + * is granted if it ever gets granted. + */ void RequestAccess (DcfState *state); /**