otg_models.c 19.2 KB
Newer Older
1
/*******************************************************************************
nikaeinn's avatar
nikaeinn committed
2 3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

nikaeinn's avatar
nikaeinn committed
5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9 10


nikaeinn's avatar
nikaeinn committed
11 12 13 14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

nikaeinn's avatar
nikaeinn committed
16 17 18 19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
    included in this distribution in the file called "COPYING". If not,
    see <http://www.gnu.org/licenses/>.
20 21

  Contact Information
nikaeinn's avatar
nikaeinn committed
22 23 24 25
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27 28 29

*******************************************************************************/

nikaeinn's avatar
nikaeinn committed
30

31
/*! \file otg_models.c
32
* \brief function containing the OTG TX traffic generation functions
nikaeinn's avatar
nikaeinn committed
33
* \author M. Laner and navid nikaein
34 35 36
* \date 2013
* \version 0.1
* \company Eurecom
nikaeinn's avatar
nikaeinn committed
37
* \email: navid.nikaein@eurecom.fr
38 39 40 41
* \note
* \warning
*/

42
#include "UTIL/MATH/oml.h"
43 44 45
#include "otg_models.h"
#include "UTIL/LOG/log.h"

46
double backgroundRateRnd(void);
47 48 49


/*all the TARMA stuff:
50 51
  this is based on the modelling framework provided in
  "M. Laner, P. Svoboda and M. Rupp, Modeling Randomness in Network Traffic, SIGMETRICS/Performance'12, London, UK, 2012".
52 53 54

*/

55 56 57 58 59 60
/* this function must be called for each random process  and each time it shall produce a new random sample,
 which is the return value
 input:   - inputSamples: an array of length TARMA_NUM_PROCESSES with iid gaussian samples
        which must be the same for xcorrelated processes
      - proc: pointer to tarmaProcess_t
 output:  - the next value in the random process
61
*/
62 63
double tarmaCalculateSample( double inputSamples[], tarmaProcess_t *proc)
{
64 65 66 67 68 69
  /* struct with all definitions of the random process and its history */
  int cnt;
  double X, Y, Ypower, Z;

  /* calculate the current sample X' by weighting the input samples */
  X=0;
70 71 72

  for( cnt=0; cnt<TARMA_NUM_PROCESSES ; cnt++) {
    X += proc->inputWeight[cnt]*inputSamples[cnt];
73 74 75
  }

  /* update the MA history: shift everything back for one lag */
76 77
  for( cnt=TARMA_NUM_MA_MAX-1; cnt>0; cnt--) {
    proc->maHist[cnt] = proc->maHist[cnt-1];
78
  }
79

80 81 82
  proc->maHist[0]=X;  /* update the MA history with the current filter input value */

  /* update the AR history: shift everything back for one lag */
83 84
  for( cnt=TARMA_NUM_AR_MAX-1; cnt>0; cnt--) {
    proc->arHist[cnt] = proc->arHist[cnt-1];
85
  }
86

87 88 89 90
  proc->arHist[0]=0;  /* caution: arHist[0] must not be used for the filter processing! */

  /* filter processing */
  Y=0;
91 92 93

  for( cnt=0; cnt<TARMA_NUM_MA_MAX; cnt++) { /* moving average part, start at lag 0 = current X */
    Y += proc->maWeight[cnt] * proc->maHist[cnt];
94
  }
95 96 97

  for( cnt=1; cnt<TARMA_NUM_AR_MAX; cnt++) { /* auto regressive part, start at lag 1 = former Y */
    Y += -proc->arWeight[cnt] * proc->arHist[cnt];
98
  }
99

100 101 102 103 104
  proc->arHist[0]=Y;  /* update the AR history with the current filter output value */

  /* polynomial transformation */
  Z=0;
  Ypower=1;
105 106 107 108

  for(cnt=0; cnt<TARMA_NUM_POLY_MAX; cnt++) {
    Z += proc->polyWeight[cnt]*Ypower;
    Ypower *= Y;
109 110 111 112 113 114 115 116 117
  }

  LOG_D(OTG,"TARMA_DEBUG: tarmaCalculateSamples called: Z=%f\n",Z);
  //tarmaPrintProc(proc);
  return Z;
}

/*
 this function must be called each time before size and itd are generated for the respective packet.
118 119 120 121
  it updates the input samples stored in the structure stream,
  ps: calling it more often than for each packet is also fine
 input:   - the stream to be updated
 output:
122
 */
