Main Page | Class List | File List | Class Members | File Members

mux.c

Go to the documentation of this file.
00001 #include "standard.h"
00002 #include <stdio.h>
00003 #include <math.h>
00004 #include "mux.h"
00005 #include "al.h"
00006 #include "al_sending.h"
00007 #include "comb.h"
00008 #include "muxstuff.h"
00009 
00010 
00011 #define MIN(a, b) ({int _a=(a),_b=(b);(_a<_b)?_a:_b;})
00012 
00013 
00014 extern int debug;
00015 
00016 extern byte sync_8[1];
00017 extern byte sync_16[2];
00018 extern byte sync_2x16[2];
00019 extern byte sync_24[3];
00020 extern byte sync_32[4];
00021 
00022 
00023 mux *new_mux(char *name)
00024 {
00025   mux *bob;
00026   
00027   bob = malloc(sizeof(mux));
00028   if (bob != NULL) {
00029      bob->num_al_senders = 0;
00030      strcpy(bob->name, name);
00031      bob->wait_time=0;
00032   }
00033 
00034   bob->packetsSent = 0;
00035   return(bob);
00036 }
00037 
00038 
00039 static int bytes_ok(int mt_bytes[], int buffer_bytes[], int d, mux *m)
00040      /*
00041       * Returns 1 iff for i=0, i<d, mt_bytes[i] <= buffer_bytes[i]
00042       *           also, number of channels described in the MED must
00043       *           equal the number of channels.  Ie. if you only
00044       *           have LCN0 and LCN1, and your MED is 
00045       *           {LCN1 RC 10, LCN2 RC UCF} this function returns 0.
00046       *
00047       * Should be used like this:
00048       *
00049       * if (bytes_ok(mt_bytes, al_buffer, num_channels, m);
00050       */
00051 {
00052   int ok = 1;
00053   int i;
00054   int tot_bytes = 0;
00055 
00056   for (i=0; i<d; i++) {
00057     tot_bytes += mt_bytes[i];
00058     if (buffer_bytes[i] < mt_bytes[i])
00059       ok = 0;
00060   }
00061   if (tot_bytes < m->params->info_field_length)
00062     ok = 0;
00063   return (ok);
00064 }
00065 
00066 
00067 float ratio_difference(float a[], float b[], int d)
00068      /* 
00069       * Computes the scalar difference between a[] and b[]
00070       * (i.e. sum(i=0, d-1, (abs(b[i] - a[i]))).
00071       *
00072       * Should be used like this:
00073       * 
00074       * diff = compute_difference(mt_ratios, al_ratios, num_channels);
00075       */
00076 {
00077   float sum = 0.0;
00078   int i;
00079   for (i=0; i<d; i++) {
00080     sum += fabs(b[i] - a[i]);
00081   }
00082   return (sum);
00083 }
00084 
00085 
00086 static void print_int(int x)
00087 {
00088   int i;
00089   for (i=31; i>=0; i--) {
00090     if (x & (1 << i))
00091       putchar('1');
00092     else
00093       putchar('0');
00094   }
00095   putchar('\n');
00096 }
00097 
00098 
00099 static void set_payload_size(mux *m)
00100 {
00101   int x;
00102   double d;
00103 
00104   x = random();
00105   
00106   d = (double) x / 0x7FFFFFFF;
00107 
00108   m->params->info_field_length = 
00109     (int) (d * (m->params->payload_max - m->params->payload_min) + 
00110     m->params->payload_min + 0.5);
00111 }
00112 
00113 
00114 void multiplex(mux *m, int num_channels)
00115 /*
00116  * mux function.  
00117  */
00118 {
00119   int requested_sizes[MAX_AL_SENDERS];
00120   int al_bytes[MAX_AL_SENDERS];
00121   float al_ratios[MAX_AL_SENDERS];
00122   float best_diff;
00123   float diff;
00124   int best_mc;
00125   int num_arqs;
00126   combinations *arq_combs;
00127   int *arq_attempt;
00128   int total_bytes;
00129   int i, j, k, l, n, count;
00130   int MC=-1;
00131   int repeating;
00132   int fromwhere;
00133   int ok;
00134   byte larry;
00135   byte *header;
00136   byte *mplf;
00137   bytes *al_pdus[MAX_AL_SENDERS];
00138   int al_pdu_counters[MAX_AL_SENDERS];
00139   int als_requesting_arqs[MAX_AL_SENDERS];
00140 
00141 #define SYNC_BYTES ((m->params->sync_flag_length)/8)
00142 #define SYNC_BITS (m->params->sync_flag_length)
00143 
00144 #define HEADER_BYTES ((code_length(m->params->header_code)+1)/8)
00145 #define MPL_BYTES ((code_length(m->params->mpl_code)+1)/8)
00146 #define INFO_BYTES (m->params->info_field_length)
00147 #define PACKET_BYTES (SYNC_BYTES + HEADER_BYTES + INFO_BYTES)
00148 #define AL (m->al_senders)
00149 #define MT_SIZE (m->params->mux_table_size)
00150 #define MT (m->params->mux_table)
00151 #define MT_RATIOS (m->params->mt_ratios)
00152 #define MT_BYTES (m->params->mt_bytes)
00153 
00154   /*
00155    * If it is time to make a packet, do so.  
00156    */
00157   
00158   if (channel_write_indication(m->output)) {
00159     
00160     /*
00161      * pick payload size randomly.
00162      */
00163     set_payload_size(m);
00164     
00165     MT_BYTES = make_mt_bytes(MT, MT_SIZE, num_channels, INFO_BYTES);
00166     MT_RATIOS = make_mt_ratios(MT_BYTES, MT_SIZE, num_channels, INFO_BYTES);
00167     
00168     if (debug) {
00169       printf("%s MUX [%s]: Payload field length = %d bytes\n", 
00170              print_time(), m->name, INFO_BYTES);
00171       printf("%s MUX [%s]: Buffer levels  : ", print_time(), m->name);
00172       for (i=0; i<num_channels; i++) {
00173         printf("%3d ", al_buffer_level(AL[i]));
00174       }
00175       printf("\n");
00176     }
00177     
00178     /*
00179      * Requested arq sizes 
00180      */
00181     if (debug >= 2) {
00182       printf("MUX [%s]: Requested sizes: ", m->name); 
00183     }
00184     num_arqs = 0;
00185     for (i=0; i<num_channels; i++) {
00186       if (al_request(AL[i]) == -1) {
00187         requested_sizes[i] = al_requested_size(AL[i]);
00188         als_requesting_arqs[num_arqs++] = i;
00189       }
00190       else {
00191         requested_sizes[i] = 0;
00192       }
00193       if (debug >= 2) {
00194         printf("%4d ", requested_sizes[i]);
00195       }
00196     }
00197     if (debug >= 2) {
00198       printf("\n");
00199     }
00200     
00201     if (debug >= 2) {
00202       printf("MUX : als requesting arq's: ");
00203       for (i=0; i<num_arqs; i++) 
00204         printf("%4d ", als_requesting_arqs[i]);
00205       printf("\n");
00206     }
00207     /*
00208      * Try to pick a multiplex code.  First try handling all or some of the ARQ's.
00209      */
00210     best_mc = -1;
00211     best_diff = -1;
00212     for (i = num_arqs; ((i >= 0) && (best_mc==-1)); i--) {
00213       if (debug >= 2) {
00214         printf("MUX : Trying to satisfy %d ARQ's.\n", i);
00215       }
00216       arq_combs = new_combinations(als_requesting_arqs, num_arqs, i);
00217       arq_attempt = next_combination(arq_combs);
00218       do {
00219         /*
00220          * Set up bytes per channel and ratios to check for this combination.
00221          */
00222         if (debug >= 3) {
00223           printf("MUX : ARQ combination: ");
00224           for (l=0; l<i; l++) 
00225             printf("%4d", arq_attempt[l]);
00226           printf("\n");
00227         }
00228         total_bytes = 0;
00229         for (j=0; j<num_channels; j++) {
00230           al_ratios[j] = 0.0;
00231           al_bytes[j] = 0;
00232         }
00233         for (j=0; j<i; j++) {
00234           al_bytes[arq_attempt[j]] = requested_sizes[arq_attempt[j]];
00235           al_ratios[arq_attempt[j]] = (float) al_bytes[arq_attempt[j]];
00236           total_bytes += al_bytes[arq_attempt[j]];
00237         }
00238         for (j=0; j<num_channels; j++) {
00239           if (al_bytes[j] == 0) {
00240             al_bytes[j] = al_buffer_level(AL[j]);
00241             al_ratios[j] = (int) al_bytes[j];
00242             total_bytes += al_bytes[j];
00243           }
00244         }
00245         if (total_bytes) {
00246           for (j=0; j<num_channels; j++) {
00247             al_ratios[j] = (float) al_ratios[j] / total_bytes;
00248           }
00249         }
00250         if (debug >= 2) {
00251           printf("MUX : AL Bytes per channel: ");
00252           for (l=0; l<num_channels; l++) 
00253             printf("%6d ", al_bytes[l]);
00254           printf("\n");
00255           printf("MUX : Byte ratios         : ");
00256           for (l=0; l<num_channels; l++)
00257             printf("%6.3f ", al_ratios[l]);
00258           printf("\n");   
00259         }
00260         /*
00261          * For each entry in the multiplex table, see if it handles the ARQ's we want.
00262          */
00263         for (j=0; j<MT_SIZE; j++) {
00264           if (debug >= 3) {
00265             printf("MUX : MC %2d ratios        : ", j);
00266             for (l=0; l<num_channels; l++) 
00267               printf("%6.3f ", MT_RATIOS[j][l]);
00268           }
00269           ok = 1;
00270           /* 
00271            * Make sure all ARQ's are handled (exactly for now) 
00272            */
00273           for (k=0; ((k<i) && (ok)); k++) {
00274             if (MT_BYTES[j][arq_attempt[k]] != requested_sizes[arq_attempt[k]])
00275               ok = 0;
00276           }
00277           /*
00278            * Check that bytes are ok.
00279            */
00280           if (ok) {
00281             if (!bytes_ok(MT_BYTES[j], al_bytes, num_channels,m))
00282               ok = 0;
00283           }
00284           /*
00285            * See if it's the best.
00286            */
00287           if (ok) {
00288             diff = ratio_difference(MT_RATIOS[j], al_ratios, num_channels);
00289             if (debug >= 3) {
00290               printf(" diff = %6.3f\n", diff);
00291             }
00292             if ((best_mc == -1) || (diff < best_diff)) {
00293               best_mc = j;
00294               best_diff = diff;
00295             }
00296           }
00297           else { 
00298             if (debug >= 3) {
00299               printf("\n");
00300             }
00301           }
00302         }
00303       } while ((arq_attempt = next_combination(arq_combs)) != NULL);
00304       close_combinations(arq_combs);
00305     }
00306     
00307     /*
00308      * If that didn't work, I don't know what will.
00309      */
00310     MC = best_mc;
00311     
00312     if (MC == -1) {
00313       if (debug) {
00314         printf("%s MUX [%s]: Doing nothing.\n", print_time(), m->name);
00315       }
00316       return;
00317     }
00318     else {
00319       if (debug) {
00320         printf("%s MUX [%s]: Making packet with MC %d, ", print_time(), m->name, MC);
00321         
00322         for (i=0; i<num_channels; i++)
00323           printf(" %3d", MT_BYTES[MC][i]);
00324         printf("\n");
00325       }
00326     }
00327     /************************************************************/
00328     /* Now form a packet based on the multiplex code chosen.    */
00329     /************************************************************/
00330     
00331     /* 
00332      * Get AL-PDU's.  Set counters to 0.
00333      */
00334     for (i=0; i<num_channels; i++) {
00335       if (MT_BYTES[MC][i] != 0) {
00336         al_pdus[i] = get_al_pdu(AL[i], MT_BYTES[MC][i]);
00337       }
00338       else {
00339         al_pdus[i] = NULL;
00340       }
00341       al_pdu_counters[i] = 0;
00342     }
00343     
00344     /*
00345      * Start sending packet 
00346      */
00347     n = 0;          /* Mux-pdu position counter */
00348     /*
00349      * Send SYNC field.
00350      */
00351     if (debug) {
00352       printf("%s MUX [%s]: Sending %d SYNC_BYTES.\n", print_time(),
00353              m->name, SYNC_BYTES);
00354     }
00355     for (count = 0; count < SYNC_BYTES; count++)  {
00356       if (m->params->use_double_flag) {
00357         larry = sync_2x16[count];
00358       }
00359       else if (SYNC_BITS == 32) {
00360         larry = sync_32[count];
00361       }
00362       else if (SYNC_BITS == 24) {
00363         larry = sync_24[count];
00364       }
00365       else if (SYNC_BITS == 16) {
00366         larry = sync_16[count];
00367       }
00368       else if (SYNC_BITS == 8) {
00369         larry = sync_8[count];
00370       }
00371       
00372       channel_write(m->output, larry);
00373       n++;
00374     }
00375 
00376     if (m->params->level == 2) {
00377       /* send HEADER and MPL concatenated, protected by 23,12 Golay code */
00378       header = construct_header_level2(MC,0,INFO_BYTES);
00379       for (count = 0; count < HEADER_BYTES; count++) {
00380         channel_write(m->output, header[count]);
00381       }
00382       if (debug) {
00383         printf("%s MUX [%s]: Sending %d HEADER_BYTES.\n", print_time(), 
00384                m->name,HEADER_BYTES);
00385       }
00386     } 
00387     else { /* level is 1 or 0 */
00388       /*
00389        * send HEADER field with BCH code
00390        */
00391       header = construct_header(MC, 0, m->params->header_code, m->params->level);
00392                               /* PM bit hard-coded to zero.  :-( */
00393       if (debug) {
00394         printf("%s MUX [%s]: Sending %d HEADER_BYTES.\n", print_time(),
00395                m->name, HEADER_BYTES);
00396       }
00397       for (count = 0; count < HEADER_BYTES; count++) {
00398         channel_write(m->output, header[count]);
00399         n++;
00400       }
00401     } 
00402     
00403     /*
00404      * Send INFO BYTES.
00405      */
00406     if (debug) {
00407         printf("%s MUX [%s]: Sending %d INFO_BYTES.\n", print_time(),
00408                m->name, INFO_BYTES);
00409     }
00410 
00411     for (count = 0; count < INFO_BYTES; count++) {
00412       fromwhere = mux_byte_source(&MT[MC], count);
00413       larry = get_byte(al_pdus[fromwhere], al_pdu_counters[fromwhere]++);
00414 
00415       channel_write(m->output, larry);
00416       n++;
00417     }
00418 
00419     /*
00420      * Don't need these anymore.
00421      */
00422     for (i=0; i<num_channels; i++) {
00423       if (al_pdus[i] != NULL) {
00424         free_bytes(al_pdus[i]);
00425       }
00426     }
00427     m->packetsSent++;
00428   }
00429   else {
00430     if (debug) {
00431       printf("%s MUX [%s] Not time to write yet.\n", print_time(), m->name);
00432     }
00433   }
00434 }
00435 
00436 void close_mux(mux *m)
00437 {
00438   FILE *outf;
00439   printf("%s: %d Packets Sent\n",m->name,m->packetsSent);
00440   if (*m->params->stat_file!=0) {
00441     outf = fopen(m->params->stat_file,"a");
00442     assert(outf!=NULL);
00443     fprintf(outf,"%s: %d packets sent\n",m->name,m->packetsSent);
00444     fclose(outf);
00445   }
00446 }
00447 

Generated on Sun Jul 16 16:27:45 2006 by  doxygen 1.3.9.1