[Ns-developers] a new 802.11 PHY and MAC

Mathieu Lacage Mathieu.Lacage at sophia.inria.fr
Fri Mar 25 00:18:03 PST 2005


hi,

For the past 4 weeks, I have been working on a new 802.11 PHY and MAC
for ns-2. These new layers are currently implemented as an addon to ns-2
and require very little modifications to the existing codebase. This
means that existing simulations using the current 802.11 layer of ns-2
will work unmodified.

An old design document which describes quickly a few ideas on this code
is attached to this email. Of course, the real code is slightly
different so, don't take that document very seriously.

http://www-sop.inria.fr/dream/personnel/Mathieu.Lacage/ns2/80211.tar.gz

The current code is distributed under the GPLv2. I will change this to
whatever license is deemed preferable for inclusion in ns2.

The current code contains:
  - mostly untested but should be working 802.11 PHY
  - code to simulate different modulation/FEC types
  - code to handle different rate control algorithms

The MAC you can find in this code is still a work in progress which
means that it does not work, is not expected to work and will change.
Every file is pretty heavily commented so I expect the codebase to be
rather easy to review.

Comments are welcome.

regards,
Mathieu
-- 
-------------- next part --------------
The architecture of the whole thing is:

---------- MAC ---------
| MAC-high --> MAC-low | --> PHY  <--> PHY ...
------------------------

The MAC is a single ns2 object which handles everything associated
with 802.11 MAC. It is implemented by two objects:
* The high-level MAC handles association, disassociation, aso...
* The low-level MAC contains a queue of packets to send and 
  handles per-packet transmission and deals with:
    - RTS/CTS
    - ACK
    - fragmentation
The PHY deals with:
    - packet corruption
    - store event history necessary for lazy event scheduling.

If you want to implement 802.11e, you would use multiple low-level
MAC instances to talk to a single PHY. For example:

---------- MAC ---------
|          |> MAC-low1 | 
|          |> MAC-low2 | 
| MAC-high |> MAC-low3 | --> PHY <--> PHY
|          |> MAC-low4 | 
------------------------

Each of the MAC-lowX instance contains the packet queue associated to
their Access Category.
-------------------------------------------------------------------------

The Phy implements a relatively simplistic model for transmission 
interference. It is based on the assumption that the SNR of a received
packet is equal to the SNIR: SNR = S / (Nf + Ni) where S is the energy of
received signal, Nf is the noise floor of the receiver and Ni is the 
interference noise.

S is calculated by using a propagation model for the transmission medium
which calculates the attenuation based on the transmission power and the 
distance between the transmitter and receiver.

Nf depends on the receiving circuitry and the bandwidth of the received
signal. It is calculated with the following formula (at 60 degree 
farenheit):
Nf = (BOLTZMANN * 290.0 * bandwidth) * (circuitNoise / 10)^10
circuitNoise is a constant whose value depends on the receiver circuitry.
bandwidth is the half-bandwidth of the received signal.

Ni is the sum of the energy of all the other signals being received at
the instant where the SNR is calculated for a given signal.

It is possible to start receiving a signal (this does not mean that it
will really be successfully received) if:
- its energy is higher than the "receiving threshold" which we denote
  by the rxThreshold variable.
- no other signal whose energy is higher than rxThreshold is already
  being received.

-------------------------------------------------------------------------
The Phy layer has two state machines:
- the CCA state machine. The meaning of the CCA states depends on the
  CCA mode which is why it is decoupled from the internal state machine.
  - CCA_IDLE
  - CCA_BUSY
- its internal state machine
  - PHY_RX: if a signal is being received with an energy higher than
    rxThreshold.
  - PHY_TX
  - PHY_IDLE: if no signal is being transmitted or received with an 
    energy higher than rxThreshold.
  - PHY_SLEEP

The MAC layer has one state machine:
- MAC_IDLE
- MAC_SLEEP
- MAC_WAIT_CTS
- MAC_WAIT_ACK
- MAC_FRAGMENT_WAIT_ACK

-------------------------------------------------------------------------

When a packet is received at the phy layer, we:
- if state is PHY_RX or PHY_TX, we put this new packet in the history list.
- otherwise, if state is PHY_SLEEP, we just ignore the packet.
- otherwise, if state is PHY_IDLE, and if the energy of the new packet is 
  lower than the rxThreshold we put it in the history list.
- otherwise, if the state is PHY_IDLE and if its energy is higher
  than rxThreshold,
    - put it in the history list
    - schedule a rxCompleted event at the calculated end of reception 
      of this packet.
    - switch to PHY_RX state.

When a rxCompleted event occurs in the PHY layer, we:
- parse the history list to calculate the maximum total energy
  of all the signals received during the reception of this packet
  (i.e., the maximum Ni)
- use this maximum total energy to calculate a minimum SNIR over
  the reception of this packet.
- use the modulation/encoding scheme of this packet to calculate a drop
  criterion. 
- If the packet must be dropped, it is marked so. 
- We pass it to the MAC layer.
- switch to PHY_IDLE state.

When the MAC layer receives a packet from the PHY, we:
- update the NAV
- if the packet received is an ACK, we:
  - update the status of the previous transmission
  - notify the rate control algorithms
  - cancel the ACKTimeout event
- if the packet received is an ACK but not a fragment ACK, we:
  - start a backoff
- if the packet received is a RTS,
  - schedule a txCTS event for current+SIFS
- if the packet received is a CTS and if we are currently
  handling an RTS/CTS exchange,
  - schedule a txData event for current+SIFS
- if the packet received is a data (or fragment) packet,
  - schedule a txACK event for current+SIFS
  
