bypass_session_layer.c 24.3 KB
Newer Older
ghaddab's avatar
ghaddab committed
1
/*******************************************************************************
2
    OpenAirInterface
ghaddab's avatar
ghaddab committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    Copyright(c) 1999 - 2014 Eurecom

    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.


    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.

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

  Contact Information
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
25

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

 *******************************************************************************/
29
/*! \file bypass_session_layer.h
Cedric Roux's avatar
Cedric Roux committed
30
31
 *  \brief implementation of emultor tx and rx
 *  \author Navid Nikaein and Raymond Knopp
32
 *  \date 2011 - 2014
Cedric Roux's avatar
Cedric Roux committed
33
34
35
36
 *  \version 1.0
 *  \company Eurecom
 *  \email: navid.nikaein@eurecom.fr
 */
37
38
39

#include "PHY/defs.h"
#include "defs.h"
Cedric Roux's avatar
Cedric Roux committed
40
#include "proto.h"
41
#include "extern.h"
Cedric Roux's avatar
Cedric Roux committed
42

43
#include "assertions.h"
44
45
46
47
48
#include "UTIL/OCG/OCG.h"
#include "UTIL/OCG/OCG_extern.h"
#include "UTIL/LOG/log.h"

#ifdef USER_MODE
49
50
# include "multicast_link.h"
# include "pgm_link.h"
51
52
53
#endif

char rx_bufferP[BYPASS_RX_BUFFER_SIZE];
54
unsigned int num_bytesP = 0;
Cedric Roux's avatar
Cedric Roux committed
55
56
57
58
59
60
int      N_P = 0, N_R = 0;
char         bypass_tx_buffer[BYPASS_TX_BUFFER_SIZE];
static unsigned int byte_tx_count;
unsigned int Master_list_rx;
static uint64_t seq_num_tx = 0;

Cedric Roux's avatar
   
Cedric Roux committed
61
62
63
64
#if defined(ENABLE_PGM_TRANSPORT)
extern unsigned int pgm_would_block;
#endif

65
mapping transport_names[] = {
66
67
68
69
70
71
  {"WAIT PM TRANSPORT INFO", EMU_TRANSPORT_INFO_WAIT_PM},
  {"WAIT SM TRANSPORT INFO", EMU_TRANSPORT_INFO_WAIT_SM},
  {"SYNC TRANSPORT INFO", EMU_TRANSPORT_INFO_SYNC},
  {"ENB_TRANSPORT INFO", EMU_TRANSPORT_INFO_ENB},
  {"UE TRANSPORT INFO", EMU_TRANSPORT_INFO_UE},
  {"RELEASE TRANSPORT INFO", EMU_TRANSPORT_INFO_RELEASE},
Cedric Roux's avatar
   
Cedric Roux committed
72
#if defined(ENABLE_PGM_TRANSPORT)
73
  {"NACK TRANSPORT INFO", EMU_TRANSPORT_NACK},
Cedric Roux's avatar
   
Cedric Roux committed
74
#endif
75
  {NULL, -1}
76
77
};

Cedric Roux's avatar
Cedric Roux committed
78
79
void init_bypass (void)
{
80
  LOG_I(EMU, "[PHYSIM] INIT BYPASS\n");
81

Cedric Roux's avatar
Cedric Roux committed
82
#if !defined(ENABLE_NEW_MULTICAST)
83
84
85
86
87
88
  pthread_mutex_init (&Tx_mutex, NULL);
  pthread_cond_init (&Tx_cond, NULL);
  Tx_mutex_var = 1;
  pthread_mutex_init (&emul_low_mutex, NULL);
  pthread_cond_init (&emul_low_cond, NULL);
  emul_low_mutex_var = 1;
89
90
#endif
#if defined(ENABLE_PGM_TRANSPORT)
91
  pgm_oai_init(oai_emulation.info.multicast_ifname);
Cedric Roux's avatar
Cedric Roux committed
92
#endif
93
  bypass_init (emul_tx_handler, emul_rx_handler);
94
95
96
}

/***************************************************************************/
Cedric Roux's avatar
Cedric Roux committed
97
98
void bypass_init (tx_handler_t tx_handlerP, rx_handler_t rx_handlerP)
{
99
  /***************************************************************************/
Cedric Roux's avatar
Cedric Roux committed
100
#if defined(USER_MODE)
101
102
  multicast_link_start (bypass_rx_handler, oai_emulation.info.multicast_group,
                        oai_emulation.info.multicast_ifname);
103
#endif //USER_MODE
104
105
106
107
108
  tx_handler = tx_handlerP;
  rx_handler = rx_handlerP;
  Master_list_rx=0;
  emu_tx_status = WAIT_SYNC_TRANSPORT;
  emu_rx_status = WAIT_SYNC_TRANSPORT;
109
}
Cedric Roux's avatar
Cedric Roux committed
110

