Advanced MAC Sceduling & Link Adaption Experiment in Jan-Feb 2004

[Experiment Setup  | New Driver Program |DBS ]

MAC Scheduling & Link Adaption

New Experiment Step :

If Cisco Aironet Card is used
  1. Install ACU and check the firmware version of cisco cards.
  2. Download new firmware to Cisico 340 PCMCIA card. link: http://www.cisco.com/public/sw-center/sw-wireless2.shtml. It's believed that the version 4.25.30 fixed some relevant bugs such as wrong RSSI report and low throughput in IBM Laptops.
  3. We does not need to download new driver Airo.c. The driver does not change much except adding some new features.
  4. Modify the new ario.c dirver for channel-state-dependent driver program
  5. test with netperf.
If Prism 2.5 Card ( Netgear) is used:
  1. download hostAP driver.
  2. Modify it to associate with channel-dependent scheduling scheme.
Finally, I only got six Prism PCMCIA cards for the experiment, so..... ,
I'm going to have One AP and 6 Associated STAs in the network. All seven machines use only one PCMCIA card, and wired ethernet interface are running an NTP protocol to synchronze all nodes. The AP is a laptop with Linux OS and hostap driver, thus it can simulate real AP with a client adaptor card. An FTP server is running in the AP to exchange files conveniently. ( Reference: FTP server on Linux )

Tracking Second-Order Charactristics of Channel Quality

Experiment has never been done on this. RSSI is always to be used as a static indicator of signal strength. I have done an experiment with only one AP and one associated STA, without any traffic, RSSI is measured in the STA from Beacons sent by AP every one second, the experimet has 20,000 ( ~5.5 hours) consecutive measuremetns, which shows at most 4dB degration in the RSSI.
DATA:  Measurents during the night of Friday, Jan,16,2004.

WLAN Benchmarking

How to use DBS?
Setting up NTP ( Network Timing Protocol)
Commmad file for UDP traffic
Scheduling UDP traffic in User Level Space ( Modify the DBS program)

802.11b Test Results:

  1. When supply with  1024 bytes CBR with 50 packets per sec for every station, (AP 0dbm)
    ether/udp1 Recv: Mean Throughput     0.4137 Mbps
    ether/udp2 Recv: Mean Throughput     0.4127 Mbps
    ether/udp3 Recv: Mean Throughput     0.4140 Mbps
    ether/udp4 Recv: Mean Throughput     0.4128 Mbps
    ether/udp5 Recv: Mean Throughput     0.4135 Mbps
    ether/udp6 Recv: Mean Throughput     0.4139 Mbps
  2. When Supply with 1024 bytes CBR with 75 packets per sec ( AP power -5 dbm) (10 min test)
    ether/udp_600k_120/udp1 Recv: Mean Throughput     0.6002 Mbps
    ether/udp_600k_120/udp2 Recv: Mean Throughput     0.4981 Mbps
    ether/udp_600k_120/udp3 Recv: Mean Throughput     0.5527 Mbps
    ether/udp_600k_120/udp4 Recv: Mean Throughput     0.3410 Mbps
    ether/udp_600k_120/udp5 Recv: Mean Throughput     0.3442 Mbps
    ether/udp_600k_120/udp6 Recv: Mean Throughput     0.4666 Mbps

    It's found that the throughput is good because node 5 is broken down at the beginning of the test, so actually, only 5 hosts and 1 AP.
  3. When Supply with 1024 bytes CBR with 75 packets per sec ( AP power -5 dbm) (10 min test in Jan.22)
    udp_600k_122/udp1 Recv: Mean Throughput     0.1677 Mbps
    udp_600k_122/udp2 Recv: Mean Throughput     0.3252 Mbps
    udp_600k_122/udp3 Recv: Mean Throughput     0.3000 Mbps
    udp_600k_122/udp4 Recv: Mean Throughput     0.3184 Mbps
    udp_600k_122/udp5 Recv: Mean Throughput     0.2821 Mbps
    udp_600k_122/udp6 Recv: Mean Throughput     0.3051 Mbps
  4. Supply with 1024 bytes CBR with 75 packets per sec ( AP power -5 dbm) (10 min test , RSSI-based scheduling in User level program)
    newudp_600k_122/udp1 Recv: Mean Throughput     0.2962 Mbps
    newudp_600k_122/udp2 Recv: Mean Throughput     0.4059 Mbps
    newudp_600k_122/udp3 Recv: Mean Throughput     0.3590 Mbps
    newudp_600k_122/udp4 Recv: Mean Throughput     0.4056 Mbps
    newudp_600k_122/udp5 Recv: Mean Throughput     0.3837 Mbps
    newudp_600k_122/udp6 Recv: Mean Throughput     0.3764 Mbps


