Mininet + NS3 for SDN and WIFI simulations

 

QoS Example:

 

h1(192.168.0.1)--wireless link (802.11e EDCF supported)--s0 ( AP + open vswitch)--wired link--h3(192.168.0.3)

h2 (192.168.0.2)--wireless link(802.11e EDCF supported)--

 

Prerequistes

1. virtual machine: download (This work is based on https://github.com/mininet/mininet/wiki/Link-modeling-using-ns-3 . I have added the  lxde  for graphical mode operation. I also added some examples under /home/mininet/examples/ns3 for SDN and WIFI simulations. Please download the ova file. You can useVirtualBox: Import Appliance or Vmware  to use this  vm. Note: when you have downloaded the mininet-ns3.ova.rar, please directly change the file name to mininet-ns3.ova.)

2. Change the wifi source codes in ns-allinone-3.17 to support the mapping of ToS field in the IP header to the IEEE 802.11 qos tag in the MAC header.

ToS

Access Category

0

AC_BE

1

AC_BK

2

AC_BK

3

AC_BE

4

AC_VI

5

AC_VI

6

AC_VO

7

AC_VO

 

2.1 go to ~/ns-allinone-3.17/ns-3.17/src/wifi/model directory and open sta-wifi-mac.cc. (add the red lines in the corresponding places.)

void

StaWifiMac::Enqueue (Ptr<const Packet> packet, Mac48Address to)

{

  NS_LOG_FUNCTION (this << packet << to);

  if (!IsAssociated ())

    {

      NotifyTxDrop (packet);

      TryToEnsureAssociated ();

      return;

    }

  WifiMacHeader hdr;

 

  Ptr<Packet> q = packet->Copy();

  uint8_t const *mydata=q->PeekData();

  uint8_t tos = 0;

  if(mydata[8]==69)

    tos = mydata[9];

 

  // If we are not a QoS AP then we definitely want to use AC_BE to

  // transmit the packet. A TID of zero will map to AC_BE (through \c

  // QosUtilsMapTidToAc()), so we use that as our default here.

  uint8_t tid = 0;

 

  // For now, an AP that supports QoS does not support non-QoS

  // associations, and vice versa. In future the AP model should

  // support simultaneously associated QoS and non-QoS STAs, at which

  // point there will need to be per-association QoS state maintained

  // by the association state machine, and consulted here.

  if (m_qosSupported)

    {

      hdr.SetType (WIFI_MAC_QOSDATA);

      hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);

      hdr.SetQosNoEosp ();

      hdr.SetQosNoAmsdu ();

      // Transmission of multiple frames in the same TXOP is not

      // supported for now

      hdr.SetQosTxopLimit (0);

 

      // Fill in the QoS control field in the MAC header

      tid = QosUtilsGetTidForPacket (packet);

 

      // Any value greater than 7 is invalid and likely indicates that

      // the packet had no QoS tag, so we revert to zero, which'll

      // mean that AC_BE is used.

      if (tid >= 7)

        {

          tid = 0;

        }

 

      //added by smallko

      if (tos > 7 || tos <=0)

        tid = 0;

      else

        tid = tos;

    

      //printf("StaWifiMac::Enqueue, tid=%d\n", tid);

      hdr.SetQosTid (tid);

    }

  else

    {

      hdr.SetTypeData ();

    }

 

  hdr.SetAddr1 (GetBssid ());

  hdr.SetAddr2 (m_low->GetAddress ());

  hdr.SetAddr3 (to);

  hdr.SetDsNotFrom ();

  hdr.SetDsTo ();

 

  if (m_qosSupported)

    {

      // Sanity check that the TID is valid

      NS_ASSERT (tid < 8);

      m_edca[QosUtilsMapTidToAc (tid)]->Queue (packet, hdr);

    }

  else

    {

      m_dca->Queue (packet, hdr);

    }

}

 

2.2 go to ~/ns-allinone-3.17/ns-3.17/src/wifi/model directory and open ap-wifi-mac.cc. (add the red lines in the corresponding places.)

void

ApWifiMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from,

                        Mac48Address to, uint8_t tid)