111
112
int emu_transport_handle_sync(bypass_msg_header_t *messg)
{
113
  int m_id;
114

115
  DevAssert(messg != NULL);
Cedric Roux's avatar
   
Cedric Roux committed
116

117
118
119
  // determite the total number of remote enb & ue
  oai_emulation.info.nb_enb_remote += messg->nb_enb;
  oai_emulation.info.nb_ue_remote += messg->nb_ue;
120

121
122
123
124
125
126
127
128
129
130
  // determine the index of local enb and ue wrt the remote ones
  if (messg->master_id < oai_emulation.info.master_id) {
    oai_emulation.info.first_enb_local +=messg->nb_enb;
    oai_emulation.info.first_ue_local +=messg->nb_ue;
  }

  // store param for enb per master
  if ((oai_emulation.info.master[messg->master_id].nb_enb = messg->nb_enb) > 0) {
    for (m_id=0; m_id < messg->master_id; m_id++ ) {
      oai_emulation.info.master[messg->master_id].first_enb+=oai_emulation.info.master[m_id].nb_enb;
131
132
    }

133
134
135
136
137
138
139
140
141
142
143
    LOG_I(EMU,
          "[ENB] WAIT_SYNC_TRANSPORT state:  for master %d (first enb %d, totan enb %d)\n",
          messg->master_id,
          oai_emulation.info.master[messg->master_id].first_enb,
          oai_emulation.info.master[messg->master_id].nb_enb);
  }

  // store param for ue per master
  if ((oai_emulation.info.master[messg->master_id].nb_ue  = messg->nb_ue) > 0) {
    for (m_id=0; m_id < messg->master_id; m_id++ ) {
      oai_emulation.info.master[messg->master_id].first_ue+=oai_emulation.info.master[m_id].nb_ue;
144
145
146
    }

    LOG_I(EMU,
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
          "[UE] WAIT_SYNC_TRANSPORT state: for master %d (first ue %d, total ue%d)\n",
          messg->master_id,
          oai_emulation.info.master[messg->master_id].first_ue,
          oai_emulation.info.master[messg->master_id].nb_ue );
  }

  Master_list_rx=((Master_list_rx) |(1<< messg->master_id));

  if (Master_list_rx == oai_emulation.info.master_list) {
    emu_rx_status = SYNCED_TRANSPORT;
  }

  LOG_I(EMU,
        "WAIT_SYNC_TRANSPORT state: m_id %d total enb remote %d total ue remote %d \n",
        messg->master_id,oai_emulation.info.nb_enb_remote,
        oai_emulation.info.nb_ue_remote );
  return 0;
164
165
166
167
}

int emu_transport_handle_wait_sm(bypass_msg_header_t *messg)
{
168
169
  DevAssert(messg != NULL);
  Master_list_rx = ((Master_list_rx) | (1 << messg->master_id));
170

171
  return 0;
172
173
174
175
}

int emu_transport_handle_wait_pm(bypass_msg_header_t *messg)
{
176
177
178
179
180
  DevAssert(messg != NULL);

  if (messg->master_id == 0) {
    Master_list_rx = ((Master_list_rx) | (1 << messg->master_id));
  }
181

182
  return 0;
183
184
185
186
187
188
189
}