We have done two 10-minutes test with 6 nodes transmitting to the 1 AP.

The overall througput improvement is from 1.7544 to 2.2804 Mbps

RSSI measurement  comparison:

Table1: RSSI (idle: out of 10 minutes test window)

  w/o scheduling w scheduling
1 206.74 207.4
2 203.6350 205.032
3 213.248 212.14
4 214.39 214.95
5 205.185 199.333
6 202.883 199.4467

Table2: RSSI (busy)

  w/o scheduling w scheduling
1 192.8689 191.0105
2 186.0568 189.0858
3 192.4553 194.459
4 193.6746 197.1952
5 182.7968 184.2826
6 182.3948 182.7943
Correlation between RSSI and througput, obtained in the first 20 seconds with node 5 in test w/o scheduling

DBSD modification (chagne sendrecv.c in source code directory)

It's difficut to have a real scheduler in kernel space. so for simulating this kind of behavior in user space is an inferior alternative. By adjusting the packet release speed over the socket level, we can regard it as same as scheduling packets in MAC level.

/************************************************************
 * UDP SEND
 ************************************************************/
int udp_send(cmd, data, rd)
struct dbsd_param * volatile cmd;
char *data;
struct record *rd;
{
    static struct timeval tp;
    struct timezone tzp;
    struct timeval esleep;
    int s, i, j;
    int total=0;        /* Total Size of sended data */
    int message;
    int sub_total;
    int rest, offset;
    struct dbsd_traffic *traffic = cmd->traffic;
    char *d;
    struct sockaddr *dest;
    int length;
    int volatile timeout_flg = OFF;


    //Zhibin WU, define more local variables
    struct timeval time_shift;
    float origin_rssi,cur_rssi,dead_rssi, total_rssi;
    //double
    FILE* fp1;
    //------------------End-------------------


    /* These are to avoid the optimization with the SPARC CPU's register window. */
    struct dbsd_param * volatile * tmp = &cmd;   /* to allocate cmd to memory */
    int volatile * tmp4 = &timeout_flg;
   
    DEBUGMSG(2, "UDP_SEND: Start.\n");