123 124
void tarmaUpdateInputSample (tarmaStream_t *stream)
{
125
  int cnt;
126
  LOG_T(OTG,"TARMA_DEBUG: tarmaUpdateInputSample(%p)\n", stream);
127 128 129 130 131 132

  if(stream) {
    for(cnt=0; cnt<TARMA_NUM_PROCESSES; cnt++) {
      stream->tarma_input_samples[cnt]=gaussian_dist(10000,1)-10000;
      LOG_D(OTG,"TARMA_DEBUG:   %f\n",stream->tarma_input_samples[cnt]);
    }
133 134 135 136 137
  }
}

/*
 this function initializes the given stream, it allocates the respective memory if necessary (stream=0)
138 139 140
  and sets all the respective values to zero.
 input:   - steam to be initialized (or zero if memory shall be allocated)
 output:  - the same stream
141
 */
142 143 144 145
tarmaStream_t *tarmaInitStream(tarmaStream_t *stream)
{
  if(stream==0) {
    stream=(tarmaStream_t*) malloc(sizeof(tarmaStream_t));
146
  }
147

148 149
  tarmaProcess_t *proc;
  int cntvar, cntp, cntma, cntar, cntpy;
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174

  for(cntvar=0; cntvar<2; cntvar++) {
    if(cntvar==0) {
      proc=&(stream->tarma_idt);
    } else {
      proc=&(stream->tarma_size);
    }

    for(cntp=0; cntp<TARMA_NUM_PROCESSES; cntp++) {
      proc->inputWeight[cntp]=0;
    }

    for(cntma=0; cntma<TARMA_NUM_MA_MAX; cntma++) {
      proc->maWeight[cntma]=0;
      proc->maHist[cntma]=0;
    }

    for(cntar=0; cntar<TARMA_NUM_AR_MAX; cntar++) {
      proc->arWeight[cntar]=0;
      proc->arHist[cntar]=0;
    }

    for(cntpy=0; cntpy<TARMA_NUM_POLY_MAX; cntpy++) {
      proc->polyWeight[cntpy]=0;
    }
175
  }
176

177
  LOG_D(OTG,"TARMA_DEBUG: tarmaInitStream(%p) called\n", stream);
178 179 180
  return stream;
}

181
/*
182
 this function initializes the input stream according to the openarena traffic modelling
183 184
 input:   - stream to be initialized
 output:
185
 */
186 187
void tarmaSetupOpenarenaDownlink(tarmaStream_t *stream)
{
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
  stream->tarma_size.inputWeight[0]=1;
  stream->tarma_size.maWeight[0]=0.6;
  stream->tarma_size.maWeight[1]=-1.04;
  stream->tarma_size.maWeight[2]=0.44;
  stream->tarma_size.arWeight[0]=1;
  stream->tarma_size.arWeight[1]=-1.971;
  stream->tarma_size.arWeight[2]=0.971;
  stream->tarma_size.polyWeight[0]=157;
  stream->tarma_size.polyWeight[1]=67.2;
  stream->tarma_size.polyWeight[2]=-11.2;
  stream->tarma_size.polyWeight[3]=-1.9;
  stream->tarma_size.polyWeight[4]=18.6;
  stream->tarma_size.polyWeight[5]=1.8;
  //tarmaPrintStreamInit(stream);
}

204
/*
205
 this function prints the actual history of a random process
206 207
 input:   - random process
 output:
208
 */
209 210
void tarmaPrintProc(tarmaProcess_t *proc)
{
211 212 213
  char prefix[]="OTG TARMA DEBUG: ";
  int cntma, cntar;

214
  printf("%s tarmaPrintProc(%p) called\n", prefix, proc);
215
  printf("%s     ma history:\n",prefix);
216 217 218

  for(cntma=0; cntma<TARMA_NUM_MA_MAX; cntma++) {
    printf("%s       ma[%d]: %f\n",prefix,cntma,proc->maHist[cntma]);
219
  }
220

221
  printf("%s     ar history:\n",prefix);
222 223 224

  for(cntar=0; cntar<TARMA_NUM_AR_MAX; cntar++) {
    printf("%s       ar[%d]: %f\n",prefix,cntar,proc->arHist[cntar]);
225 226 227
  }
}

228
/*
229
 this function prints the fixed (weigths) parameters of the input stream
230 231
 input:   - stream to be printed
 output:
232
 */