static
int emu_transport_handle_enb_info(bypass_msg_header_t *messg,
                                  unsigned int next_slot,
                                  int bytes_read)
{
190
191
192
  eNB_transport_info_t *eNB_info;
  int total_header = 0, total_tbs = 0;
  int n_dci, n_enb, enb_info_ix = 0,CC_id;
Cedric Roux's avatar
   
Cedric Roux committed
193

194
195
  DevAssert(bytes_read >= 0);
  DevAssert(messg != NULL);
Cedric Roux's avatar
   
Cedric Roux committed
196

197
#ifdef DEBUG_EMU
198
  LOG_D(EMU," RX ENB_TRANSPORT INFO from master %d \n",messg->master_id);
199
#endif
200
201
  clear_eNB_transport_info(oai_emulation.info.nb_enb_local+
                           oai_emulation.info.nb_enb_remote);
202

203
204
205
206
207
208
209
210
211
212
213
214
215
216
  if (oai_emulation.info.master[messg->master_id].nb_enb > 0 ) {
    total_header += sizeof(eNB_transport_info_t)-MAX_TRANSPORT_BLOCKS_BUFFER_SIZE;

    eNB_info = (eNB_transport_info_t *) (&rx_bufferP[bytes_read]);

    for (n_enb = oai_emulation.info.master[messg->master_id].first_enb;
         n_enb < oai_emulation.info.master[messg->master_id].first_enb+
         oai_emulation.info.master[messg->master_id].nb_enb;
         n_enb ++) {
      for (n_dci = 0; n_dci < (eNB_info[enb_info_ix].num_ue_spec_dci + eNB_info[enb_info_ix].num_common_dci); n_dci ++) {
        total_tbs += eNB_info[enb_info_ix].tbs[n_dci];
      }

      enb_info_ix++;
217

218
219
220
221
222
223
224
225
226
227
228
      if ((total_tbs + total_header) > MAX_TRANSPORT_BLOCKS_BUFFER_SIZE ) {
        LOG_W(EMU,"RX eNB Transport buffer total size %d (header%d,tbs %d) \n",
              total_header+total_tbs, total_header,total_tbs);
      }

      memcpy(&eNB_transport_info[n_enb], eNB_info, total_header + total_tbs);

      /* Go to the next eNB info */
      eNB_info = (eNB_transport_info_t *)((uintptr_t)eNB_info + total_header+
                                          total_tbs);
      bytes_read += (total_header + total_tbs);
229
    }
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248

    for (n_enb = oai_emulation.info.master[messg->master_id].first_enb;
         n_enb < oai_emulation.info.master[messg->master_id].first_enb +
         oai_emulation.info.master[messg->master_id].nb_enb; n_enb ++)
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        fill_phy_enb_vars(n_enb, CC_id,next_slot);
      }
  } else {
    LOG_T(EMU,"WAIT_ENB_TRANSPORT state: no enb transport info from master %d \n",
          messg->master_id);
  }

  Master_list_rx=((Master_list_rx) |(1<< messg->master_id));

  if (Master_list_rx == oai_emulation.info.master_list) {
    emu_rx_status = SYNCED_TRANSPORT;
  }

  return 0;
249
250
251
252
253
254
255
}

static
int emu_transport_handle_ue_info(bypass_msg_header_t *messg,
                                 unsigned int last_slot,
                                 int bytes_read)
{
256
257
258
  UE_transport_info_t *UE_info;
  int n_ue, n_enb,CC_id=0;
  int total_tbs = 0, total_header = 0, ue_info_ix =0;
259

260
261
  DevAssert(bytes_read >= 0);
  DevAssert(messg != NULL);
Cedric Roux's avatar
   
Cedric Roux committed
262

263
#ifdef DEBUG_EMU
264
  LOG_D(EMU," RX UE TRANSPORT INFO from master %d\n",messg->master_id);
265
#endif
266
267
  clear_UE_transport_info(oai_emulation.info.nb_ue_local+
                          oai_emulation.info.nb_ue_remote);
268

269
270
  if (oai_emulation.info.master[messg->master_id].nb_ue > 0 ) {
    total_header += sizeof(UE_transport_info_t)-MAX_TRANSPORT_BLOCKS_BUFFER_SIZE;
271

272
273
274
275
276
277
278
279
280
281
282
    UE_info = (UE_transport_info_t *) (&rx_bufferP[bytes_read]);

    // get the total size of the transport blocks
    for (n_ue = oai_emulation.info.master[messg->master_id].first_ue;
         n_ue < oai_emulation.info.master[messg->master_id].first_ue +
         oai_emulation.info.master[messg->master_id].nb_ue; n_ue ++) {
      total_tbs = 0;

      for (n_enb = 0; n_enb < UE_info[ue_info_ix].num_eNB; n_enb ++) {
        total_tbs += UE_info[ue_info_ix].tbs[n_enb];
      }
283

284
285
286
287
288
289
290
      ue_info_ix++;

      if (total_tbs + total_header > MAX_TRANSPORT_BLOCKS_BUFFER_SIZE ) {
        LOG_W(EMU,"RX [UE %d] Total size of buffer is %d (header%d,tbs %d) \n",
              n_ue, total_header+total_tbs,total_header,total_tbs);
      }

Cedric Roux's avatar
Cedric Roux committed
291
//#warning "CC id should be adjusted, set to zero for the moment"
292
293
294
295
296
297
      memcpy(&UE_transport_info[n_ue][CC_id], UE_info, total_header + total_tbs);

      /* Go to the next UE info */
      UE_info = (UE_transport_info_t *)((uintptr_t)UE_info + total_header+
                                        total_tbs);
      bytes_read += (total_header + total_tbs);
298
    }
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318

    for (n_ue = oai_emulation.info.master[messg->master_id].first_ue;
         n_ue < oai_emulation.info.master[messg->master_id].first_ue +
         oai_emulation.info.master[messg->master_id].nb_ue;
         n_ue ++)
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        fill_phy_ue_vars(n_ue, CC_id,last_slot);
      }
  } else {
    LOG_T(EMU,"WAIT_UE_TRANSPORT state: no UE transport info from master %d\n",
          messg->master_id);
  }

  Master_list_rx=((Master_list_rx) |(1<< messg->master_id));

  if (Master_list_rx == oai_emulation.info.master_list) {
    emu_rx_status = SYNCED_TRANSPORT;
  }

  return 0;
