00001 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ 00002 00003 #include "ns3/nstime.h" 00004 #include "ns3/event-id.h" 00005 #include <vector> 00006 00007 namespace ns3 { 00008 00009 class WifiPhy; 00010 class WifiMac; 00011 class MacLow; 00012 00013 /** 00014 * \brief keep track of the state needed for a single DCF 00015 * function. 00016 * 00017 * Multiple instances of a DcfState can be registered in a single 00018 * DcfManager to implement 802.11e-style relative QoS. 00019 * DcfState::SetAifsn and DcfState::SetCwBounds allow the user to 00020 * control the relative QoS differentiation. 00021 */ 00022 class DcfState 00023 { 00024 public: 00025 DcfState (); 00026 00027 virtual ~DcfState (); 00028 00029 /** 00030 * \param aifsn the number of slots which make up an AIFS for a specific DCF. 00031 * a DIFS corresponds to an AIFSN = 2. 00032 * 00033 * Calling this method after DcfManager::Add has been called is not recommended. 00034 */ 00035 void SetAifsn (uint32_t aifsn); 00036 void SetCwMin (uint32_t minCw); 00037 void SetCwMax (uint32_t maxCw); 00038 uint32_t GetAifsn (void) const; 00039 uint32_t GetCwMin (void) const; 00040 uint32_t GetCwMax (void) const; 00041 /** 00042 * Update the value of the CW variable to take into account 00043 * a transmission success or a transmission abort (stop transmission 00044 * of a packet after the maximum number of retransmissions has been 00045 * reached). By default, this resets the CW variable to minCW. 00046 */ 00047 void ResetCw (void); 00048 /** 00049 * Update the value of the CW variable to take into account 00050 * a transmission failure. By default, this triggers a doubling 00051 * of CW (capped by maxCW). 00052 */ 00053 void UpdateFailedCw (void); 00054 /** 00055 * \param nSlots the number of slots of the backoff. 00056 * 00057 * Start a backoff by initializing the backoff counter to the number of 00058 * slots specified. 00059 */ 00060 void StartBackoffNow (uint32_t nSlots); 00061 /** 00062 * \returns the current value of the CW variable. The initial value is 00063 * minCW. 00064 */ 00065 uint32_t GetCw (void) const; 00066 /** 00067 * \returns true if access has been requested for this DcfState and 00068 * has not been granted already, false otherwise. 00069 */ 00070 bool IsAccessRequested (void) const; 00071 00072 private: 00073 friend class DcfManager; 00074 00075 uint32_t GetBackoffSlots (void) const; 00076 Time GetBackoffStart (void) const; 00077 void UpdateBackoffSlotsNow (uint32_t nSlots, Time backoffUpdateBound); 00078 void NotifyAccessRequested (void); 00079 void NotifyAccessGranted (void); 00080 void NotifyCollision (void); 00081 void NotifyInternalCollision (void); 00082 00083 00084 /** 00085 * Called by DcfManager to notify a DcfState subclass 00086 * that access to the medium is granted and can 00087 * start immediately. 00088 */ 00089 virtual void DoNotifyAccessGranted (void) = 0; 00090 /** 00091 * Called by DcfManager to notify a DcfState subclass 00092 * that an 'internal' collision occured, that is, that 00093 * the backoff timer of a higher priority DcfState expired 00094 * at the same time and that access was granted to this 00095 * higher priority DcfState. 00096 * 00097 * The subclass is expected to start a new backoff by 00098 * calling DcfState::StartBackoffNow and DcfManager::RequestAccess 00099 * is access is still needed. 00100 */ 00101 virtual void DoNotifyInternalCollision (void) = 0; 00102 /** 00103 * Called by DcfManager to notify a DcfState subclass 00104 * that a normal collision occured, that is, that 00105 * the medium was busy when access was requested. 00106 * 00107 * The subclass is expected to start a new backoff by 00108 * calling DcfState::StartBackoffNow and DcfManager::RequestAccess 00109 * is access is still needed. 00110 */ 00111 virtual void DoNotifyCollision (void) = 0; 00112 00113 uint32_t m_aifsn; 00114 uint32_t m_backoffSlots; 00115 // the backoffStart variable is used to keep track of the 00116 // time at which a backoff was started or the time at which 00117 // the backoff counter was last updated. 00118 Time m_backoffStart; 00119 uint32_t m_cwMin; 00120 uint32_t m_cwMax; 00121 uint32_t m_cw; 00122 bool m_accessRequested; 00123 }; 00124 00125 /** 00126 * \brief Manage a set of ns3::DcfState 00127 * 00128 * Handle a set of independent ns3::DcfState, each of which represents 00129 * a single DCF within a MAC stack. Each ns3::DcfState has a priority 00130 * implicitely associated with it (the priority is determined when the 00131 * ns3::DcfState is added to the DcfManager: the first DcfState to be 00132 * added gets the highest priority, the second, the second highest 00133 * priority, and so on.) which is used to handle "internal" collisions. 00134 * i.e., when two local DcfState are expected to get access to the 00135 * medium at the same time, the highest priority local DcfState wins 00136 * access to the medium and the other DcfState suffers a "internal" 00137 * collision. 00138 */ 00139 class DcfManager 00140 { 00141 public: 00142 DcfManager (); 00143 ~DcfManager (); 00144 00145 void SetupPhyListener (Ptr<WifiPhy> phy); 00146 void SetupLowListener (Ptr<MacLow> low); 00147 00148 /** 00149 * \param slotTime the duration of a slot. 00150 * 00151 * It is a bad idea to call this method after RequestAccess or 00152 * one of the Notify methods has been invoked. 00153 */ 00154 void SetSlot (Time slotTime); 00155 /** 00156 * \param sifs the duration of a SIFS. 00157 * 00158 * It is a bad idea to call this method after RequestAccess or 00159 * one of the Notify methods has been invoked. 00160 */ 00161 void SetSifs (Time sifs); 00162 00163 /** 00164 * \param eifsNoDifs the duration of a EIFS minus the duration of DIFS. 00165 * 00166 * It is a bad idea to call this method after RequestAccess or 00167 * one of the Notify methods has been invoked. 00168 */ 00169 void SetEifsNoDifs (Time eifsNoDifs); 00170 00171 /** 00172 * \param dcf a new DcfState. 00173 * 00174 * The DcfManager does not take ownership of this pointer so, the callee 00175 * must make sure that the DcfState pointer will stay valid as long 00176 * as the DcfManager is valid. Note that the order in which DcfState 00177 * objects are added to a DcfManager matters: the first DcfState added 00178 * has the highest priority, the second DcfState added, has the second 00179 * highest priority, etc. 00180 */ 00181 void Add (DcfState *dcf); 00182 00183 /** 00184 * \param state a DcfState 00185 * 00186 * Notify the DcfManager that a specific DcfState needs access to the 00187 * medium. The DcfManager is then responsible for starting an access 00188 * timer and, invoking DcfState::DoNotifyAccessGranted when the access 00189 * is granted if it ever gets granted. 00190 */ 00191 void RequestAccess (DcfState *state); 00192 00193 /** 00194 * \param duration expected duration of reception 00195 * 00196 * Notify the DCF that a packet reception started 00197 * for the expected duration. 00198 */ 00199 void NotifyRxStartNow (Time duration); 00200 /** 00201 * Notify the DCF that a packet reception was just 00202 * completed successfully. 00203 */ 00204 void NotifyRxEndOkNow (void); 00205 /** 00206 * Notify the DCF that a packet reception was just 00207 * completed unsuccessfully. 00208 */ 00209 void NotifyRxEndErrorNow (void); 00210 /** 00211 * \param duration expected duration of transmission 00212 * 00213 * Notify the DCF that a packet transmission was 00214 * just started and is expected to last for the specified 00215 * duration. 00216 */ 00217 void NotifyTxStartNow (Time duration); 00218 /** 00219 * \param duration expected duration of cca busy period 00220 * 00221 * Notify the DCF that a CCA busy period has just started. 00222 */ 00223 void NotifyMaybeCcaBusyStartNow (Time duration); 00224 /** 00225 * \param duration the value of the received NAV. 00226 * 00227 * Called at end of rx 00228 */ 00229 void NotifyNavResetNow (Time duration); 00230 /** 00231 * \param duration the value of the received NAV. 00232 * 00233 * Called at end of rx 00234 */ 00235 void NotifyNavStartNow (Time duration); 00236 00237 private: 00238 void UpdateBackoff (void); 00239 Time MostRecent (Time a, Time b) const; 00240 Time MostRecent (Time a, Time b, Time c) const; 00241 Time MostRecent (Time a, Time b, Time c, Time d) const; 00242 /** 00243 * Access will never be granted to the medium _before_ 00244 * the time returned by this method. 00245 * 00246 * \returns the absolute time at which access could start to 00247 * be granted 00248 */ 00249 Time GetAccessGrantStart (void) const; 00250 Time GetBackoffStartFor (DcfState *state); 00251 Time GetBackoffEndFor (DcfState *state); 00252 void DoRestartAccessTimeoutIfNeeded (void); 00253 void AccessTimeout (void); 00254 void DoGrantAccess (void); 00255 bool IsBusy (void) const; 00256 00257 typedef std::vector<DcfState *> States; 00258 00259 States m_states; 00260 Time m_lastNavStart; 00261 Time m_lastNavDuration; 00262 Time m_lastRxStart; 00263 Time m_lastRxDuration; 00264 bool m_lastRxReceivedOk; 00265 Time m_lastRxEnd; 00266 Time m_lastTxStart; 00267 Time m_lastTxDuration; 00268 Time m_lastBusyStart; 00269 Time m_lastBusyDuration; 00270 bool m_rxing; 00271 bool m_sleeping; 00272 Time m_eifsNoDifs; 00273 EventId m_accessTimeout; 00274 Time m_slotTime; 00275 Time m_sifs; 00276 class PhyListener *m_phyListener; 00277 class LowNavListener *m_lowListener; 00278 }; 00279 00280 } // namespace ns3