233 234
void tarmaPrintStreamInit(tarmaStream_t *stream)
{
235 236 237 238
  char prefix[]="OTG TARMA DEBUG: ";
  tarmaProcess_t *proc;
  int cntvar, cntp, cntma, cntar, cntpy;

239
  printf("%s tarmaPrintStreamInit(%p) called\n", prefix, stream);
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272

  for(cntvar=0; cntvar<2; cntvar++) {
    if(cntvar==0) {
      proc=&(stream->tarma_idt);
      printf("%s     variable: idt\n",prefix);
    } else {
      proc=&(stream->tarma_size);
      printf("%s     variable: size\n",prefix);
    }

    printf("%s       input processes\n",prefix);

    for(cntp=0; cntp<TARMA_NUM_PROCESSES; cntp++) {
      printf("%s         w_pr[%d]: %f\n",prefix,cntp,proc->inputWeight[cntp]);
    }

    printf("%s       moving average weights\n",prefix);

    for(cntma=0; cntma<TARMA_NUM_MA_MAX; cntma++) {
      printf("%s         w_ma[%d]: %f\n",prefix,cntma,proc->maWeight[cntma]);
    }

    printf("%s       auto-regressive weights\n",prefix);

    for(cntar=0; cntar<TARMA_NUM_AR_MAX; cntar++) {
      printf("%s         w_ar[%d]: %f\n",prefix,cntar,proc->arWeight[cntar]);
    }

    printf("%s       polynomial factors\n",prefix);

    for(cntpy=0; cntpy<TARMA_NUM_POLY_MAX; cntpy++) {
      printf("%s         w_py[%d]: %f\n",prefix,cntpy,proc->polyWeight[cntpy]);
    }
273 274 275 276 277 278 279 280
  }
}


/*
 everything about video modeling which is an extended version of tarma modeling
 */

281
/*
282
 this function calculates the packet size (frame size) for each video frame,
283 284 285
  the idt is always fixed to the framerate (i.e., between 20 and 50 fps, default=25)
 input:   - vidoe stream
 output:  - frame size
286
 */
287 288
double tarmaCalculateVideoSample(tarmaVideo_t *video)
{
289 290 291 292 293 294
  double size=0;
  double inputsamples[TARMA_NUM_PROCESSES];
  tarmaProcess_t *proc;
  int frameidx;
  int cntp, cntpy;

295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
  if(video) {
    proc=&(video->tarma_size);
    frameidx=video->tarmaVideoGopStructure[video->tarmaVideoFrameNumber];
    LOG_D(OTG,"TARMA_DEBUG: tarmaCalculateVideoSample(%p) called\n", video);
    LOG_D(OTG,"TARMA_DEBUG:     frameidx=%d\n",frameidx);

    if(frameidx>=0 && frameidx<TARMA_NUM_FRAME_TYPES) {
      for(cntpy=0; cntpy<TARMA_NUM_POLY_MAX; cntpy++) {
        proc->polyWeight[cntpy]=video->polyWeightFrame[frameidx][cntpy];
      }

      for(cntp=0; cntp<TARMA_NUM_PROCESSES; cntp++) {
        inputsamples[cntp]=gaussian_dist(10000,1)-10000;
      }

      size=tarmaCalculateSample(inputsamples,proc);
    }

    /*get ready for the next frame*/
    video->tarmaVideoFrameNumber++;

    if(video->tarmaVideoFrameNumber>=TARMA_NUM_GOP_MAX) {
      video->tarmaVideoFrameNumber=0;
    }

    if(video->tarmaVideoGopStructure[video->tarmaVideoFrameNumber]<0 ||
        video->tarmaVideoGopStructure[video->tarmaVideoFrameNumber]>TARMA_NUM_FRAME_TYPES) {
      video->tarmaVideoFrameNumber=0;
    }
324
  }
325

326 327 328
  return size;
}

329
/*
330
 this function initializes a video stream (and allocates memory if needed)
331 332
 input:   - video stream (or zero if memory should be allocated)
 output:  - the same video stream
333
 */