319
}
Cedric Roux's avatar
Cedric Roux committed
320
321
322
323

int bypass_rx_data(unsigned int frame, unsigned int last_slot,
                   unsigned int next_slot, uint8_t is_master)
{
324
325
326
  bypass_msg_header_t *messg;
  bypass_proto2multicast_header_t *bypass_read_header;
  int bytes_read = 0;
Cedric Roux's avatar
Cedric Roux committed
327

328
329
  LOG_D(EMU, "Entering bypass_rx for frame %d next_slot %d is_master %u\n",
        frame, next_slot, is_master);
Cedric Roux's avatar
Cedric Roux committed
330
331

#if defined(ENABLE_NEW_MULTICAST)
332
# if defined(ENABLE_PGM_TRANSPORT)
333
334
335
  num_bytesP = pgm_recv_msg(oai_emulation.info.multicast_group,
                            (uint8_t *)&rx_bufferP[0], sizeof(rx_bufferP),
                            frame, next_slot);
336

337
  DevCheck(num_bytesP > 0, num_bytesP, 0, 0);
338
# else
339
340
341
342
343
344

  if (multicast_link_read_data_from_sock(is_master) == 1) {
    /* We got a timeout */
    return -1;
  }

345
# endif
Cedric Roux's avatar
Cedric Roux committed
346
#else
347
  pthread_mutex_lock(&emul_low_mutex);
Cedric Roux's avatar
Cedric Roux committed
348

349
350
351
352
353
354
355
  if(emul_low_mutex_var) {
    pthread_cond_wait(&emul_low_cond, &emul_low_mutex);
  }

  if(num_bytesP==0) {
    pthread_mutex_unlock(&emul_low_mutex);
  } else {
356
#endif
357
358
359
360
361
362
363
364
365
366
367
  bypass_read_header = (bypass_proto2multicast_header_t *) (
                         &rx_bufferP[bytes_read]);
  bytes_read += sizeof (bypass_proto2multicast_header_t);

  if (num_bytesP != bytes_read + bypass_read_header->size) {
    LOG_W(EMU, "WARNINIG BYTES2READ # DELIVERED BYTES!!! (%d != %d)\n",
          num_bytesP, bytes_read + bypass_read_header->size);
    exit(EXIT_FAILURE);
  } else {
    messg = (bypass_msg_header_t *) (&rx_bufferP[bytes_read]);
    bytes_read += sizeof (bypass_msg_header_t);
Cedric Roux's avatar
Cedric Roux committed
368
#if defined(ENABLE_NEW_MULTICAST)
369
370
371
372
    LOG_D(EMU, "Received %d bytes [%s] from master_id %d with seq %"PRIuMAX"\n",
          num_bytesP, map_int_to_str(transport_names, messg->Message_type),
          messg->master_id,
          messg->seq_num);
Cedric Roux's avatar
   
Cedric Roux committed
373
#if defined(ENABLE_PGM_TRANSPORT)
374
375

    if (messg->Message_type != EMU_TRANSPORT_NACK)
Cedric Roux's avatar
   
Cedric Roux committed
376
#endif
377
378
379
      DevCheck4((messg->frame == frame) && (messg->subframe == (next_slot>>1)),
                messg->frame, frame, messg->subframe, next_slot>>1);

Cedric Roux's avatar
Cedric Roux committed
380
#else
381
382
383
384
385
386
387
388
389
390

    if ((messg->frame != frame) || (messg->subframe != next_slot>>1))
      LOG_W(EMU,
            "Received %s from master %d for (frame %d,subframe %d) "
            "currently (frame %d,subframe %d)\n",
            map_int_to_str(transport_names,messg->Message_type),
            messg->master_id,
            messg->frame, messg->subframe,
            frame, next_slot>>1);

Cedric Roux's avatar
Cedric Roux committed
391
#endif
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

    //chek if MASTER in my List
    switch(messg->Message_type) {
    case EMU_TRANSPORT_INFO_WAIT_PM:
      emu_transport_handle_wait_pm(messg);
      break;

    case EMU_TRANSPORT_INFO_WAIT_SM:
      emu_transport_handle_wait_sm(messg);
      break;

    case EMU_TRANSPORT_INFO_SYNC:
      emu_transport_handle_sync(messg);
      break;

    case EMU_TRANSPORT_INFO_ENB:
      emu_transport_handle_enb_info(messg, next_slot, bytes_read);
      break;

    case EMU_TRANSPORT_INFO_UE:
      emu_transport_handle_ue_info(messg, last_slot, bytes_read);
      break;

    case EMU_TRANSPORT_INFO_RELEASE :
      Master_list_rx = oai_emulation.info.master_list;
      LOG_E(EMU, "RX EMU_TRANSPORT_INFO_RELEASE\n");
      break;
Cedric Roux's avatar
   
Cedric Roux committed
419
#if defined(ENABLE_PGM_TRANSPORT)
420
421
422
423
424
425
426
427
428
429
430
431

    case EMU_TRANSPORT_NACK:
      if (messg->failing_master_id == oai_emulation.info.master_id) {
        /* We simply re-send the last message */
        pgm_link_send_msg(oai_emulation.info.multicast_group,
                          (uint8_t *)bypass_tx_buffer, byte_tx_count);
      } else {
        /* Sleep awhile till other peers have recovered data */
        usleep(500);
      }

      break;
Cedric Roux's avatar
   
Cedric Roux committed
432
#endif
433

434
435
436
437
438
439
440
441
    default:
      LOG_E(EMU, "[MAC][BYPASS] ERROR RX UNKNOWN MESSAGE\n");
      //mac_xface->macphy_exit("");
      break;
    }
  }

  num_bytesP=0;
442

Cedric Roux's avatar
Cedric Roux committed
443
#if !defined(ENABLE_NEW_MULTICAST)
444
  emul_low_mutex_var=1;
Cedric Roux's avatar
Cedric Roux committed
445

446
447
  pthread_cond_signal(&emul_low_cond);
  pthread_mutex_unlock(&emul_low_mutex);
Cedric Roux's avatar
Cedric Roux committed
448
#endif
449
  bypass_signal_mac_phy(frame, last_slot, next_slot, is_master);
Cedric Roux's avatar
Cedric Roux committed
450
#if !defined(ENABLE_NEW_MULTICAST)
451
452
}

Cedric Roux's avatar
Cedric Roux committed
453
#endif
454

455
return bytes_read;
456
457
}