    if (sigsetjmp(env_alrm, 0) == 0) {

        /*
         * Initialization
         */

        if (signal(SIGALRM, udp_send_timeout) == SIG_ERR)
            safe_exit(SIGNAL, "UDP_SEND.signal(SIGALRM)", strerror(errno));
   
        INIT_RECORD();
        timeval_cp(&esleep, &cmd->start_time);

        dest = (struct sockaddr *)&cmd->d_address;
        length = sizeof(cmd->d_address);

        WAIT_BEFORE(cmd->start_time);
#ifdef DEBUGMODE
        WAIT_UNTIL(cmd->start_time);
#else
        WAIT_AT(cmd->start_time);
#endif
        alarm_at(&cmd->end_time);

        /*
         * Send Main Loop
         */

        /* Zhibin Wu----------------------------------------------
      Open the RSSI_Measurement file, read the first 30 measurments
    */
    fp1 = fopen("rssi_mes.dat","r");
        if ( fp1  == NULL)
    {
       DEBUGMSG(0, "RSSI file calc open error.\n");
    }
    else
    { 
       j = 0;
       total_rssi = 0.;
       while (!feof(fp1))
       {
           fscanf( fp1, "%f4.0", &cur_rssi);
           total_rssi += cur_rssi;
           j++;
       }
       fclose(fp1);
       origin_rssi = total_rssi / j;
       fprintf ( stderr, "average RSSI is %f\n", origin_rssi);
    }        
        //---------------------------End-----------------------

        message = 1;
        sub_total = 0;
        for (j=1; j<=cmd->send_times; j++) {
            for (i=0, traffic=cmd->traffic; i < cmd->traffic_n; i++, traffic++) {
                offset = 0;
                rest   = traffic->size;
                while (1) {
                    d = data + offset;
                    *((unsigned int *)d) = htonl(total); /* XXX UDP Packet must larger than sizeof(int), 4byte*/

                    while ((s = sendto(cmd->fd, d, MIN(traffic->packet, rest), 0, dest, length)) < 0)
                        /* NULL */;

                    sub_total += traffic->packet;
                    if (message % cmd->record_interval == 0) {
                        RECORD(total, sub_total);
                        sub_total = 0;
                    }

                    total  += traffic->packet;
                    rest   -= traffic->packet;
                    offset += traffic->packet;
                    message++;
                   
                    if(rest <= 3)                     /* XXX */
                        break;
                }
       
        /*Zhibin Wu, ------------------------------------------------
              adjust new transmission rate
         */
        fp1 = fopen("rssi_mes.dat","r");
            if ( fp1 == NULL)
        {
           DEBUGMSG(0, "RSSI file read open error.\n");
        }
        else
        {
           fseek (fp1,  -5L,  SEEK_END);
           fscanf(fp1, "%f4.0", &cur_rssi );
         //  fprintf( stderr, "%d\n", (int)cur_rssi ) ; 
           fclose (fp1);
        }
            /*The idea is that there are two ranges of the RSSI
           above -- 200 good, transmit as most as possible
           180-200 are fair, so keep the original rate
           belwo 180---  reduce to 1 packet per 100ms.
        */
        if (cur_rssi >= 200)
               timeval_put(&time_shift, 0.01);
        else if (cur_rssi<180)
               timeval_put(&time_shift, 0.1);
        else
               timeval_cp(&time_shift, &traffic->esleep);              
                           
        //-------------End Change by Zhibin               

                USLEEP2(traffic->isleep, traffic->isleep_flag);
        WAIT_AT2(esleep, time_shift, traffic->esleep_flag); //Zhibin Modified
            }
        }
    } else {
        timeout_flg = ON;
        DEBUGMSG(1, "*Time Out!*\n");
    }

    /*
     * Data Transfer End.
     */

    alarm(0);
    wait_at(&cmd->end_time);
    sleep(END_TIME_OFFSET1);
    DEBUGMSG(2, "UDP_SEND: END.\n");

    return timeout_flg;
}

New Driver program:


Analysis of the original program  written in August, 2003. Airo.c

Channel_monitor function