334 335
tarmaVideo_t *tarmaInitVideo(tarmaVideo_t *video)
{
336 337 338
  tarmaProcess_t *proc;
  int cntp, cntma, cntar, cntpy, cntgop, cnttype;

339
  LOG_D(OTG,"TARMA_DEBUG: tarmaInitVideo(%p) called\n", video);
340 341 342

  if(video==0) {
    video=(tarmaVideo_t*) malloc(sizeof(tarmaVideo_t));
343
  }
344

345
  proc=&(video->tarma_size);
346 347 348

  for(cntp=0; cntp<TARMA_NUM_PROCESSES; cntp++) {
    proc->inputWeight[cntp]=0;
349
  }
350 351 352 353

  for(cntma=0; cntma<TARMA_NUM_MA_MAX; cntma++) {
    proc->maWeight[cntma]=0;
    proc->maHist[cntma]=0;
354
  }
355 356 357 358

  for(cntar=0; cntar<TARMA_NUM_AR_MAX; cntar++) {
    proc->arWeight[cntar]=0;
    proc->arHist[cntar]=0;
359
  }
360 361 362

  for(cntpy=0; cntpy<TARMA_NUM_POLY_MAX; cntpy++) {
    proc->polyWeight[cntpy]=0;
363
  }
364

365
  video->tarmaVideoFrameNumber=0;
366 367 368

  for(cntgop=0; cntgop<TARMA_NUM_GOP_MAX; cntgop++) {
    video->tarmaVideoGopStructure[cntgop]=-1;
369
  }
370 371 372 373 374

  for(cnttype=0; cnttype<TARMA_NUM_FRAME_TYPES; cnttype++) {
    for(cntpy=0; cntpy<TARMA_NUM_POLY_MAX; cntpy++) {
      video->polyWeightFrame[cnttype][cntpy]=0;
    }
375
  }
376

377 378 379
  return video;
}

380
/*
381
 this function initializes a video stream according to a tarma model
382 383 384
 input:   - video to be initialized
      - compression rate: 1...dvd quality
 output:
385
 */
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
void tarmaSetupVideoGop12(tarmaVideo_t *video, double compression)
{
  if(video) {
    video->tarma_size.inputWeight[0]=1;
    video->tarma_size.maWeight[0]=0.47;
    video->tarma_size.maWeight[1]=-0.829;
    video->tarma_size.maWeight[2]=0.358;
    video->tarma_size.arWeight[0]=1;
    video->tarma_size.arWeight[1]=-1.984;
    video->tarma_size.arWeight[2]=0.984;
    video->tarmaVideoGopStructure[0]=0; /*i frame*/
    video->tarmaVideoGopStructure[1]=2; /*b frame*/
    video->tarmaVideoGopStructure[2]=2;
    video->tarmaVideoGopStructure[3]=1; /*p frame*/
    video->tarmaVideoGopStructure[4]=2;
    video->tarmaVideoGopStructure[5]=2;
    video->tarmaVideoGopStructure[6]=1;
    video->tarmaVideoGopStructure[7]=2;
    video->tarmaVideoGopStructure[8]=2;
    video->tarmaVideoGopStructure[9]=1;
    video->tarmaVideoGopStructure[10]=2;
    video->tarmaVideoGopStructure[11]=2;

    if(compression<1) {
      compression=1;
    }

    video->polyWeightFrame[0][0]=55400/compression; /*i frame*/
    video->polyWeightFrame[0][1]=32300/compression;
    video->polyWeightFrame[0][2]=10400/compression;
    video->polyWeightFrame[0][3]=-100/compression;
    video->polyWeightFrame[0][4]=-800/compression;
    video->polyWeightFrame[0][5]=74/compression;
    video->polyWeightFrame[1][0]=20900/compression; /*p frame*/
    video->polyWeightFrame[1][1]=19100/compression;
    video->polyWeightFrame[1][2]=7150/compression;
    video->polyWeightFrame[1][3]=-740/compression;
    video->polyWeightFrame[1][4]=-130/compression;
    video->polyWeightFrame[1][5]=20/compression;
    video->polyWeightFrame[2][0]=11700/compression; /*b frame*/
    video->polyWeightFrame[2][1]=10300/compression;
    video->polyWeightFrame[2][2]=4320/compression;
    video->polyWeightFrame[2][3]=700/compression;
    video->polyWeightFrame[2][4]=-90/compression;
    video->polyWeightFrame[2][5]=-2/compression;
    tarmaPrintVideoInit(video);
432 433 434
  }
}

435
/*
436
 this function prints the fixed (weigths) parameters of the input video stream
437 438
 input:   - video stream to be printed
 output:
439
 */