Cedric Roux's avatar
Cedric Roux committed
458
459
460
461
/******************************************************************************************************/
#ifndef USER_MODE
int bypass_rx_handler(unsigned int fifo, int rw)
{
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
  /******************************************************************************************************/
  int bytes_read;
  int bytes_processed=0;
  int header_bytes; //, elapsed_time;
  //printk("[BYPASS] BYPASS_RX_HANDLER IN...\n");
  header_bytes= rtf_get(fifo_bypass_phy_user2kern, rx_bufferP,
                        sizeof(bypass_proto2multicast_header_t) );

  if (header_bytes> 0) {
    bytes_read = rtf_get(fifo_bypass_phy_user2kern, &rx_bufferP[header_bytes],
                         ((bypass_proto2multicast_header_t *) (&rx_bufferP[0]))->size);

    // printk("BYTES_READ=%d\n",bytes_read);
    if (bytes_read > 0) {
      num_bytesP=header_bytes+bytes_read;
      emul_low_mutex_var=0;
      //printk("BYPASS_PHY SIGNAL MAC_LOW...\n");
      pthread_cond_signal(&emul_low_cond);
480
    }
481
482
483
484
  }

  // }
  return 0;
485
486
}
#else //USER_MODE
Cedric Roux's avatar
Cedric Roux committed
487
488
489
/******************************************************************************************************/
void bypass_rx_handler(unsigned int Num_bytes,char *Rx_buffer)
{
490
491
  /******************************************************************************************************/
  if(Num_bytes >0) {
Cedric Roux's avatar
Cedric Roux committed
492
#if !defined(ENABLE_NEW_MULTICAST)
493
494
495
496
497
498
    pthread_mutex_lock(&emul_low_mutex);

    while(!emul_low_mutex_var) {
      pthread_cond_wait(&emul_low_cond, &emul_low_mutex);
    }

Cedric Roux's avatar
Cedric Roux committed
499
#endif
500
501
    num_bytesP=Num_bytes;
    memcpy(rx_bufferP, Rx_buffer, Num_bytes);
Cedric Roux's avatar
Cedric Roux committed
502
#if !defined(ENABLE_NEW_MULTICAST)
503
    emul_low_mutex_var=0;
Cedric Roux's avatar
Cedric Roux committed
504

505
506
507
508
509
    /* on ne peut que signaler depuis un context linux
     * (rtf_handler); pas de wait, jamais!!!!!!
     */
    pthread_cond_signal(&emul_low_cond);
    pthread_mutex_unlock(&emul_low_mutex);
Cedric Roux's avatar
Cedric Roux committed
510
#endif
511
  }
512
513
514
}
#endif //USER_MODE

