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, ¢erfreq);
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