440 441
void tarmaPrintVideoInit(tarmaVideo_t *video)
{
442 443 444 445
  char prefix[]="OTG TARMA DEBUG: ";
  tarmaProcess_t *proc;
  int cntp, cntma, cntar, cntpy, cntgop, cnttype;

446
  printf("%s tarmaPrintVideoInit(%p) called\n", prefix, video);
447 448
  proc=&(video->tarma_size);
  printf("%s      input process weights\n",prefix);
449 450 451

  for(cntp=0; cntp<TARMA_NUM_PROCESSES; cntp++) {
    printf("%s        w[%d]=%f\n",prefix,cntp,proc->inputWeight[cntp]);
452
  }
453

454
  printf("%s      ma weights\n",prefix);
455 456 457

  for(cntma=0; cntma<TARMA_NUM_MA_MAX; cntma++) {
    printf("%s        ma[%d]=%f\n",prefix,cntma,proc->maWeight[cntma]);
458
  }
459

460
  printf("%s      ar weights\n",prefix);
461 462 463

  for(cntar=0; cntar<TARMA_NUM_AR_MAX; cntar++) {
    printf("%s        ar[%d]=%f\n",prefix,cntar,proc->arWeight[cntar]);
464
  }
465

466
  printf("%s      polynomial weights\n",prefix);
467 468 469

  for(cntpy=0; cntpy<TARMA_NUM_POLY_MAX; cntpy++) {
    printf("%s        p[%d]=%f\n",prefix,cntpy,proc->polyWeight[cntpy]);
470
  }
471

472 473
  printf("%s      video frame number=%d\n",prefix,video->tarmaVideoFrameNumber);
  printf("%s      gop structure\n",prefix);
474 475 476

  for(cntgop=0; cntgop<TARMA_NUM_GOP_MAX; cntgop++) {
    printf("%s        gop[%d]=%d\n",prefix,cntgop,video->tarmaVideoGopStructure[cntgop]);
477
  }
478 479 480 481 482 483 484 485 486 487 488

  printf("%s      frame poly weights\n",prefix);

  for(cntpy=0; cntpy<TARMA_NUM_POLY_MAX; cntpy++) {
    printf("%s      [%d] ",prefix,cntpy);

    for(cnttype=0; cnttype<TARMA_NUM_FRAME_TYPES; cnttype++) {
      printf("     %05.3f",video->polyWeightFrame[cnttype][cntpy]);
    }

    printf("\n");
489 490 491 492 493 494 495
  }
}





496 497
/*
 everything about background traffic modeling according to
498 499 500
 "M. Laner, P. Svoboda, S. Schwarz, M. Rupp, Users in Cells: a Data Traffic Analysis, WCNC'12, Paris, France, 2012".
 */

501 502 503 504
/*
 this function creates a random realization of the mean data rate of a background-session
 input:
 output:  - random realization of R_s (B/s)
505
 */
506 507
double backgroundRateRnd(void)
{
508 509
  double rate;
  rate=pow(10,lognormal_dist(1.3525, 0.1954))/8; /*Byte/s*/;
510 511 512 513 514

  if(rate>BACKGROUND_RATE_MAX) {
    rate=BACKGROUND_RATE_MAX;
  } else if(rate<0) {
    rate=0;
515
  }
516

517 518 519
  return rate;
}

520
/*
521
 this function creates a random realization of the session duration of a background-session
522 523
 input:
 output:  - random realization of D_s (ms)
524
 */
525 526
int backgroundSessionDurationRnd(void)
{
527 528
  int duration;
  duration = ceil(pow(10,exponential_dist(1/0.3591))*1000); /*ms*/
529 530 531 532 533

  if(duration<0) {
    duration=0;
  } else if(duration>1<<30) {
    duration=1<<30;
534
  }
535

536 537 538
  return duration;
}

539
/*
540
 this function initializes a background stream and allocates memory if needed
541 542 543
 input:   - the bg-stream (or zero if memory shall be allocated)
      - the mean number of users (sessions) to be expected for this stream
 output:  - the same bg-stream
544
 */