Cedric Roux's avatar
Cedric Roux committed
515
516
517
518
/******************************************************************************************************/
void  bypass_signal_mac_phy(unsigned int frame, unsigned int last_slot,
                            unsigned int next_slot, uint8_t is_master)
{
519
520
  /******************************************************************************************************/
  if (Master_list_rx != oai_emulation.info.master_list) {
521
#ifndef USER_MODE
522
523
    rtf_put(fifo_mac_bypass, &tt, 1);
    /* the Rx window is still opened  (Re)signal bypass_phy (emulate MAC signal) */
Cedric Roux's avatar
Cedric Roux committed
524
#endif
525
526
527
528
    bypass_rx_data(frame, last_slot, next_slot, is_master);
  } else {
    Master_list_rx = 0;
  }
529
530
531
532
}

#ifndef USER_MODE
/***************************************************************************/
Cedric Roux's avatar
Cedric Roux committed
533
534
int multicast_link_write_sock (int groupP, char *dataP, unsigned int sizeP)
{
535
536
  /***************************************************************************/
  int             tx_bytes=0;
Cedric Roux's avatar
Cedric Roux committed
537

538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
  pthread_mutex_lock(&Tx_mutex);

  while(!Tx_mutex_var) {
    pthread_cond_wait(&Tx_cond,&Tx_mutex);
  }

  Tx_mutex_var=0;
  N_P=(int)((sizeP-sizeof (bypass_proto2multicast_header_t))/1000)+2;
  tx_bytes += rtf_put (fifo_bypass_phy_kern2user, &dataP[tx_bytes],
                       sizeof (bypass_proto2multicast_header_t));

  while(tx_bytes<sizeP) {
    if(sizeP-tx_bytes<=1000) {
      tx_bytes += rtf_put (fifo_bypass_phy_kern2user, &dataP[tx_bytes],
                           sizeP-tx_bytes);
    } else {
      tx_bytes += rtf_put (fifo_bypass_phy_kern2user, &dataP[tx_bytes],1000);
Cedric Roux's avatar
Cedric Roux committed
555
    }
556
  }
Cedric Roux's avatar
Cedric Roux committed
557

558
559
560
561
  //RG_tx_mutex_var=0;
  pthread_mutex_unlock(&Tx_mutex);

  return tx_bytes;
562
563
564
}
#endif

Cedric Roux's avatar
   
Cedric Roux committed
565
566
567
#if defined(ENABLE_PGM_TRANSPORT)
void bypass_tx_nack(unsigned int frame, unsigned int next_slot)
{
568
  bypass_tx_data(NACK_TRANSPORT, frame, next_slot);
Cedric Roux's avatar
   
Cedric Roux committed
569
570
571
}
#endif