Queue Handling
static int queue_pos_for_pkt ( struct airo_queue* q, int pkt_length )
{

   int new_tail, head;
   head  =  q->pos[q->head_pos] ;
   new_tail  =  q->pos[q->tail_pos] + q->pktlen[q->tail_pos];
   if (BUF_SIZE - new_tail > pkt_length )
       return new_tail;
   if ( head > pkt_length)
       return 0; 
   // if no places for the packet                                                                                                                                  
   return -1;
   
}   



 # Sample 1 for UDP traffic, one AP - 6 users; AP-bound UDP traffic
  {                                             
          sender {
                  hostname  = 10.0.0.2;
                  hostname_cmd = 192.168.180.21
                  port      = 20001;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  send_buff = 65535;
                  recv_buff = 65535;
                  mem_align = 2048;
                  pattern {1024,   1024,     0.01,      0.0}
          }
          receiver {
                  hostname  = 10.0.0.1;
                  hostname_cmd = 192.168.180.249
                  port      = 20001;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  recv_buff = 65535;
                  send_buff = 65535;
                  mem_align = 2048;
                 pattern {1024,   1024,     0.0,      0.0}
          }
          file           = ether/udp1;
          protocol       = UDP;
          start_time     = 0.0;
          connection_mode= BEFORE;
          end_time       = 600;
          send_times     = 60000;
  }
 {                                            
          sender {
                  hostname  = 10.0.0.3;
                  hostname_cmd = 192.168.180.23
                  port      = 20002;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  send_buff = 65535;
                  recv_buff = 65535;
                  mem_align = 2048;
                  pattern {1024,   1024,     0.01,      0.0}
          }
          receiver {
                  hostname  = 10.0.0.1;
                  hostname_cmd = 192.168.180.249
                  port      = 20002;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  recv_buff = 65535;
                  send_buff = 65535;
                  mem_align = 2048;
                 pattern {1024,   1024,     0.0,      0.0}
          }
          file           = ether/udp2;
          protocol       = UDP;
          start_time     = 0.0;
          connection_mode= BEFORE;
          end_time       = 600;
          send_times     = 60000;
  }
 {                                            
          sender {
                  hostname  = 10.0.0.4;
                  hostname_cmd = 192.168.180.24
                  port      = 20003;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  send_buff = 65535;
                  recv_buff = 65535;
                  mem_align = 2048;
                  pattern {1024,   1024,     0.01,      0.0}
          }
          receiver {
                  hostname  = 10.0.0.1;
                  hostname_cmd = 192.168.180.249
                  port      = 20003;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  recv_buff = 65535;
                  send_buff = 65535;
                  mem_align = 2048;
                 pattern {1024,   1024,     0.0,      0.0}
          }
          file           = ether/udp3;
          protocol       = UDP;
          start_time     = 0.0;
          connection_mode= BEFORE;
          end_time       = 600;
          send_times     = 60000;
  }
 {                                            
          sender {
                  hostname  = 10.0.0.5;
                  hostname_cmd = 192.168.180.26
                  port      = 20004;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  send_buff = 65535;
                  recv_buff = 65535;
                  mem_align = 2048;
                  pattern {1024,   1024,     0.01,      0.0}
          }
          receiver {
                  hostname  = 10.0.0.1;
                  hostname_cmd = 192.168.180.249
                  port      = 20004;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  recv_buff = 65535;
                  send_buff = 65535;
                  mem_align = 2048;
                 pattern {1024,   1024,     0.0,      0.0}
          }
          file           = ether/udp4;
          protocol       = UDP;
          start_time     = 0.0;
          connection_mode= BEFORE;
          end_time       = 600;
          send_times     = 60000;
  }
 {                                            
          sender {
                  hostname  = 10.0.0.6;
                  hostname_cmd = 192.168.180.27
                  port      = 20005;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  send_buff = 65535;
                  recv_buff = 65535;
                  mem_align = 2048;
                  pattern {1024,   1024,     0.01,      0.0}
          }
          receiver {
                  hostname  = 10.0.0.1;
                  hostname_cmd = 192.168.180.249
                  port      = 20005;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  recv_buff = 65535;
                  send_buff = 65535;
                  mem_align = 2048;
                 pattern {1024,   1024,     0.0,      0.0}
          }
          file           = ether/udp5;
          protocol       = UDP;
          start_time     = 0.0;
          end_time       = 600;
          connection_mode= BEFORE;
          send_times     = 60000;
  }
 {                                            
          sender {
                  hostname  = 10.0.0.7;
                  hostname_cmd = 192.168.180.29
                  port      = 20006;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  send_buff = 65535;
                  recv_buff = 65535;
                  mem_align = 2048;
                  pattern {1024,   1024,     0.01,      0.0}
          }
          receiver {
                  hostname  = 10.0.0.1;
                  hostname_cmd = 192.168.180.249
                  port      = 20006;
                  so_debug  = OFF;
                  tcp_trace = OFF;
                  recv_buff = 65535;
                  send_buff = 65535;
                  mem_align = 2048;
                 pattern {1024,   1024,     0.0,      0.0}
          }
          file           = ether/udp6;
          protocol       = UDP;
          start_time     = 0.0;
          end_time       = 600;
          connection_mode= BEFORE;
          send_times     = 60000;
  }
 



Some Thoughts.....

1. A Quality-of-Service Enhanced Socket API in GNU/Linux  ...