When the MAC layer receives a txACK event, we:
- send the ACK packet to the PHY, regardless of the IDLE/BUSY status

When the MAC layer receives a txCTS event, we:
- if the state is IDLE (i.e., if the NAV indicates IDLE), 
  send the CTS packet to the PHY.
  
When the PHY receives a packet from the MAC,
- switch to PHY_TX state
- the packet is put in the history list.
- it is sent to the phy layers connected to this phy layer.

When the MAC layer needs to send a data packet to another MAC layer, we:
- parse the history list to calculate:
  - if the current CCA status is IDLE
  - if it is IDLE, how long it has been IDLE
  - if the last packet received was erronous or not.
- if the current CS is not IDLE, and if backoff is zero, we 
  restart a backoff.
- otherwise, if the current CS was not IDLE for longer than the 
  requested IFS (XIFS = EIFS if last packet received erronous, 
  DIFS otherwise), we schedule an event for current+XIFS.
- otherwise, if the backoff timer is zero, and if the packet
  requires RTS/CTS, we send a RTS to the phy layer and
  start a CTSTimeout event.
- otherwise, if the backoff time is zero and if the packet
  does not require an RTS/CTS, we send the packet to the phy layer
  and start an ACKTimeout event.
- otherwise, if the backoff timer is not zero, we schedule an event
  for the end of the backoff timer.
  
When the MAC layer receives a backoff timer event, we:
- parse the phy layer history list to calculate:
  - how long since the start of this backoff timer the
    CS (virtual+phy) was IDLE = CS_BUSY
  - how many times it switched from IDLE to BUSY.
- if the CS_BUSY is not zero, we restart a backoff timer
  to CS_BUSY.
- if the CS_BUSY is zero, the backoff has really expired
  so:
    - if the packet requires RTS/CTS, we send RTS and start a
      CTSTimeout.
    - if the packet does not require RTS/CTS, we send the
      data and start an ACKTimeout.
- we remove from the history list any event which has expired.

When the MAC layer receives an ACKTimeout event, we:
- start a backoff.
- notify the rate control algorithms

When the MAC layer receives a CTSTimeout event, we:
- start a backoff.
- notify the rate control algorithms

When the PHY layer receives a packet to tx, we:
- add an event in its phy event list
- send the packet to the other PHY connected to this PHY.

When the MAC layer receives a GC event, we:
- remove from the history list any event which has expired
  before current-(EIFS+255*aSlotTime).
- schedule another GC event sometime later.

-------------------------------------------------------------------------

Interesting remarks:
--------------------

1) a MAC (low-level) only needs to send a single data packet at
   a time, maybe with small fragments but only one packet/fragment
   is ever sent at a time.

2) the history list maintained by the PHY layer grows upon each event
   deemed necessary. Of course, there need to be a way to remove items
   form the list to make sure it does not grow infinitely.
   There are two events which can remove items from the list:
   - backoff timeout events should be used to remove any event whose
     end time is smaller than the current.
   - a special "garbage collection" event should be regularly scheduled
     to remove any event too old to be useful from the history list.
     This is necessary if the station does not tx any data (which means
     it would not trigger _any_ backoff timeout).

3) rxThreshold is understood to be the minimum signal energy required by 
   the receiver to be able to lock onto a receiving signal.

4) The Phy layer does not need to always update its internal state. It 
   merely need to record every event in its history list and recompute
   its state from the history list whenever needed. Specifically,
   this should avoid a txCompleted event in the PHY layer.

5) This scheme which moves the MAC queue into the MAC object is clearly
   against the ns2 philosophy and way of doing things but it is necessary
   to be able to correctly implement the specification (for example, see
   section 9.9.1.6 paragraph 6 of the 802.11e/D9 spec). This means that:
     - the ns2 input queue do the MAC object will have a size of zero.
     - there will be a need for some elaborate (read: evil) code in the 
       MAC object to obtain the packets and queue them in the MAC-low 
       objects.

6) OAR is available in 802.11e/D9: see section 9.9.1.4

7) To ensure that when the backoff timeout of two ACs (Access Categories)
   expire at the same time, the one with the highest UP (User Priority)
   wins (gains access to the medium), we need to get the MAC-low to ask
   their MAC-high which in turn asks every other MAC-low whether or not
   another backoff timeout is going to expire NOW and if their priority 
   is higher.

8) the wwise proposal for 802.11n does not really change the MAC in 
   fundamental ways. It merely adds frame aggregation which might be 
   a bit tricky to implement but should not require major reworks.

9) the tgnsync proposal for 802.11n changes the MAC in fundamental ways
   which will probably require a complete re-implementation of the 
   MAC-low. It might be possible to save part of the existing MAC-high
   but there is no way to know beforehand. Most notably:
   - pairwise spoofing requires elaborate duration calculations by
     the MAC.
   - LongNAV spoofing also requires elaborate duration calculations
     by the MAC.
   - rate control is fundamentaly different since it is possible to
     create something similar to RBAR.
   - packet agregation
   - ...

10) MCCA should be reasonably easy to implement within an existing 
    802.11e implementation. It looks furiously like the other 802.11n
    proposals though...



-------------------------------------------------------------------------

Open issues:

1) How do we evaluate the rxThreshold ? Should we set a simulation-wide
   constant ? Should this depend on the receiver circuitry ?

2) How do you deal with multi-protocol PHYs ? i.e., 802.11g. It is
   really really hard so I would suggest we support only 802.11a and 
   802.11b. Maybe we can. I don't know now.


More information about the Ns-developers mailing list