572
/***************************************************************************/
Cedric Roux's avatar
Cedric Roux committed
573
574
void bypass_tx_data(emu_transport_info_t Type, unsigned int frame, unsigned int next_slot)
{
575
576
577
  /***************************************************************************/
  unsigned int         num_flows;
  bypass_msg_header_t *messg;
Cedric Roux's avatar
Cedric Roux committed
578

579
580
  LOG_D(EMU, "Entering bypass_tx [%s] for frame %d next_slot %d\n",
        map_int_to_str(transport_names, Type), frame, next_slot);
Cedric Roux's avatar
Cedric Roux committed
581

582
583
584
585
586
  int n_enb,n_ue, CC_id,n_dci,total_tbs=0,total_size=0;
  messg = (bypass_msg_header_t *) (
            &bypass_tx_buffer[sizeof (bypass_proto2multicast_header_t)]);
  num_flows = 0;
  messg->master_id       = oai_emulation.info.master_id; //Master_id;
Cedric Roux's avatar
Cedric Roux committed
587

588
589
590
591
592
593
594
  messg->nb_enb          = oai_emulation.info.nb_enb_local; //Master_id;
  messg->nb_ue           = oai_emulation.info.nb_ue_local; //Master_id;
  messg->nb_flow         = num_flows;
  messg->frame           = frame;
  messg->subframe        = next_slot>>1;
  messg->seq_num         = seq_num_tx;
  messg->failing_master_id = 0;
Cedric Roux's avatar
Cedric Roux committed
595

596
  seq_num_tx++;
Cedric Roux's avatar
Cedric Roux committed
597

598
599
  byte_tx_count = sizeof (bypass_msg_header_t) + sizeof (
                    bypass_proto2multicast_header_t);
Cedric Roux's avatar
Cedric Roux committed
600

Cedric Roux's avatar
   
Cedric Roux committed
601
#if defined(ENABLE_PGM_TRANSPORT)
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619

  if (Type == NACK_TRANSPORT) {
    int i;
    messg->Message_type = EMU_TRANSPORT_NACK;

    for (i = 0; i < oai_emulation.info.nb_master; i++) {
      /* Skip our id */
      if (i == oai_emulation.info.master_id)
        continue;

      if ((Master_list_rx & (1 << i)) == 0) {
        messg->failing_master_id = i;
        break;
      }
    }

    LOG_T(EMU,"[TX_DATA] NACK TRANSPORT\n");
  } else
Cedric Roux's avatar
   
Cedric Roux committed
620
#endif
Cedric Roux's avatar
Cedric Roux committed
621
    if (Type == WAIT_PM_TRANSPORT) {
622
623
      messg->Message_type = EMU_TRANSPORT_INFO_WAIT_PM;
      LOG_T(EMU,"[TX_DATA] WAIT SYNC PM TRANSPORT\n");
Cedric Roux's avatar
Cedric Roux committed
624
    } else if (Type == WAIT_SM_TRANSPORT) {
625
626
      messg->Message_type = EMU_TRANSPORT_INFO_WAIT_SM;
      LOG_T(EMU,"[TX_DATA] WAIT SYNC SM TRANSPORT\n");
Cedric Roux's avatar
Cedric Roux committed
627
    } else if (Type == SYNC_TRANSPORT) {
628
629
630
631
632
633
      messg->Message_type = EMU_TRANSPORT_INFO_SYNC;
      /* make sure that sync messages from the masters are received in
       * increasing order of master id
       */
      sleep(oai_emulation.info.master_id+1);
      LOG_T(EMU,"[TX_DATA] SYNC TRANSPORT\n");
Cedric Roux's avatar
Cedric Roux committed
634
    } else if(Type==ENB_TRANSPORT) {
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669

      messg->Message_type = EMU_TRANSPORT_INFO_ENB;
      total_size=0;
      total_tbs=0;

      for (n_enb=oai_emulation.info.first_enb_local;
           n_enb<(oai_emulation.info.first_enb_local+oai_emulation.info.nb_enb_local);
           n_enb++)
        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
          total_tbs=0;
          LOG_D(EMU,"[TX_DATA] Frame %d subframe %d CC id %d : ENB TRANSPORT: num dci %d \n",
                frame, next_slot>>1, CC_id,
                eNB_transport_info[n_enb][CC_id].num_pmch +
                eNB_transport_info[n_enb][CC_id].num_ue_spec_dci +
                eNB_transport_info[n_enb][CC_id].num_common_dci   );

          for (n_dci = 0; n_dci < (eNB_transport_info[n_enb][CC_id].num_pmch +
                                   eNB_transport_info[n_enb][CC_id].num_ue_spec_dci +
                                   eNB_transport_info[n_enb][CC_id].num_common_dci);
               n_dci++) {
            total_tbs +=eNB_transport_info[n_enb][CC_id].tbs[n_dci];
          }

          if (total_tbs <= MAX_TRANSPORT_BLOCKS_BUFFER_SIZE) {
            total_size = sizeof(eNB_transport_info_t) + total_tbs -
                         MAX_TRANSPORT_BLOCKS_BUFFER_SIZE;
          } else {
            LOG_E(EMU,
                  "[eNB]running out of memory for the eNB emulation transport buffer of size %d\n",
                  MAX_TRANSPORT_BLOCKS_BUFFER_SIZE);
          }

          memcpy(&bypass_tx_buffer[byte_tx_count], (char *)&eNB_transport_info[n_enb][CC_id],
                 total_size);
          byte_tx_count += total_size;
Cedric Roux's avatar
Cedric Roux committed
670
671
        }
    } else if (Type == UE_TRANSPORT) {
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
      LOG_D(EMU,"[TX_DATA] UE TRANSPORT\n");
      messg->Message_type = EMU_TRANSPORT_INFO_UE;
      total_size=0;
      total_tbs=0; // compute the actual size of transport_blocks

      for (n_ue = oai_emulation.info.first_ue_local;
           n_ue < (oai_emulation.info.first_ue_local+oai_emulation.info.nb_ue_local);
           n_ue++) {
        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
          for (n_enb=0; n_enb<UE_transport_info[n_ue][CC_id].num_eNB; n_enb++) {
            total_tbs+=UE_transport_info[n_ue][CC_id].tbs[n_enb];
          }

          if (total_tbs <= MAX_TRANSPORT_BLOCKS_BUFFER_SIZE) {
            total_size = sizeof(UE_transport_info_t)+total_tbs-
                         MAX_TRANSPORT_BLOCKS_BUFFER_SIZE;
          } else {
            LOG_E(EMU,
                  "[UE]running out of memory for the UE emulation transport buffer of size %d\n",
                  MAX_TRANSPORT_BLOCKS_BUFFER_SIZE);
          }

#ifdef DEBUG_EMU
          LOG_D(EMU,"[UE %d][eNB %d][CC %d] total size %d\n",
                n_ue, n_enb, CC_id,total_size);
#endif
          memcpy(&bypass_tx_buffer[byte_tx_count], (char *)&UE_transport_info[n_ue][CC_id],
                 total_size);
          byte_tx_count += total_size;
        }
      }
