From d072cdd5275794fcaa5f00d697e797670d34203a Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Wed, 31 Oct 2007 16:26:31 +0100 Subject: [PATCH] doxygen --- src/devices/wifi/aarf-mac-stations.h | 8 + src/devices/wifi/arf-mac-stations.h | 14 ++ src/devices/wifi/cr-mac-stations.h | 6 + src/devices/wifi/dca-txop.h | 42 +++++ src/devices/wifi/dcf.h | 131 ++++++++++++++- src/devices/wifi/ideal-mac-stations.h | 14 ++ src/devices/wifi/mac-low.h | 224 +++++++++++++++++++++++--- src/devices/wifi/wifi-mac-queue.h | 35 ++-- src/devices/wifi/wifi-net-device.h | 6 + src/devices/wifi/wifi.h | 29 +++- 10 files changed, 451 insertions(+), 58 deletions(-) diff --git a/src/devices/wifi/aarf-mac-stations.h b/src/devices/wifi/aarf-mac-stations.h index ceae5da16..f5e9c2dce 100644 --- a/src/devices/wifi/aarf-mac-stations.h +++ b/src/devices/wifi/aarf-mac-stations.h @@ -24,6 +24,14 @@ namespace ns3 { +/** + * \brief AARF Rate control algorithm + * + * This class implements the AARF rate control algorithm which + * was initially described in IEEE 802.11 Rate Adaptation: + * A Practical Approach, by M. Lacage, M.H. Manshaei, and + * T. Turletti. + */ class AarfMacStations : public ArfMacStations { public: AarfMacStations (WifiMode defaultTxMode, diff --git a/src/devices/wifi/arf-mac-stations.h b/src/devices/wifi/arf-mac-stations.h index b75f1cf2a..8325a1138 100644 --- a/src/devices/wifi/arf-mac-stations.h +++ b/src/devices/wifi/arf-mac-stations.h @@ -24,6 +24,20 @@ namespace ns3 { +/** + * \brief ARF Rate control algorithm + * + * This class implements the so-called ARF algorithm which was + * initially described in WaveLAN-II: A High-performance wireless + * LAN for the unlicensed band, by A. Kamerman and L. Monteban. in + * Bell Lab Technical Journal, pages 118-133, Summer 1997. + * + * This implementation differs from the initial description in that it + * uses a packet-based timer rather than a time-based timer as described + * in XXX (I cannot find back the original paper which described how + * the time-based timer could be easily replaced with a packet-based + * timer.) + */ class ArfMacStations : public MacStations { public: ArfMacStations (WifiMode defaultTxMode, uint32_t timerThreshold, uint32_t successThreshold); diff --git a/src/devices/wifi/cr-mac-stations.h b/src/devices/wifi/cr-mac-stations.h index a9e417c51..9337d8bbe 100644 --- a/src/devices/wifi/cr-mac-stations.h +++ b/src/devices/wifi/cr-mac-stations.h @@ -26,6 +26,12 @@ namespace ns3 { +/** + * \brief use constant rates for data and control transmissions + * + * This class uses always the same transmission rate for every + * packet sent. + */ class CrMacStations : public MacStations { public: diff --git a/src/devices/wifi/dca-txop.h b/src/devices/wifi/dca-txop.h index a4e3cf07f..63f97de31 100644 --- a/src/devices/wifi/dca-txop.h +++ b/src/devices/wifi/dca-txop.h @@ -38,12 +38,39 @@ class WifiPhy; class MacParameters; class MacTxMiddle; +/** + * \brief handle packet fragmentation and retransmissions. + * + * This class implements the packet fragmentation and + * retransmission policy. It uses the ns3::MacLow and ns3::Dcf + * helper classes to respectively send packets and decide when + * to send them. Packets are stored in a ns3::WifiMacQueue until + * they can be sent. + * + * The policy currently implemented uses a simple fragmentation + * threshold: any packet bigger than this threshold is fragmented + * in fragments whose size is smaller than the threshold. + * + * The retransmission policy is also very simple: every packet is + * retransmitted until it is either successfully transmitted or + * it has been retransmitted up until the ssrc or slrc thresholds. + * + * The rts/cts policy is similar to the fragmentation policy: when + * a packet is bigger than a threshold, the rts/cts protocol is used. + */ class DcaTxop { public: typedef Callback TxOk; typedef Callback TxFailed; + /** + * \param minCw forwarded to ns3::Dcf constructor + * \param maxCw forwarded to ns3::Dcf constructor + * + * Initialized from \valueref{WifiMaxSsrc}, \valueref{WifiMaxSlrc}, + * \valueref{WifiRtsCtsThreshold}, and, \valueref{WifiFragmentationThreshold}. + */ DcaTxop (uint32_t minCw, uint32_t maxCw); ~DcaTxop (); @@ -51,7 +78,15 @@ public: void SetPhy (Ptr phy); void SetParameters (MacParameters *parameters); void SetTxMiddle (MacTxMiddle *txMiddle); + /** + * \param callback the callback to invoke when a + * packet transmission was completed successfully. + */ void SetTxOkCallback (TxOk callback); + /** + * \param callback the callback to invoke when a + * packet transmission was completed unsuccessfully. + */ void SetTxFailedCallback (TxFailed callback); void SetDifs (Time difs); @@ -60,6 +95,13 @@ public: void SetMaxQueueSize (uint32_t size); void SetMaxQueueDelay (Time delay); + /** + * \param packet packet to send + * \param hdr header of packet to send. + * + * Store the packet in the internal queue until it + * can be sent safely. + */ void Queue (Packet packet, WifiMacHeader const &hdr); private: class AccessListener; diff --git a/src/devices/wifi/dcf.h b/src/devices/wifi/dcf.h index ae169f5cf..2c46c3776 100644 --- a/src/devices/wifi/dcf.h +++ b/src/devices/wifi/dcf.h @@ -31,56 +31,177 @@ namespace ns3 { class RandomStream; class MacParameters; +/** + * \brief listen to DCF events + * + * If you want to call methods from the ns3::Dcf class, + * you need to provide an instance of this class + * to be notified of the DCF evens. + */ class DcfAccessListener { public: DcfAccessListener (); virtual ~DcfAccessListener (); - /* Tell the listener than it can start + /** + * Tell the listener than it can start * accessing the medium right now. */ virtual void AccessGrantedNow (void) = 0; - /* ask the listener if there are candidates + /** + * ask the listener if there are candidates * who need access to the medium. + * + * \return true if access to the medium is + * needed, false otherwise. */ virtual bool AccessNeeded (void) = 0; - /* ask the listener if it is currently + /** + * ask the listener if it is currently * performing an access which was granted * earlier to him and if it will notify * the Dcf when the access is complete. + * + * \return true if the listener expects to call + * Dcf::RequestAccess later, false otherwise. */ virtual bool AccessingAndWillNotify (void) = 0; }; +/** + * \brief the Distributed Coordination Function + * + * This class implements the DCF as described in IEEE 802.11-1999 + * section 9.2, p72. + * + * This implementation is based on the technique described in + * Scalable simulation of large-scale wireless networks with + * bounded inaccuracies., by Z. Ji, J. Zhou, M. Takai, and R. Bagrodia. + */ class Dcf { public: + /** + * \param minCw the minimum value for CW + * \param maxCW the maximum value for CW + */ Dcf (uint32_t minCw, uint32_t maxCw); ~Dcf (); + /** + * \param parameters + * + * Must be invoked after construction to configure + * a set of parameters. + */ void SetParameters (const MacParameters *parameters); + /** + * \param difs the difs + * + * Must be invoked after construction. + */ void SetDifs (Time difs); + /** + * \param eifs the eifs + * + * Must be invoked after construction. + */ void SetEifs (Time eifs); + /** + * \param minCw the minimum value for CW + * \param maxCw the maximum value for CW + * + * Reset the cw bounds and CW to minCW. + */ void SetCwBounds (uint32_t minCw, uint32_t maxCw); + /** + * \param listener the listener + * + * This listener is notified of DCF-specific events + * when they happen. You _must_ register a listener + * before calling Dcf::RequestAccess. + */ void RegisterAccessListener (DcfAccessListener *listener); + /** + * Request access to the medium. This method will grant + * access by calling the DcfAccessListener::AccessGrantedNow + * method + */ void RequestAccess (void); + /** + * Reset the CW to CWmin + * This method is typically invoked after a successfully + * transmission or after the maximum number of retries has + * been reached. + */ void ResetCw (void); + /** + * Update the CW to a new value. This method is typically + * invoked after a failed transmission before calling + * Dcf::StartBackoff. + */ void UpdateFailedCw (void); + /** + * Start a backoff now by picking a backoff duration + * in the [0, cw] interval. + */ void StartBackoff (void); - /* notification methods. */ + /** + * \param duration expected duration of reception + * + * Notify the DCF that a packet reception started + * for the expected duration. + */ void NotifyRxStartNow (Time duration); + /** + * Notify the DCF that a packet reception was just + * completed successfully. + */ void NotifyRxEndOkNow (void); + /** + * Notify the DCF that a packet reception was just + * completed unsuccessfully. + */ void NotifyRxEndErrorNow (void); + /** + * \param duration expected duration of transmission + * + * Notify the DCF that a packet transmission was + * just started and is expected to last for the specified + * duration. + */ void NotifyTxStartNow (Time duration); + /** + * \param duration expected duration of cca busy period + * + * Notify the DCF that a CCA busy period has just started. + */ void NotifyCcaBusyStartNow (Time duration); + /** + * \param now the time at which a NAV starts + * \param duration the value of the received NAV. + */ void NotifyNavReset (Time now, Time duration); + /** + * \param now the time at which a NAV starts + * \param duration the value of the received NAV. + */ void NotifyNavStart (Time now, Time duration); + /** + * \param now the time at which a NAV starts + * \param duration the value of the received NAV. + */ void NotifyNavContinue (Time now, Time duration); - // for testing only. + /** + * \param stream a random stream + * + * This method is used for testing only to force a predictable + * set of random numbers to be used. + */ void ResetRngForTest (RandomStream *stream); private: void AccessTimeout (void); diff --git a/src/devices/wifi/ideal-mac-stations.h b/src/devices/wifi/ideal-mac-stations.h index 9dd2c0a4b..e0deb8dce 100644 --- a/src/devices/wifi/ideal-mac-stations.h +++ b/src/devices/wifi/ideal-mac-stations.h @@ -27,6 +27,20 @@ namespace ns3 { +/** + * \brief Ideal rate control algorithm + * + * This class implements an 'ideal' rate control algorithm + * similar to RBAR in spirit (see A rate-adaptive MAC + * protocol for multihop wireless networks by G. Holland, + * N. Vaidya, and P. Bahl.): every station keeps track of the + * snr of every packet received and sends back this snr to the + * original transmitter by an out-of-band mechanism. Each + * transmitter keeps track of the last snr sent back by a receiver + * and uses it to pick a transmission mode based on a set + * of snr thresholds built from a target ber and transmission + * mode-specific snr/ber curves. + */ class IdealMacStations : public MacStations { public: IdealMacStations (WifiMode defaultTxMode); diff --git a/src/devices/wifi/mac-low.h b/src/devices/wifi/mac-low.h index aa0948d31..55c4afc65 100644 --- a/src/devices/wifi/mac-low.h +++ b/src/devices/wifi/mac-low.h @@ -42,93 +42,223 @@ class MacStations; class MacStation; class MacParameters; +/** + * \brief listen to events coming from ns3::MacLow. + */ class MacLowTransmissionListener { public: MacLowTransmissionListener (); virtual ~MacLowTransmissionListener (); + /** + * \param snr the snr of the cts + * \param txMode the txMode of the cts + * + * ns3::MacLow received an expected CTS within + * CtsTimeout. + */ virtual void GotCts (double snr, WifiMode txMode) = 0; + /** + * ns3::MacLow did not receive an expected CTS + * within CtsTimeout. + */ virtual void MissedCts (void) = 0; - /* Do not rely on the gotAck method to be - * given valid parameters when SuperFastAck is - * enabled. + /** + * \param snr the snr of the ack + * \param txMode the transmission mode of the ack + * + * ns3::MacLow received an expected ACL within + * AckTimeout. The snr and txMode + * arguments are not valid when SUPER_FAST_ACK is + * used. */ virtual void GotAck (double snr, WifiMode txMode) = 0; + /** + * ns3::MacLow did not receive an expected ACK within + * AckTimeout. + */ virtual void MissedAck (void) = 0; + /** + * Invoked when ns3::MacLow wants to start a new transmission + * as configured by MacLowTransmissionParameters::EnableNextData. + * The listener is expected to call again MacLow::StartTransmission + * with the "next" data to send. + */ virtual void StartNext (void) = 0; - /* Invoked if this transmission was canceled + /** + * Invoked if this transmission was canceled * one way or another. When this method is invoked, * you can assume that the packet has not been passed - * down the stack to the PHY. You are responsible - * for freeing the packet if you want to. + * down the stack to the PHY. */ virtual void Cancel (void) = 0; }; +/** + * \brief listen to NAV events + * + * This class is typically connected to an instance of ns3::Dcf + * and calls to its methods are forwards to the corresponding + * ns3::Dcf methods. + */ class MacLowNavListener { public: MacLowNavListener (); virtual ~MacLowNavListener (); + /** + * \param now start of NAV timer + * \param duration duration of NAV timer + */ virtual void NavStart (Time now, Time duration) = 0; + /** + * \param now start of NAV timer + * \param duration duration of NAV timer + */ virtual void NavContinue (Time now, Time duration) = 0; + /** + * \param now start of NAV timer + * \param duration duration of NAV timer + */ virtual void NavReset (Time now, Time duration) = 0; }; +/** + * \brief control how a packet is transmitted. + * + * The ns3::MacLow::StartTransmission method expects + * an instance of this class to describe how the packet + * should be transmitted. + */ class MacLowTransmissionParameters { public: MacLowTransmissionParameters (); - /* If ACK is enabled, we wait ACKTimeout for an ACK. + /** + * Wait ACKTimeout for an ACK. If we get an ACK + * on time, call MacLowTransmissionListener::GotAck. + * Call MacLowTransmissionListener::MissedAck otherwise. */ void EnableAck (void); - /* If FastAck is enabled, we: - * - wait PIFS after end-of-tx. If idle, report - * FastAckMissed. + /** + * - wait PIFS after end-of-tx. If idle, call + * MacLowTransmissionListener::MissedAck. * - if busy at end-of-tx+PIFS, wait end-of-rx - * - if Ack ok at end-of-rx, report FastAck ok. - * - if Ack not ok at end-of-rx, report FastAckMissed + * - if Ack ok at end-of-rx, call + * MacLowTransmissionListener::GotAck. + * - if Ack not ok at end-of-rx, report call + * MacLowTransmissionListener::MissedAck * at end-of-rx+SIFS. + * * This is really complicated but it is needed for * proper HCCA support. */ void EnableFastAck (void); - /* If SuperFastAck is enabled, we: - * - if busy at end-of-tx+PIFS, report gotAck - * - if idle at end-of-tx+PIFS, report missedAck + /** + * - if busy at end-of-tx+PIFS, call + * MacLowTransmissionListener::GotAck + * - if idle at end-of-tx+PIFS, call + * MacLowTransmissionListener::MissedAck */ void EnableSuperFastAck (void); - /* If RTS is enabled, we wait CTSTimeout for a CTS. - * Otherwise, no RTS is sent. + /** + * Send a RTS, and wait CTSTimeout for a CTS. If we get a + * CTS on time, call MacLowTransmissionListener::GotCts + * and send data. Otherwise, call MacLowTransmissionListener::MissedCts + * and do not send data. */ void EnableRts (void); - /* If NextData is enabled, we add the transmission duration - * of the nextData to the durationId and we notify the - * transmissionListener at the end of the current - * transmission + SIFS. + /** + * \param size size of next data to send after current packet is + * sent. + * + * Add the transmission duration of the next data to the + * durationId of the outgoing packet and call + * MacLowTransmissionListener::StartNext at the end of + * the current transmission + SIFS. */ void EnableNextData (uint32_t size); - /* If we enable this, we ignore all other durationId - * calculation and simply force the packet's durationId - * field to this value. + /** + * \param durationId the value to set in the duration/Id field of + * the outgoing packet. + * + * Ignore all other durationId calculation and simply force the + * packet's durationId field to this value. */ void EnableOverrideDurationId (Time durationId); + /** + * Do not wait for Ack after data transmission. Typically + * used for Broadcast and multicast frames. + */ void DisableAck (void); + /** + * Do not send rts and wait for cts before sending data. + */ void DisableRts (void); + /** + * Do not attempt to send data burst after current transmission + */ void DisableNextData (void); + /** + * Do not force the duration/id field of the packet: its + * value is automatically calculated by the MacLow before + * calling WifiPhy::Send. + */ void DisableOverrideDurationId (void); + /** + * \returns true if must wait for ACK after data transmission, + * false otherwise. + * + * This methods returns true when any of MustWaitNormalAck, + * MustWaitFastAck, or MustWaitSuperFastAck return true. + */ bool MustWaitAck (void) const; + /** + * \returns true if normal ACK protocol should be used, false + * otherwise. + * + * \sa EnableAck + */ bool MustWaitNormalAck (void) const; + /** + * \returns true if fast ack protocol should be used, false + * otherwise. + * + * \sa EnableFastAck + */ bool MustWaitFastAck (void) const; + /** + * \returns true if super fast ack protocol should be used, false + * otherwise. + * + * \sa EnableSuperFastAck + */ bool MustWaitSuperFastAck (void) const; + /** + * \returns true if RTS should be sent and CTS waited for before + * sending data, false otherwise. + */ bool MustSendRts (void) const; + /** + * \returns true if a duration/id was forced with + * EnableOverrideDurationId, false otherwise. + */ bool HasDurationId (void) const; + /** + * \returns the duration/id forced by EnableOverrideDurationId + */ Time GetDurationId (void) const; + /** + * \returns true if EnableNextData was called, false otherwise. + */ bool HasNextPacket (void) const; + /** + * \returns the size specified by EnableNextData. + */ uint32_t GetNextPacketSize (void) const; private: @@ -144,6 +274,9 @@ private: }; +/** + * \brief handle RTS/CTS/DATA/ACK transactions. + */ class MacLow { public: typedef Callback MacLowRxCallback; @@ -155,23 +288,62 @@ public: void SetPhy (Ptr phy); void SetStations (MacStations *stations); void SetParameters (MacParameters *parameters); + /** + * \param callback the callback which receives every incoming packet. + * + * This callback typically forwards incoming packets to + * an instance of ns3::MacRxMiddle. + */ void SetRxCallback (MacLowRxCallback callback); + /** + * \param listener listen to NAV events for every incoming + * and outgoing packet. + */ void RegisterNavListener (MacLowNavListener *listener); - /* This transmission time includes the time required for + /** + * \param payloadSize size of packet to send (does not include the 802.11 MAC header and checksum) + * \param to destination address of packet. + * \param parameters transmission parameters of packet. + * + * This transmission time includes the time required for * the next packet transmission if one was selected. */ Time CalculateTransmissionTime (uint32_t payloadSize, Mac48Address to, MacLowTransmissionParameters const¶meters) const; - /* start the transmission of the currently-stored data. */ + /** + * \param packet packet to send + * \param hdr 802.11 header for packet to send + * \param parameters the transmission parameters to use for this packet. + * \param listener listen to transmission events. + * + * Start the transmission of the input packet and notify the listener + * of transmission events. + */ void StartTransmission (Packet packet, WifiMacHeader const*hdr, MacLowTransmissionParameters parameters, MacLowTransmissionListener *listener); + /** + * \param packet packet received + * \param rxSnr snr of packet received + * \param txMode transmission mode of packet received + * \param preamble type of preamble used for the packet received + * + * This method is typically invoked by the lower PHY layer to notify + * the MAC layer that a packet was successfully received. + */ void ReceiveOk (Packet packet, double rxSnr, WifiMode txMode, WifiPreamble preamble); + /** + * \param packet packet received. + * \param rxSnr snr of packet received. + * + * This method is typically invoked by the lower PHY layer to notify + * the MAC layer that a packet was unsuccessfully received. + */ void ReceiveError (Packet packet, double rxSnr); private: void CancelAllEvents (void); diff --git a/src/devices/wifi/wifi-mac-queue.h b/src/devices/wifi/wifi-mac-queue.h index 66ec4acf2..5def317e5 100644 --- a/src/devices/wifi/wifi-mac-queue.h +++ b/src/devices/wifi/wifi-mac-queue.h @@ -20,26 +20,6 @@ #ifndef WIFI_MAC_QUEUE_H #define WIFI_MAC_QUEUE_H -/* This queue implements what is needed for the 802.11e standard - * Specifically, it refers to 802.11e/D9, section 9.9.1.6, paragraph 6. - * - * When a packet is received by the MAC, to be sent to the PHY, - * it is queued in the internal queue after being tagged by the - * current time. If the queue is non-Empty (quite likely), we - * notify m_packetNotify. This information is forwarded to - * The associated MacLow80211 which might try to dequeue packets - * from this queue if it is not doing anything else more important. - * - * If it is doing something too important to handle new packets, - * the MacLow80211 is supposed to try to dequeue packets the next - * time it can. - * - * When a packet is dequeued, the queue checks its timestamp - * to verify whether or not it should be dropped. If - * dot11EDCATableMSDULifetime has elapsed, it is dropped. - * Otherwise, it is returned to the caller. - */ - #include #include #include "ns3/packet.h" @@ -50,6 +30,21 @@ namespace ns3 { class MacParameters; +/** + * \brief a 802.11e-specific queue. + * + * This queue implements what is needed for the 802.11e standard + * Specifically, it refers to 802.11e/D9, section 9.9.1.6, paragraph 6. + * + * When a packet is received by the MAC, to be sent to the PHY, + * it is queued in the internal queue after being tagged by the + * current time. + * + * When a packet is dequeued, the queue checks its timestamp + * to verify whether or not it should be dropped. If + * dot11EDCATableMSDULifetime has elapsed, it is dropped. + * Otherwise, it is returned to the caller. + */ class WifiMacQueue { public: WifiMacQueue (); diff --git a/src/devices/wifi/wifi-net-device.h b/src/devices/wifi/wifi-net-device.h index fba7b0ace..53ee3a38c 100644 --- a/src/devices/wifi/wifi-net-device.h +++ b/src/devices/wifi/wifi-net-device.h @@ -168,6 +168,9 @@ private: class NqstaWifiNetDevice : public WifiNetDevice { public: + /** + * The ssid is initialized from \valueref{WifiSsid}. + */ NqstaWifiNetDevice (Ptr node); virtual ~NqstaWifiNetDevice (); @@ -205,6 +208,9 @@ private: class NqapWifiNetDevice : public WifiNetDevice { public: + /** + * The ssid is initialized from \valueref{WifiSsid}. + */ NqapWifiNetDevice (Ptr node); virtual ~NqapWifiNetDevice (); diff --git a/src/devices/wifi/wifi.h b/src/devices/wifi/wifi.h index bda511f5a..c24a8952f 100644 --- a/src/devices/wifi/wifi.h +++ b/src/devices/wifi/wifi.h @@ -6,11 +6,13 @@ * and to provide a not-so-slow PHY-level model of the 802.11a * specification. * - * The current implementation provides roughly 3 levels of models: + * The current implementation provides roughly 4 levels of models: * - the PHY layer models * - the so-called MAC low models: they implement DCF * - the so-called MAC high models: they implement the MAC-level * beacon generation, probing, and association state machines. + * - a set of Rate control algorithms used by the MAC low models. + * * * We have today 3 MAC high models: * - a simple adhoc state machine which does not perform any @@ -24,13 +26,26 @@ * accepts every attempt to associate. This AP state machine * is implemented by the ns3::NqapWifiNetDevice. * - * The PHY layer implements the model described in - * "Yet Another Network Simulator", (http://cutebugs.net/files/wns2-yans.pdf) - * The implementation is located in the ns3::WifiPhy class. + * The MAC low layer is split in 3 components: + * - ns3::MacLow which takes care of RTS/CTS/DATA/ACK transactions. + * - ns3::Dcf which implements the DCF function. + * - ns3::DcaTxop which handles the packet queue, packet fragmentation, + * and packet retransmissions if they are needed. + * + * The PHY layer implements a single model in ns3::WifiPhy. + * + * It also provides a set of Rate control algorithms: + * - ns3::ArfMacStations (initialized from \valueref{WifiArfTimerThreshold}, and, + * \valueref{WifiArfSuccessThreshold}) + * - ns3::AArfMacStations (initialized from \valueref{WifiAarfMinSuccessThreshold}, + * \valueref{WifiAarfMinTimerThreshold}, \valueref{WifiAarfSuccessK}, + * \valueref{WifiAarfMaxSuccessThreshold}, and, \valueref{WifiAarfTimerK} + * - ns3::IdealMacStations (initialized from \valueref{WifiIdealRateControlBerThreshold}) + * - ns3::CrMacStations (initialized from \valueref{WifiConstantDataRate}, and, + * \valueref{WifiConstantCtlRate}). + * + * The type of rate control algorithm is controlled through \valueref{WifiRateControlAlgorithm}. * - * The MAC low models attempt to implement the 802.11 DCF function - * in an optimized way through the technique described in XXX. - * This implementation is located in the ns3::Dcf class. * * \section Wifi Tutorial *