1 #include <stdlib.h>
2 #include <string.h>
3 #include <strings.h>
4 #include <stdint.h>
5 #include <inttypes.h>
6 #include <limits.h>
7 #include <stddef.h>
8 #include "WLAN_actmod_argparse.h"
9 #include "bs_utils.h"
10 #include "bs_tracing.h"
11 #include "bs_oswrap.h"
12 #include "bs_cmd_line.h"
13 #include "bs_cmd_line_typical.h"
14 #include "bs_utils.h"
15 #include "bs_pc_2G4_utils.h"
16 
17 char executable_name[] = "bs_device_2G4_WLAN_actmod";
18 
component_print_post_help()19 void component_print_post_help(){
20   fprintf(stdout,"\n\
21 A ConfigSet defines all parameters from DataRate downto kappa.\n\
22 Instead of choosing a <ConfigSet>, these parameters can be selected\n\
23 one by one. Or a set can be chosen, and some of its parameters replaced\n\
24 \n\
25 Note that parameters are processed from left to right\n\
26 (whatever is set later overwrites the previous settings)\n\
27 \n\
28 \n\
29 This WLAN model can be made to start and stop several times.\n\
30 Use the timestart and timeend options to do so:\n\
31 \n\
32 If both of these parameters are omitted, it will run from the beginning to\n\
33 the end of the simulation\n\
34 \n\
35 This model, although very simplistic generates patterns of channel occupancy\n\
36 similar to what a real WLAN would generate while its underlying traffic\n\
37 pattern would remain static.\n\
38 \n\
39 Documentation of this model can be found in the doc folder\n\
40 \n\
41 This model may generate traffic into one Phy port or several. The\n\
42 distribution of traffic in ports is done uniformly given each port probability\n\
43 (<port<x>_probab>)\n"
44   );
45 }
46 
SetParams_fromConfigSet(char * ConfigSetName,WLAN_actmod_args_t * args)47 static void SetParams_fromConfigSet(char *ConfigSetName, WLAN_actmod_args_t *args) {
48 
49   args->PacketHeaderSize = 160; //bits
50   args->DataRate = 54; //Mbps
51   args->SIFS  = 16;   //useconds (wait time between packet and ACK)
52   args->ACKBe = 135;  //bits (an ack is assumed to have ACKTus + ACKBe bits at datarate
53   args->ACKT  = 21.5; //us
54 
55   args->AveCWSize = 67.5; //us ( average size of the contention window ) JUST 1 DEVICE and the router
56   //args->AveCWSize = 350; //us ( average size of the contention window ) MANY DEVICES and high activity
57   args->BeaconPeriod = 200e-3; //seconds (Somewhere in [20ms, 1 second] )
58 
59   //fully random traffic size
60   args->PacketMinSize = 128; //bytes
61   args->PacketMaxSize = 1536;//bytes
62 
63   if ( strcasecmp(ConfigSetName,"VoIP") == 0 ) {
64     args->PacketMinSize = 128; //bytes
65     args->PacketMaxSize = 384;//bytes
66     args->p     = 0.1;  //probability of having a consecutive transmission
67     args->sigma = 11.5; //ms (scale parameter of the generalized pareto)
68     args->kappa = -0.45; //shape parameter of the generalized pareto
69   } else if ( strcasecmp(ConfigSetName,"VideoConf") == 0 ) {
70     args->PacketMinSize = 500; //bytes
71     args->PacketMaxSize = 1536;//bytes
72     args->p     = 0.10;  //probability of having a consecutive transmission
73     args->sigma = 12; //ms (scale parameter of the generalized pareto)
74     args->kappa = -0.45; //shape parameter of the generalized pareto
75   } else if (   ( strcasecmp(ConfigSetName,"FileDownload") == 0 )
76              || ( strcasecmp(ConfigSetName,"100") == 0 ) ) {
77     args->PacketMinSize = 1300; //bytes
78     args->PacketMaxSize = 1536;//bytes
79     args->p     = 0.988;  //probability of having a consecutive transmission
80     args->sigma = 0.04; //ms (scale parameter of the generalized pareto)
81     args->kappa = 0.5; //shape parameter of the generalized pareto
82   } else if (   ( strcasecmp(ConfigSetName,"FileDownload_24M") == 0 )
83              || ( strcasecmp(ConfigSetName,"100_24M") == 0 ) ) {
84     args->DataRate = 24;
85     args->PacketMinSize = 1300; //bytes
86     args->PacketMaxSize = 1536;//bytes
87     args->p     = 0.99;  //probability of having a consecutive transmission
88     args->sigma = 0.04; //ms (scale parameter of the generalized pareto)
89     args->kappa = 0.5; //shape parameter of the generalized pareto
90   } else if (   ( strcasecmp(ConfigSetName,"FileDownload_12M") == 0 )
91              || ( strcasecmp(ConfigSetName,"100_12M") == 0 ) ) {
92     args->DataRate = 12;
93     args->PacketMinSize = 1300; //bytes
94     args->PacketMaxSize = 1536;//bytes
95     args->p     = 0.99;  //probability of having a consecutive transmission
96     args->sigma = 0.04; //ms (scale parameter of the generalized pareto)
97     args->kappa = 0.5; //shape parameter of the generalized pareto
98   } else if (   ( strcasecmp(ConfigSetName,"FileDownload_6M") == 0 )
99              || ( strcasecmp(ConfigSetName,"100_6M") == 0 ) ) {
100     args->DataRate = 6;
101     args->PacketMinSize = 1300; //bytes
102     args->PacketMaxSize = 1536;//bytes
103     args->p     = 0.988;  //probability of having a consecutive transmission
104     args->sigma = 0.04; //ms (scale parameter of the generalized pareto)
105     args->kappa = 0.5; //shape parameter of the generalized pareto
106   } else if ( strcasecmp(ConfigSetName,"50") == 0 ) {
107     args->p     = 0.55;  //probability of having a consecutive transmission
108     args->sigma = 0.45; //ms (scale parameter of the generalized pareto)
109     args->kappa = 0; //shape parameter of the generalized pareto
110   } else if ( strcasecmp(ConfigSetName,"50_24M") == 0 ) {
111     args->DataRate = 24;
112     args->p     = 0.5;  //probability of having a consecutive transmission
113     args->sigma = 0.5; //ms (scale parameter of the generalized pareto)
114     args->kappa = 0.2; //shape parameter of the generalized pareto
115   } else if ( strcasecmp(ConfigSetName,"50_12M") == 0 ) {
116     args->DataRate = 12;
117     args->p     = 0.45;  //probability of having a consecutive transmission
118     args->sigma = 0.7; //ms (scale parameter of the generalized pareto)
119     args->kappa = 0.4; //shape parameter of the generalized pareto
120   } else if ( strcasecmp(ConfigSetName,"50_6M") == 0 ) {
121     args->DataRate = 6;
122     args->p     = 0.4;  //probability of having a consecutive transmission
123     args->sigma = 0.87; //ms (scale parameter of the generalized pareto)
124     args->kappa = 0.6; //shape parameter of the generalized pareto
125 
126   } else if ( strcasecmp(ConfigSetName,"25") == 0 ) {
127     args->p     = 0.45;  //probability of having a consecutive transmission
128     args->sigma = 1.4; //ms (scale parameter of the generalized pareto)
129     args->kappa = 0; //shape parameter of the generalized pareto
130   } else if ( strcasecmp(ConfigSetName,"25_24M") == 0 ) {
131     args->DataRate = 24;
132     args->p     = 0.4;  //probability of having a consecutive transmission
133     args->sigma = 1.5; //ms (scale parameter of the generalized pareto)
134     args->kappa = 0.15; //shape parameter of the generalized pareto
135   } else if ( strcasecmp(ConfigSetName,"25_12M") == 0 ) {
136     args->DataRate = 12;
137     args->p     = 0.3;  //probability of having a consecutive transmission
138     args->sigma = 2.0; //ms (scale parameter of the generalized pareto)
139     args->kappa = 0.27; //shape parameter of the generalized pareto
140   } else if ( strcasecmp(ConfigSetName,"25_6M") == 0 ) {
141     args->DataRate = 6;
142     args->p     = 0.24;  //probability of having a consecutive transmission
143     args->sigma = 2.9; //ms (scale parameter of the generalized pareto)
144     args->kappa = 0.41; //shape parameter of the generalized pareto
145   } else if ( strcasecmp(ConfigSetName,"10") == 0 ) {
146     args->p     = 0.35;  //probability of having a consecutive transmission
147     args->sigma = 4; //ms (scale parameter of the generalized pareto)
148     args->kappa = 0; //shape parameter of the generalized pareto
149   } else if ( strcasecmp(ConfigSetName,"10_24M") == 0 ) {
150     args->DataRate = 24;
151     args->p     = 0.3;  //probability of having a consecutive transmission
152     args->sigma = 4; //ms (scale parameter of the generalized pareto)
153     args->kappa = 0.1; //shape parameter of the generalized pareto
154   } else if ( strcasecmp(ConfigSetName,"10_12M") == 0 ) {
155     args->DataRate = 12;
156     args->p     = 0.3;  //probability of having a consecutive transmission
157     args->sigma = 4.5; //ms (scale parameter of the generalized pareto)
158     args->kappa = 0.47; //shape parameter of the generalized pareto
159   } else if ( strcasecmp(ConfigSetName,"10_6M") == 0 ) {
160     args->DataRate = 6;
161     args->p     = 0.3;  //probability of having a consecutive transmission
162     args->sigma = 8.5; //ms (scale parameter of the generalized pareto)
163     args->kappa = 0.47; //shape parameter of the generalized pareto
164   } else if ( strcasecmp(ConfigSetName,"5") == 0 ) {
165     args->p     = 0.2;  //probability of having a consecutive transmission
166     args->sigma = 6.5; //ms (scale parameter of the generalized pareto)
167     args->kappa = 0; //shape parameter of the generalized pareto
168   } else {
169     bs_trace_error_line("ConfigSetName \"%s\" is not known\n",ConfigSetName);
170   }
171 }
172 
CenterFreq_from_WLANChannel(int WChannel)173 static p2G4_freq_t CenterFreq_from_WLANChannel(int WChannel) {
174   double center;
175   p2G4_freq_t centerfreq;
176   center = 2407 + WChannel * 5;
177   if (WChannel == 14) {
178     center = 2484;
179   }
180   p2G4_freq_from_d(center , 0, &centerfreq);
181   return centerfreq;
182 }
183 
184 WLAN_actmod_args_t *args_g;
185 
cmd_trace_lvl_found(char * argv,int offset)186 static void cmd_trace_lvl_found(char * argv, int offset) {
187   bs_trace_set_level(args_g->verb);
188 }
189 
cmd_gdev_nbr_found(char * argv,int offset)190 static void cmd_gdev_nbr_found(char * argv, int offset) {
191   bs_trace_set_prefix_dev(args_g->global_device_nbr);
192 }
193 
cmd_nports_found(char * argv,int offset)194 static void cmd_nports_found(char * argv, int offset) {
195   if ( args_g->number_ports > WLAN_MAX_NBR_PORTS ){
196     bs_trace_error_line("You configured %i ports but the maximum is %i (%s)\n",
197                         args_g->number_ports, WLAN_MAX_NBR_PORTS, argv);
198   }
199 }
200 
201 static double doub;
202 static char *str;
203 
cmd_power_found(char * argv,int offset)204 static void cmd_power_found(char * argv, int offset) {
205   args_g->powerdBm = p2G4_power_from_d(doub);
206 }
207 
208 static int WChannel;
cmd_channel_found(char * argv,int offset)209 static void cmd_channel_found(char * argv, int offset) {
210   if (( WChannel < 1 ) || ( WChannel > 14 )) {
211     bs_trace_error_line("Error parsing channel (only channels between 1 and 14 allowed) (%s)\n", argv);
212   }
213   args_g->centerfreq = CenterFreq_from_WLANChannel(WChannel);
214   bs_trace_raw(9,"=> center frequency set to %.2lfMHz (+2400)\n", ((double)args_g->centerfreq)/(1<<P2G4_freq_FRACB));
215 }
cmd_cfreq_found(char * argv,int offset)216 static void cmd_cfreq_found(char * argv, int offset) {
217   int error = p2G4_freq_from_d(doub, 0, &args_g->centerfreq);
218   if (error) {
219     bs_trace_error_line("Could not parse center frequency (%s)\n", argv);
220   }
221   bs_trace_raw(9,"center frequency set to %.2lfMHz (+2400)\n", ((double)args_g->centerfreq)/(1<<P2G4_freq_FRACB));
222 }
cmd_mod_found(char * argv,int offset)223 static void cmd_mod_found(char * argv, int offset){
224   int error = p2G4_modulation_from_string(str, &args_g->modulation, OnlyNonReceivable, 1);
225   if ( error != 0 ) {
226     bs_trace_error_line("Could not interpret modulation type %s\n",&argv[offset]);
227   }
228 }
cmd_cfgs_found(char * argv,int offset)229 static void cmd_cfgs_found(char * argv, int offset){
230   SetParams_fromConfigSet(str, args_g);
231 }
cmd_datarate_found(char * argv,int offset)232 static void cmd_datarate_found(char * argv, int offset) {
233   if ((args_g->DataRate < 1) || (args_g->DataRate > 54)) {
234     bs_trace_warning_line("DataRate (%.3fMbps) is weird.. (expected 1..54Mbps) (%s)\n", args_g->DataRate, argv);
235   }
236 }
cmd_mins_found(char * argv,int offset)237 static void cmd_mins_found(char * argv, int offset) {
238   if ((args_g->PacketMinSize < 80 ) || ( args_g->PacketMinSize > 1536)) {
239     bs_trace_warning_line("Minimum packet size(%i) is weird.. (expected 80..1536) (%s)\n", args_g->PacketMinSize , argv);
240   }
241 }
cmd_maxs_found(char * argv,int offset)242 static void cmd_maxs_found(char * argv, int offset) {
243   if ((args_g->PacketMaxSize < 80) || (args_g->PacketMaxSize > 1536)) {
244     bs_trace_warning_line("Maximum packet size(%i) is weird.. (expected 80..1536) (%s)\n", args_g->PacketMaxSize , argv);
245   }
246 }
cmd_SIFS_found(char * argv,int offset)247 static void cmd_SIFS_found(char * argv, int offset) {
248   if ( ( args_g->SIFS < 10 ) || ( args_g->SIFS > 100 ) ) {
249     bs_trace_warning_line("SIFS (%f) is weird.. (expected 10 to 100us) (%s)\n", args_g->SIFS);
250   }
251 }
252 
cmd_ACKT_found(char * argv,int offset)253 static void cmd_ACKT_found(char * argv, int offset) {
254   if ( ( args_g->ACKT < 5 ) || ( args_g->ACKT > 200 ) ) {
255     bs_trace_warning_line("ACKT (%f) is weird.. (expected 5 to 200us) (%s)\n", args_g->ACKT , argv);
256   }
257 }
258 
cmd_AveCWSize_found(char * argv,int offset)259 static void cmd_AveCWSize_found(char * argv, int offset) {
260   if ( ( args_g->AveCWSize < 5 ) || ( args_g->AveCWSize > 2000 ) ) {
261     bs_trace_warning_line("AveCWSize (%f) is weird.. (expected 5 to 2000us) (%s)\n", args_g->AveCWSize , argv);
262   }
263 }
264 
cmd_beap_found(char * argv,int offset)265 static void cmd_beap_found(char * argv, int offset) {
266   if ((args_g->BeaconPeriod < 10e-3) || (args_g->BeaconPeriod > 2)) {
267     bs_trace_warning_line("BeaconPeriod (%f) is weird.. (expected 10e-3 to 2s) (%s)\n", args_g->BeaconPeriod , argv);
268   }
269 }
270 
cmd_p_found(char * argv,int offset)271 static void cmd_p_found(char * argv, int offset) {
272   if ((args_g->p < 0) || (args_g->p > 1)) {
273     bs_trace_error_line("p out of range (%f) (expected 0 to 1) (%s)\n", args_g->p , argv);
274   }
275 }
cmd_sigma_found(char * argv,int offset)276 static void cmd_sigma_found(char * argv, int offset) {
277   if ((args_g->sigma < 0) || (args_g->sigma > 100)) {
278     bs_trace_warning_line("sigma looks out of range (%f) (expected 0 to 100ms) (%s)\n", args_g->sigma , argv);
279   }
280 }
281 
282 /**
283  * Check the arguments provided in the command line: set args based on it or
284  * defaults, and check they are correct
285  */
WLAN_actmod_argparse(int argc,char * argv[],WLAN_actmod_args_t * args)286 void WLAN_actmod_argparse(int argc, char *argv[], WLAN_actmod_args_t *args)
287 {
288 
289   args_g = args;
290   bs_args_struct_t args_struct[] = {
291       /*manual,mandatory,switch,option,     name ,               type,   destination,         callback,             , description*/
292       ARG_TABLE_S_ID,
293       ARG_TABLE_P_ID_2G4,
294       { false, true  , false, "d",       "port_number0",         'u', (void*)&args->device_nbr[0],NULL,      "device number (port in phy) (equivalent to -d0=<>)"},
295       ARG_TABLE_GDEV_NBR,
296       ARG_TABLE_VERB,
297       ARG_TABLE_STARTO,
298       ARG_TABLE_SEED,
299       { false, false , false, "nports",  "number_ports",         'u', (void*)&args->number_ports,cmd_nports_found,"(1) number of ports to connect to in the phy" },
300       { true,  false , false, "d<x>",    "port_number<x>",       'u', NULL                    ,NULL,         "device/port number in phy to be used for port <x>" },
301       { true,  false , false, "pp<x>",   "port<x>_probab",       'u', NULL                    ,NULL,         "probability of a transmission going out thru port <x>" },
302       { false, false , false, "power",   "powerdBm",             'f', (void*)&doub            ,cmd_power_found,"In dBm power of the interference (20dBm)" },
303       { false, false , false, "channel", "WLANChannel",          'i', (void*)&WChannel        ,cmd_channel_found,"WLAN channel to use" },
304       { false, false , false, "centerfreq","centerf",            'f', (void*)&doub            ,cmd_cfreq_found,"Centerfreq in MHz (can be given instead of -channel)" },
305       { false, false , false, "mod",      "modtype",             's', (void*)&str             ,cmd_mod_found,"{CW,(WLAN),BLE,WN{1|2|4|8|16|20|40|80}} Type of interference (default WLAN)" },
306       { false, false , false, "ConfigSet","ConfigSet",           's', (void*)&str             ,cmd_cfgs_found,"One of the predefined sets of parameters {VoIP,VideoConf,FileDownload,100,50,25,10,(5)} where 100,50,25,10 & 5 model one device driving traffic at 100%%,..,5%% of the WLAN total capacity (Only for <DataRate>=54Mbps) See documentation for a longer description\n" },
307       { false, false , false, "DataRate" ,"DataRate",            'f', (void*)&(args->DataRate),cmd_datarate_found,"WLAN datarate in Mbits/s (54)" },
308       { false, false , false, "PacketMinSize" ,"PminSize",       'u', (void*)&(args->PacketMinSize),cmd_mins_found,"Minimum size of the WLAN packets in bytes (128)" },
309       { false, false , false, "PacketMaxSize" ,"PmaxSize",       'u', (void*)&(args->PacketMaxSize),cmd_maxs_found,"Maximum size of the WLAN packets in bytes (1536)" },
310       { false, false , false, "PacketHeaderSize" ,"PHSize",      'u', (void*)&(args->PacketHeaderSize),NULL,  "Size of the WLAN headers in bits(160)" },
311       { false, false , false, "SIFS"      ,"SIFS",               'f', (void*)&(args->SIFS)    ,cmd_SIFS_found,"WLAN SIFS time in us (16)" },
312       { false, false , false, "ACKBe"     ,"ACKBe",              'u', (void*)&(args->ACKBe)   ,NULL,          "ACK duration in bits at DataRate (will be added to ACKT) (135)" },
313       { false, false , false, "ACKT"      ,"ACKT",               'f', (void*)&(args->ACKT)    ,cmd_ACKT_found,"ACK duration in us (will be added to ACKBe) (21.5)" },
314       { false, false , false, "AveCWSize" ,"AveCWSize",          'f', (void*)&(args->AveCWSize),cmd_AveCWSize_found,"Average contention window size in us [(67.5)..20460]" },
315       { false, false , false, "BeaconPeriod" ,"BeacP",           'f', (void*)&(args->BeaconPeriod),cmd_beap_found,"Period of the WLAN beacons,in seconds [10e-3..(200e-3)..2]" },
316       { false, false , false, "pr"        ,"pr",                 'f', (void*)&(args->p)       ,cmd_p_found,  "Probability of having a new packet right after finalizing transmitting a previous one (0.2)" },
317       { false, false , false, "sigma"     ,"sigma",              'f', (void*)&(args->sigma)   ,cmd_sigma_found,"Generalized Pareto scale factor (in ms) (6.5)" },
318       { false, false , false, "kappa"     ,"kappa",              'f', (void*)&(args->kappa)   ,NULL,         "Generalized Pareto shape factor (0)\n" },
319       { true,  false , false, "timestart" ,"time",               'l', NULL                    ,NULL,         "Times at which the active periods shall start (omit to run from the beginning) (up to " STR(WLAN_actmod_MAX_TIMES) " periods)" },
320       { true,  false , false, "timeend" ,"time",                 'l', NULL                    ,NULL,         "Times at which the activity periods shall end (omit the last to run until the end of the simulation) (up to " STR(WLAN_actmod_MAX_TIMES) " periods)" },
321       ARG_TABLE_ENDMARKER
322   };
323 
324   bs_args_set_defaults(args_struct);
325   args->verb = 2;
326   bs_trace_set_level(args->verb);
327   args->rseed = 0xFFFF;
328   args->start_offset = 0;
329   args->number_ports = 1;
330   for (int i = 0; i < WLAN_MAX_NBR_PORTS; i++){
331     args->device_nbr[i] = UINT_MAX;
332     args->ports_probs[i] = 0;
333   }
334   args->ports_probs[0] = 1; //by default there is only 1 port where everything goes
335 
336   args->n_times_start = 0;
337   args->n_times_end   = 0;
338   args->modulation    = P2G4_MOD_WLANINTER;
339   args->centerfreq    = P2G4_INVALID_FREQ;
340   args->powerdBm = p2G4_power_from_d(20);
341   args->PacketMinSize = 128;
342   args->PacketMaxSize = 1536;
343   args->PacketHeaderSize = 160;
344   args->DataRate = 54;
345   args->SIFS  = 16;
346   args->ACKBe = 135;
347   args->ACKT  = 21.5;
348   args->AveCWSize = 67.5;
349   args->BeaconPeriod = 200e-3;
350   args->p = 0.2;
351   args->sigma = 6.5;
352   args->kappa = 0;
353   static char default_phy[] ="2G4";
354 
355   for (int i=1; i<argc; i++) {
356     int offset;
357     uint index;
358     if ( !bs_args_parse_one_arg(argv[i], args_struct) ){ //Attempt to find and parse it between the non-manual options
359       if ((offset = bs_is_multi_opt(argv[i], "d", &index, 1))) {
360         if (index < args->number_ports) {
361           char name[50];
362           snprintf(name, 50, "port_number%i", index);
363           bs_read_optionparam(&argv[i][offset], (void*)&(args->device_nbr[index]), 'u', name);
364         } else {
365           bs_trace_error_line("You configured %i ports but tried to set the device numbr for port %i (%s) [you need to give -nports option before any -d<port> option] \n", args->number_ports, index, argv[i]);
366         }
367       }
368       else if ((offset = bs_is_multi_opt(argv[i], "pp", &index, 1))) {
369         if (index < args->number_ports) {
370           char name[50];
371           snprintf(name, 50, "port%i_prob", index);
372           bs_read_optionparam(&argv[i][offset], (void*)&(args->ports_probs[index]), 'f', name);
373         } else {
374           bs_trace_error_line("You configured %i ports but tried to set the probability port %i (%s) [you need to give -np option before any -pp<port> option]\n", args->number_ports, index, argv[i]);
375         }
376       }
377       else if ((offset = bs_is_option(argv[i], "timestart", 0))) {
378         double time;
379         while ((i + 1 < argc) && (argv[i+1][0] != '-')) {
380           i += 1;
381           if (sscanf(argv[i],"%lf",&time) != 1) {
382             bs_trace_error_line("Could not parse timestart entry nbr %i (%s)\n", args->n_times_start+1, argv[i]);
383           }
384           args->times_start[args->n_times_start] = time;
385           bs_trace_raw(9,"added timestart[%i] = %"PRItime" to list\n", args->n_times_start, args->times_start[args->n_times_start]);
386           args->n_times_start += 1;
387         }
388       }
389       else if ((offset = bs_is_option(argv[i], "timeend", 0))) {
390         double time;
391         while ((i + 1 < argc) && (argv[i+1][0] != '-')) {
392           i += 1;
393           if (sscanf(argv[i],"%lf",&time) != 1) {
394             bs_trace_error_line("Could not parse timeend entry nbr %i (%s)\n", args->n_times_end+1, argv[i]);
395           }
396           args->times_end[args->n_times_end] = time;
397           bs_trace_raw(9,"added timeend[%i] = %"PRItime" to list\n", args->n_times_end, args->times_end[args->n_times_end]);
398           args->n_times_end += 1;
399         }
400       } else {
401         bs_args_print_switches_help(args_struct);
402         bs_trace_error_line("Unknown command line switch '%s'\n",argv[i]);
403       }
404     }
405   }
406 
407   if (!args->s_id) {
408     bs_args_print_switches_help(args_struct);
409     bs_trace_error_line("The command line option <simulation ID> needs to be set\n");
410   }
411   if (!args->p_id) {
412     args->p_id = default_phy;
413   }
414 
415   double total_prob = 0;
416   for (int i = 0 ; i < args->number_ports ; i++) {
417     if ( args->device_nbr[i] == UINT_MAX ) {
418       bs_args_print_switches_help(args_struct);
419       bs_trace_error_line("The command line option <port_number%i> needs to be"
420                           " set (%i ports set)\n", i, args->number_ports);
421     }
422     total_prob += args->ports_probs[i];
423   }
424   double warning_tolerance = 1e-3;
425   if ((total_prob > 1.0 + warning_tolerance) || (total_prob < 1.0 - warning_tolerance)) {
426     //if the ports probabilities don't add up to 1 by a big amount, we tell the user
427     bs_trace_raw(2, "All ports probability doesn't add up to 100% but to "
428                     "%0.2f%%, I will re-scale them proportionally\n",
429                     total_prob*100.0);
430   }
431   //we always scale the ports probabilities so they add up to 1 together
432   for (int i = 0;  i < args->number_ports ; i++) {
433     args->ports_probs[i] /= total_prob;
434   }
435   for (int i = 1 ; i < args->number_ports ; i++) {
436     if (args->device_nbr[i] <= args->device_nbr[i-1] )
437       bs_trace_error_line("device ports need to be in ascending order "
438                           "(otherwise it will deadlock)\n");
439   }
440 
441   if (args->global_device_nbr == UINT_MAX) {
442     args->global_device_nbr = args->device_nbr[0];
443     bs_trace_set_prefix_dev(args->global_device_nbr);
444   }
445 
446   if (args->centerfreq == P2G4_INVALID_FREQ) {
447     bs_args_print_switches_help(args_struct);
448     bs_trace_error_line("The WLAN channel or center frequency needs to be "
449                         "specified\n");
450   }
451 
452   if (args->n_times_start == 0) {
453     args->n_times_start = 1;
454     args->times_start[0] = 1;
455   }
456   if (args->n_times_end == args->n_times_start - 1) {
457     args->n_times_end = args->n_times_start ;
458     args->times_end[args->n_times_end-1] = TIME_NEVER;
459   }
460   if ( args->n_times_end != args->n_times_start ){
461     bs_trace_error_line("You need to provide the same number of end and start "
462                         "times (or one less if you want to let the last burst "
463                         "run forever) (run with --help for more info)\n");
464   }
465 
466   args->DIFS = args->SIFS*2 + 2*9; //we assume the slot time is 9us
467 }
468