Cedric Roux's avatar
Cedric Roux committed
703
    } else if (Type == RELEASE_TRANSPORT) {
704
      messg->Message_type = EMU_TRANSPORT_INFO_RELEASE;
Cedric Roux's avatar
Cedric Roux committed
705
    } else {
706
      LOG_E(EMU,"[TX_DATA] UNKNOWN MSG  \n");
707
    }
Cedric Roux's avatar
Cedric Roux committed
708

709
710
  ((bypass_proto2multicast_header_t *) bypass_tx_buffer)->size = byte_tx_count -
      sizeof (bypass_proto2multicast_header_t);
Cedric Roux's avatar
Cedric Roux committed
711

712
#if defined(ENABLE_PGM_TRANSPORT)
713
714
  pgm_link_send_msg(oai_emulation.info.multicast_group,
                    (uint8_t *)bypass_tx_buffer, byte_tx_count);
715
#else
716
717
  multicast_link_write_sock(oai_emulation.info.multicast_group,
                            bypass_tx_buffer, byte_tx_count);
718
#endif
Cedric Roux's avatar
Cedric Roux committed
719

720
721
722
  LOG_D(EMU, "Frame %d, subframe %d (%d): Sent %d bytes [%s] with master_id %d and seq %"PRIuMAX"\n",
        frame, next_slot>>1, next_slot,byte_tx_count, map_int_to_str(transport_names, Type),
        messg->master_id, messg->seq_num);
723
724
}

Cedric Roux's avatar
Cedric Roux committed
725
#ifndef USER_MODE
726
/*********************************************************************************************************************/
Cedric Roux's avatar
Cedric Roux committed
727
728
int bypass_tx_handler(unsigned int fifo, int rw)
{
729
730
731
  /***************************************************************************/
  if(++N_R==N_P) {
    rtf_reset(fifo_bypass_phy_kern2user);
Cedric Roux's avatar
Cedric Roux committed
732

733
734
    Tx_mutex_var=1;
    N_R=0;
Cedric Roux's avatar
Cedric Roux committed
735

736
737
    pthread_cond_signal(&Tx_cond);
  }
738
739
740
}
#endif