{

  NS_LOG_FUNCTION (this << packet << from << to << static_cast<uint32_t> (tid));

  WifiMacHeader hdr;

 

  // For now, an AP that supports QoS does not support non-QoS

  // associations, and vice versa. In future the AP model should

  // support simultaneously associated QoS and non-QoS STAs, at which

  // point there will need to be per-association QoS state maintained

  // by the association state machine, and consulted here.

 

  Ptr<Packet> q = packet->Copy();

  uint8_t const *mydata=q->PeekData();

  uint8_t tos = 0;

  if(mydata[8]==69)

    tos = mydata[9];

 

  if (tos > 7 || tos <=0)

    tid = 0;

  else

    tid = tos;

 

  if (m_qosSupported)

    {

      hdr.SetType (WIFI_MAC_QOSDATA);

      hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);

      hdr.SetQosNoEosp ();

      hdr.SetQosNoAmsdu ();

      // Transmission of multiple frames in the same TXOP is not

      // supported for now

      hdr.SetQosTxopLimit (0);

      // Fill in the QoS control field in the MAC header

      //printf("ApWifiMac::ForwardDown, tid=%d\n", tid);

      hdr.SetQosTid (tid);

    }

  else

    {

      hdr.SetTypeData ();

    }

 

  hdr.SetAddr1 (to);

  hdr.SetAddr2 (GetAddress ());

  hdr.SetAddr3 (from);

  hdr.SetDsFrom ();

  hdr.SetDsNotTo ();

 

  if (m_qosSupported)

    {

      // Sanity check that the TID is valid

      NS_ASSERT (tid < 8);

      m_edca[QosUtilsMapTidToAc (tid)]->Queue (packet, hdr);

    }

  else

    {

      m_dca->Queue (packet, hdr);

    }

}

2.3 recompile ns3. go to ns-allinone-3.17/ns-3.17 and type "./waf" to recompile.

3. Change the ns3.py setting.

3.1 go to ~/mininet/mininet and open ns3.py

class WIFISegment( object ):

    """Equivalent of radio WiFi channel.

       Only Ap and WDS devices support SendFrom()."""

    def __init__( self ):

        # Helpers instantiation.

        self.channelhelper = ns.wifi.YansWifiChannelHelper.Default()

        self.phyhelper = ns.wifi.YansWifiPhyHelper.Default()

        self.wifihelper = ns.wifi.WifiHelper.Default()

        #self.machelper = ns.wifi.NqosWifiMacHelper.Default()

        self.machelper = ns.wifi.QosWifiMacHelper.Default()

........................................................................................................

3.2 recompile mininet

go to ~/mininet and type "sudo make install" to recompile mininet

 

Usage:

1. Put the following file (test-wifi5.py) under ~/mininet/example/ns3

import rlcompleter

import readline

 

import time

 

from mininet.net import Mininet

from mininet.node import Node, Switch

from mininet.link import Link, Intf

from mininet.log import setLogLevel, info

from mininet.cli import CLI

 

import mininet.ns3

from mininet.ns3 import WIFISegment

from mininet.node import OVSController

from mininet.link import TCLink

 

import ns.wifi

 

readline.parse_and_bind("tab: complete")

 

if __name__ == '__main__':

    setLogLevel( 'info' )

 

    net = Mininet( controller=OVSController )

    c0 = net.addController( 'c0' )

 

    info( '*** Adding hosts\n' )

    h1 = net.addHost( 'h1', ip='192.168.0.1' )

    h2 = net.addHost( 'h2', ip='192.168.0.2' )

    h3 = net.addHost( 'h3', ip='192.168.0.3' )

 

    info( '*** Adding switch\n' )

    s0 = net.addSwitch( 's0' )

    s0.listenPort = 6634

    c0.start()

    s0.start( [c0] )

    linkopts=dict( bw=100, delay='1ms', loss=0 )

    TCLink( s0, h3, **linkopts )

     

    #net.hosts.append( s0 )

    net.hosts.append( h1 )

    net.hosts.append( h2 )

 

    wifi = WIFISegment()

 

    wifi.addAp( s0 )

    wifi.addSta( h1 )

    wifi.addSta( h2 )

 

    wifi.phyhelper.EnablePcap( "s0-trace.pcap", s0.nsNode.GetDevice( 0 ), True, True ); 

 

    net.start()

    mininet.ns3.start()

 

    CLI(net)

 

2. Run the script. (The h1 will first send out one ping with ToS (0x6) which is corresponding to VOICE service to h3. Then one ping with ToS (0x1) which is corresponding to Background service is sent to h3. Followed by one ping with ToS (0x4) and one ping with ToS (0x0).

After running the script, open the captured file with wireshark.

 

 

 

 

Dr. Chih-Heng Ke

Department of Computer Science and Information Engineering, National Quemoy University, Kinmen, Taiwan

Email: smallko@gmail.com