545 546
backgroundStream_t *backgroundStreamInit(backgroundStream_t *stream, double lambda_n)
{
547
  int cnts, numactivenow;
548 549 550

  if(stream==0) {
    stream=(backgroundStream_t*) malloc(sizeof(backgroundStream_t));
551 552 553 554 555
  }

  stream->meanNumSessions=lambda_n;
  stream->lastUpdateTime=0;
  numactivenow=poisson_dist(lambda_n); /*how many sessions are active (i.e., started before simulation)*/
556 557 558 559 560 561 562 563 564 565

  for(cnts=0; cnts<BACKGROUND_NUM_ACTIVE_MAX; cnts++) {
    if(cnts<numactivenow) {
      /*these sessions are already active for unknown time and have therefore a random phaseshift in ds*/
      stream->activeSessions[cnts].meanSessionRate=backgroundRateRnd();
      stream->activeSessions[cnts].endTime=ceil((double)backgroundSessionDurationRnd()*uniform_rng()); /*ms*/
    } else {
      stream->activeSessions[cnts].meanSessionRate=0;
      stream->activeSessions[cnts].endTime=-1;
    }
566 567
  }

568
  LOG_D(OTG,"BACKGROUND_USERS DEBUG: backgroundStreamInit(%p) called\n", stream);
569 570 571 572
  backgroundPrintStream (stream);
  return stream;
}

573
/*
574
 this function updates a given background stream
575 576 577
 input:   - bg-stream
      - current time
 output:
578
 */
579 580
void backgroundUpdateStream(backgroundStream_t *stream, int ctime)
{
581 582
  int numNewSessions, cnts, period;

583
  LOG_D(OTG,"BACKGROUND DEBUG: backgroundUpdateStream(stream*=%p,ctime=%d) called\n", stream, ctime);
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604

  if(stream) {
    period=ctime-stream->lastUpdateTime;
    numNewSessions=poisson_dist(stream->meanNumSessions/5710*period);

    for(cnts=0; cnts<BACKGROUND_NUM_ACTIVE_MAX; cnts++) {
      if(stream->activeSessions[cnts].endTime<ctime) {
        if(numNewSessions>0) {
          stream->activeSessions[cnts].meanSessionRate=backgroundRateRnd();
          stream->activeSessions[cnts].endTime=
            ctime-period*uniform_rng()+backgroundSessionDurationRnd(); /*ms*/
          numNewSessions--;
        } else {
          stream->activeSessions[cnts].meanSessionRate=0;
          stream->activeSessions[cnts].endTime=-1;
        }
      }
    }

    stream->lastUpdateTime=ctime;
    backgroundPrintStream (stream);
605 606 607
  }
}

608
/*
609
 this function generates the packet size for a given bg-stream and a given idt,
610 611 612 613 614
  the distribution of the idt can thereby be arbitrary (const idt=20ms recommended)
 input:   - bg-stream
        - current time
        - idt of the current packet
 output:  - packet size of the current packet
615
 */
616 617
double backgroundCalculateSize(backgroundStream_t *stream, int ctime, int idt)
{
618 619 620 621 622
  int cnts, cntact=0;
  double size=0;
  double mrate=0;

  backgroundUpdateStream(stream, ctime);
623
  LOG_D(OTG,"BACKGROUND DEBUG: backgroundCalculateSize(stream*=%p,idt=%d,ctime=%d) called\n", stream, idt, ctime);
624 625 626 627 628 629 630 631 632 633 634

  if(stream) {
    for(cnts=0; cnts<BACKGROUND_NUM_ACTIVE_MAX; cnts++) {
      if(stream->activeSessions[cnts].endTime>ctime) {
        mrate+=stream->activeSessions[cnts].meanSessionRate;
        cntact++;
      }
    }

    size=mrate*idt/1000;
    LOG_D(OTG,"BACKGROUND DEBUG:     cntact=%02d, idt=%05d, agg_mrate=%05.1f, size=%04.1f\n", cntact, idt, mrate,size);
635
  }
636

637 638 639
  return size;
}

640
/*
641
 this function prints the current status of the bg-stream
642 643
 input:   - bg-stream
 output:
644
 */
645 646
void backgroundPrintStream(backgroundStream_t *stream)
{
647
  int cnts;
648

649
  LOG_D(OTG,"BACKGROUND DEBUG: backgroundPrintStream(%p)\n", stream);
650 651

  if(stream) {
652
    LOG_D(OTG,"BACKGROUND DEBUG:     meanNumSessions(lambda_n)=%f\n",stream->meanNumSessions);
653 654 655 656 657

    for(cnts=0; cnts<BACKGROUND_NUM_ACTIVE_MAX; cnts++) {
      LOG_D(OTG,"BACKGROUND DEBUG:       session[%d] -> mrate=%06.3f, etime=%05d\n",
            cnts, stream->activeSessions[cnts].meanSessionRate, stream->activeSessions[cnts].endTime);
    }
658 659 660 661 662
  }
}