nfapi_pnf.c 62.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>

#include "debug.h"
#include "nfapi_pnf_interface.h"
#include "nfapi.h"
#include "nfapi_pnf.h"
#include "common/ran_context.h"
//#include "openair1/PHY/vars.h"
extern RAN_CONTEXT_t RC;

#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <assert.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <errno.h>

#include <vendor_ext.h>
#include "fapi_stub.h"
25
//#include "fapi_l1.h"
26
#include "UTIL/LOG/log.h"
27
28
29

#define NUM_P5_PHY 2

30
extern void phy_init_RU(RU_t*);
31
extern int config_sync_var;
32

33
34
35
36
37
38
39
extern pthread_cond_t nfapi_sync_cond;
extern pthread_mutex_t nfapi_sync_mutex;
extern int nfapi_sync_var;

extern int sync_var;

extern void init_eNB_afterRU(void);
40
41
42
43
44
extern void handle_nfapi_dci_dl_pdu(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc, nfapi_dl_config_request_pdu_t *dl_config_pdu);
extern void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, nfapi_ul_config_request_pdu_t *ul_config_pdu, uint16_t frame,uint8_t subframe,uint8_t srs_present);
extern void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,  nfapi_dl_config_request_pdu_t *dl_config_pdu, uint8_t codeword_index, uint8_t *sdu);
extern void handle_nfapi_hi_dci0_dci_pdu(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu);
extern void handle_nfapi_hi_dci0_hi_pdu(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, nfapi_hi_dci0_request_pdu_t *hi_dci0_config_pdu);
45
extern void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, nfapi_dl_config_request_pdu_t *dl_config_pdu, uint8_t *sdu);
46

47
extern uint8_t  nfapi_mode;
48
49

nfapi_tx_request_pdu_t* tx_request_pdu[1023][10][10]; // [frame][subframe][max_num_pdus]
50
51


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
uint16_t phy_antenna_capability_values[] = { 1, 2, 4, 8, 16 };

nfapi_pnf_param_response_t g_pnf_param_resp;


nfapi_pnf_p7_config_t *p7_config_g = NULL;

void* pnf_allocate(size_t size)
{
  //DJP
  //return (void*)memory_pool::allocate(size);
  return malloc(size);
}

void pnf_deallocate(void* ptr)
{
  //DJP
  //memory_pool::deallocate((uint8_t*)ptr);
  free(ptr);
}


//class udp_data
//DJP
typedef struct 
{
  //public:
  uint8_t enabled;
  uint32_t rx_port;
  uint32_t tx_port;
  //std::string tx_addr;
  char tx_addr[80];
}udp_data;

//class phy_info
//DJP
typedef struct 
{
#if 0
  public:

    phy_info()
      : first_subframe_ind(0), fapi(0),
      dl_ues_per_subframe(0), ul_ues_per_subframe(0), 
      timing_window(0), timing_info_mode(0), timing_info_period(0)
  {
    index = 0;
    id = 0;

    local_port = 0;
    remote_addr = 0;
    remote_port = 0;

    duplex_mode = 0;
    dl_channel_bw_support = 0;
    ul_channel_bw_support = 0;
    num_dl_layers_supported = 0;
    num_ul_layers_supported = 0;
    release_supported = 0;
    nmm_modes_supported = 0;
  }
#endif

    uint16_t index;
    uint16_t id;
    //std::vector<uint8_t> rfs;
    //std::vector<uint8_t> excluded_rfs;
    uint8_t rfs[2];
    uint8_t excluded_rfs[2];

    udp_data udp;

    //std::string local_addr;
    char local_addr[80];
    int local_port;

    char* remote_addr;
    int remote_port;

    uint8_t duplex_mode;
    uint16_t dl_channel_bw_support;
    uint16_t ul_channel_bw_support;
    uint8_t num_dl_layers_supported;
    uint8_t num_ul_layers_supported;
    uint16_t release_supported;
    uint8_t nmm_modes_supported;

    uint8_t dl_ues_per_subframe;
    uint8_t ul_ues_per_subframe;

    uint8_t first_subframe_ind;

    // timing information recevied from the vnf
    uint8_t timing_window;
    uint8_t timing_info_mode;
    uint8_t timing_info_period;

    //fapi_t* fapi;

}phy_info;

//class rf_info
//DJP
typedef struct 
{
  //public:
  uint16_t index;
  uint16_t band;
  int16_t max_transmit_power;
  int16_t min_transmit_power;
  uint8_t num_antennas_supported;
  uint32_t min_downlink_frequency;
  uint32_t max_downlink_frequency;
  uint32_t max_uplink_frequency;
  uint32_t min_uplink_frequency;
}rf_info;


//class pnf_info
//DJP
typedef struct 
{
#if 0
  public:

    pnf_info() 
      : release(13), wireshark_test_mode(0),
      max_total_power(0), oui(0)

  {
    release = 0;

    sync_mode = 0;
    location_mode = 0;
    dl_config_timing = 0;
    ul_config_timing = 0;
    tx_timing = 0;
    hi_dci0_timing = 0;

    max_phys = 0;
    max_total_bw = 0;
    max_total_dl_layers = 0;
    max_total_ul_layers = 0;
    shared_bands = 0;
    shared_pa = 0;

  }
#endif

    int release;
    //DJPstd::vector<phy_info> phys;
    //std::vector<rf_info> rfs;
    phy_info phys[2];
    rf_info rfs[2];

    uint8_t sync_mode;
    uint8_t location_mode;
    uint8_t location_coordinates[6];
    uint32_t dl_config_timing;
    uint32_t ul_config_timing;
    uint32_t tx_timing;
    uint32_t hi_dci0_timing;

    uint16_t max_phys;
    uint16_t max_total_bw;
    uint16_t max_total_dl_layers;
    uint16_t max_total_ul_layers;
    uint8_t shared_bands;
    uint8_t shared_pa;
    int16_t max_total_power;
    uint8_t oui;

    uint8_t wireshark_test_mode;

}pnf_info;

// DJP struct pnf_phy_user_data_t
typedef struct 
{
  uint16_t phy_id;
  nfapi_pnf_config_t* config;
  phy_info* phy;
  nfapi_pnf_p7_config_t* p7_config;
}pnf_phy_user_data_t;

237
238
239
static pnf_info pnf;
static pthread_t pnf_start_pthread;

240

241
242
243
extern void nfapi_log(char *file, char *func, int line, int comp, int level, const char* format, va_list args);

void pnf_nfapi_trace(nfapi_trace_level_t nfapi_level, const char* message, ...)
244
{
David Price's avatar
David Price committed
245
#if 1
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
273
274
275

  va_list    args;
  int oai_level;

  if (nfapi_level==NFAPI_TRACE_ERROR)
  {
    oai_level = LOG_ERR;
  }
  else if (nfapi_level==NFAPI_TRACE_WARN)
  {
    oai_level = LOG_WARNING;
  }
  else if (nfapi_level==NFAPI_TRACE_NOTE)
  {
    oai_level = LOG_INFO;
  }
  else if (nfapi_level==NFAPI_TRACE_INFO)
  {
    oai_level = LOG_INFO;
  }
  else
  {
    oai_level = LOG_INFO;
  }

  va_start(args, message);
  nfapi_log("FILE>", "FUNC", 999, PHY, oai_level, message, args);
  va_end(args);
  #else
  va_list    args;
276
277
278
  va_start(args, message);
  vprintf(message, args);
  va_end(args);
279
  #endif
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
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
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
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
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
}

void pnf_set_thread_priority(int priority)
{
  //printf("%s(priority:%d)\n", __FUNCTION__, priority);

  pthread_attr_t ptAttr;

  struct sched_param schedParam;
  schedParam.__sched_priority = priority; //79;
  if(sched_setscheduler(0, SCHED_RR, &schedParam) != 0)
  {
    printf("failed to set SCHED_RR\n");
  }

  if(pthread_attr_setschedpolicy(&ptAttr, SCHED_RR) != 0)
  {
    printf("failed to set pthread SCHED_RR %d\n", errno);
  }

  pthread_attr_setinheritsched(&ptAttr, PTHREAD_EXPLICIT_SCHED);

  struct sched_param thread_params;
  thread_params.sched_priority = 20;
  if(pthread_attr_setschedparam(&ptAttr, &thread_params) != 0)
  {
    printf("failed to set sched param\n");
  }
}

void* pnf_p7_thread_start(void* ptr)
{
  NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] P7 THREAD %s\n", __FUNCTION__);

  pnf_set_thread_priority(79);

  nfapi_pnf_p7_config_t* config = (nfapi_pnf_p7_config_t*)ptr;
  nfapi_pnf_p7_start(config);

  return 0;
}



int pnf_param_request(nfapi_pnf_config_t* config, nfapi_pnf_param_request_t* req)
{
  printf("[PNF] pnf param request\n");

  nfapi_pnf_param_response_t resp;
  memset(&resp, 0, sizeof(resp));
  resp.header.message_id = NFAPI_PNF_PARAM_RESPONSE;
  resp.error_code = NFAPI_MSG_OK;

  pnf_info* pnf = (pnf_info*)(config->user_data);

  resp.pnf_param_general.tl.tag = NFAPI_PNF_PARAM_GENERAL_TAG;
  resp.pnf_param_general.nfapi_sync_mode = pnf->sync_mode;
  resp.pnf_param_general.location_mode = pnf->location_mode;
  //uint8_t location_coordinates[NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH];
  resp.pnf_param_general.dl_config_timing = pnf->dl_config_timing;
  resp.pnf_param_general.tx_timing = pnf->tx_timing;
  resp.pnf_param_general.ul_config_timing = pnf->ul_config_timing;
  resp.pnf_param_general.hi_dci0_timing = pnf->hi_dci0_timing;
  resp.pnf_param_general.maximum_number_phys = pnf->max_phys;
  resp.pnf_param_general.maximum_total_bandwidth = pnf->max_total_bw;
  resp.pnf_param_general.maximum_total_number_dl_layers = pnf->max_total_dl_layers;
  resp.pnf_param_general.maximum_total_number_ul_layers = pnf->max_total_ul_layers;
  resp.pnf_param_general.shared_bands = pnf->shared_bands;
  resp.pnf_param_general.shared_pa = pnf->shared_pa;
  resp.pnf_param_general.maximum_total_power = pnf->max_total_power;
  //uint8_t oui[NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH];

  resp.pnf_phy.tl.tag = NFAPI_PNF_PHY_TAG;
  //DJP resp.pnf_phy.number_of_phys = pnf->phys.size();
  resp.pnf_phy.number_of_phys = 1;

  //for(int i = 0; i < pnf->phys.size(); ++i)
  for(int i = 0; i < 1; ++i)
  {
    resp.pnf_phy.phy[i].phy_config_index = pnf->phys[i].index; 
    resp.pnf_phy.phy[i].downlink_channel_bandwidth_supported = pnf->phys[i].dl_channel_bw_support;
    resp.pnf_phy.phy[i].uplink_channel_bandwidth_supported = pnf->phys[i].ul_channel_bw_support;
    resp.pnf_phy.phy[i].number_of_dl_layers_supported = pnf->phys[i].num_dl_layers_supported;
    resp.pnf_phy.phy[i].number_of_ul_layers_supported = pnf->phys[i].num_ul_layers_supported;
    resp.pnf_phy.phy[i].maximum_3gpp_release_supported = pnf->phys[i].release_supported;
    resp.pnf_phy.phy[i].nmm_modes_supported = pnf->phys[i].nmm_modes_supported;

    //DJP resp.pnf_phy.phy[i].number_of_rfs = pnf->phys[i].rfs.size();
    resp.pnf_phy.phy[i].number_of_rfs = 2;
    //for(int j = 0; j < pnf->phys[i].rfs.size(); ++j)
    for(int j = 0; j < 1; ++j)
    {
      resp.pnf_phy.phy[i].rf_config[j].rf_config_index = pnf->phys[i].rfs[j];
    }

    //DJP resp.pnf_phy.phy[i].number_of_rf_exclusions = pnf->phys[i].excluded_rfs.size();
    resp.pnf_phy.phy[i].number_of_rf_exclusions = 0;
    //DJP for(int j = 0; j < pnf->phys[i].excluded_rfs.size(); ++j)
    for(int j = 0; j < 0; ++j)
    {
      resp.pnf_phy.phy[i].excluded_rf_config[j].rf_config_index = pnf->phys[i].excluded_rfs[j];
    }
  }


  resp.pnf_rf.tl.tag = NFAPI_PNF_RF_TAG;
  //DJPresp.pnf_rf.number_of_rfs = pnf->rfs.size();
  resp.pnf_rf.number_of_rfs = 2;

  //for(int i = 0; i < pnf->rfs.size(); ++i)
  for(int i = 0; i < 2; ++i)
  {
    resp.pnf_rf.rf[i].rf_config_index = pnf->rfs[i].index; 
    resp.pnf_rf.rf[i].band = pnf->rfs[i].band;
    resp.pnf_rf.rf[i].maximum_transmit_power = pnf->rfs[i].max_transmit_power; 
    resp.pnf_rf.rf[i].minimum_transmit_power = pnf->rfs[i].min_transmit_power;
    resp.pnf_rf.rf[i].number_of_antennas_suppported = pnf->rfs[i].num_antennas_supported;
    resp.pnf_rf.rf[i].minimum_downlink_frequency = pnf->rfs[i].min_downlink_frequency;
    resp.pnf_rf.rf[i].maximum_downlink_frequency = pnf->rfs[i].max_downlink_frequency;
    resp.pnf_rf.rf[i].minimum_uplink_frequency = pnf->rfs[i].min_uplink_frequency;
    resp.pnf_rf.rf[i].maximum_uplink_frequency = pnf->rfs[i].max_uplink_frequency;
  }

  if(pnf->release >= 10)
  {
    resp.pnf_phy_rel10.tl.tag = NFAPI_PNF_PHY_REL10_TAG;
    //DJPresp.pnf_phy_rel10.number_of_phys = pnf->phys.size();
    resp.pnf_phy_rel10.number_of_phys = 1;

    //for(int i = 0; i < pnf->phys.size(); ++i)
    for(int i = 0; i < 1; ++i)
    {
      resp.pnf_phy_rel10.phy[i].phy_config_index = pnf->phys[i].index; 
      resp.pnf_phy_rel10.phy[i].transmission_mode_7_supported = 0;
      resp.pnf_phy_rel10.phy[i].transmission_mode_8_supported = 1;
      resp.pnf_phy_rel10.phy[i].two_antenna_ports_for_pucch = 0;
      resp.pnf_phy_rel10.phy[i].transmission_mode_9_supported = 1;
      resp.pnf_phy_rel10.phy[i].simultaneous_pucch_pusch = 0;
      resp.pnf_phy_rel10.phy[i].four_layer_tx_with_tm3_and_tm4 = 1;

    }
  }

  if(pnf->release >= 11)
  {
    resp.pnf_phy_rel11.tl.tag = NFAPI_PNF_PHY_REL11_TAG;
    //DJP resp.pnf_phy_rel11.number_of_phys = pnf->phys.size();
    resp.pnf_phy_rel11.number_of_phys = 1;

    //DJP for(int i = 0; i < pnf->phys.size(); ++i)
    for(int i = 0; i < 1; ++i)
    {
      resp.pnf_phy_rel11.phy[i].phy_config_index = pnf->phys[i].index; 
      resp.pnf_phy_rel11.phy[i].edpcch_supported = 0;
      resp.pnf_phy_rel11.phy[i].multi_ack_csi_reporting = 1;
      resp.pnf_phy_rel11.phy[i].pucch_tx_diversity = 0;
      resp.pnf_phy_rel11.phy[i].ul_comp_supported = 1;
      resp.pnf_phy_rel11.phy[i].transmission_mode_5_supported = 0;
    }
  }

  if(pnf->release >= 12)
  {
    resp.pnf_phy_rel12.tl.tag = NFAPI_PNF_PHY_REL12_TAG;
    //DJP resp.pnf_phy_rel12.number_of_phys = pnf->phys.size();
    resp.pnf_phy_rel12.number_of_phys = 1;

    //DJP for(int i = 0; i < pnf->phys.size(); ++i)
    for(int i = 0; i < 1; ++i)
    {
      resp.pnf_phy_rel12.phy[i].phy_config_index = pnf->phys[i].index; 
      resp.pnf_phy_rel12.phy[i].csi_subframe_set = 0;
      resp.pnf_phy_rel12.phy[i].enhanced_4tx_codebook = 2; // yes this is invalid
      resp.pnf_phy_rel12.phy[i].drs_supported = 0;
      resp.pnf_phy_rel12.phy[i].ul_64qam_supported = 1;
      resp.pnf_phy_rel12.phy[i].transmission_mode_10_supported = 0;
      resp.pnf_phy_rel12.phy[i].alternative_bts_indices = 1;
    }
  }

  if(pnf->release >= 13)
  {
    resp.pnf_phy_rel13.tl.tag = NFAPI_PNF_PHY_REL13_TAG;
    //DJP resp.pnf_phy_rel13.number_of_phys = pnf->phys.size();
    resp.pnf_phy_rel13.number_of_phys = 1;

    //for(int i = 0; i < pnf->phys.size(); ++i)
    for(int i = 0; i < 1; ++i)
    {
      resp.pnf_phy_rel13.phy[i].phy_config_index = pnf->phys[i].index; 
      resp.pnf_phy_rel13.phy[i].pucch_format4_supported = 0;
      resp.pnf_phy_rel13.phy[i].pucch_format5_supported = 1;
      resp.pnf_phy_rel13.phy[i].more_than_5_ca_support = 0;
      resp.pnf_phy_rel13.phy[i].laa_supported = 1;
      resp.pnf_phy_rel13.phy[i].laa_ending_in_dwpts_supported = 0;
      resp.pnf_phy_rel13.phy[i].laa_starting_in_second_slot_supported = 1;
      resp.pnf_phy_rel13.phy[i].beamforming_supported = 0;
      resp.pnf_phy_rel13.phy[i].csi_rs_enhancement_supported = 1;
      resp.pnf_phy_rel13.phy[i].drms_enhancement_supported = 0;
      resp.pnf_phy_rel13.phy[i].srs_enhancement_supported = 1;
    }

    resp.pnf_phy_rel13_nb_iot.tl.tag = NFAPI_PNF_PHY_REL13_NB_IOT_TAG;
    //DJP resp.pnf_phy_rel13_nb_iot.number_of_phys = pnf->phys.size();		
    resp.pnf_phy_rel13_nb_iot.number_of_phys = 1;

    //for(int i = 0; i < pnf->phys.size(); ++i)
    for(int i = 0; i < 1; ++i)
    {
      resp.pnf_phy_rel13_nb_iot.phy[i].phy_config_index = pnf->phys[i].index; 

      //DJP resp.pnf_phy_rel13_nb_iot.phy[i].number_of_rfs = pnf->phys[i].rfs.size();
      resp.pnf_phy_rel13_nb_iot.phy[i].number_of_rfs = 1;
      //DJP for(int j = 0; j < pnf->phys[i].rfs.size(); ++j)
      for(int j = 0; j < 1; ++j)
      {
        resp.pnf_phy_rel13_nb_iot.phy[i].rf_config[j].rf_config_index = pnf->phys[i].rfs[j];
      }

      //DJP resp.pnf_phy_rel13_nb_iot.phy[i].number_of_rf_exclusions = pnf->phys[i].excluded_rfs.size();
      resp.pnf_phy_rel13_nb_iot.phy[i].number_of_rf_exclusions = 1;
      //DJP for(int j = 0; j < pnf->phys[i].excluded_rfs.size(); ++j)
      for(int j = 0; j < 1; ++j)
      {
        resp.pnf_phy_rel13_nb_iot.phy[i].excluded_rf_config[j].rf_config_index = pnf->phys[i].excluded_rfs[j];
      }

      resp.pnf_phy_rel13_nb_iot.phy[i].number_of_dl_layers_supported = pnf->phys[i].num_dl_layers_supported;
      resp.pnf_phy_rel13_nb_iot.phy[i].number_of_ul_layers_supported = pnf->phys[i].num_ul_layers_supported;
      resp.pnf_phy_rel13_nb_iot.phy[i].maximum_3gpp_release_supported = pnf->phys[i].release_supported;
      resp.pnf_phy_rel13_nb_iot.phy[i].nmm_modes_supported = pnf->phys[i].nmm_modes_supported;

    }
  }


  nfapi_pnf_pnf_param_resp(config, &resp);

  return 0;
}

int pnf_config_request(nfapi_pnf_config_t* config, nfapi_pnf_config_request_t* req)
{
  printf("[PNF] pnf config request\n");

  pnf_info* pnf = (pnf_info*)(config->user_data);

#if 0
  for(int i = 0; i < req->pnf_phy_rf_config.number_phy_rf_config_info; ++i)
  {
    auto found = std::find_if(pnf->phys.begin(), pnf->phys.end(), [&](phy_info& item)
        { return item.index == req->pnf_phy_rf_config.phy_rf_config[i].phy_config_index; });

    if(found != pnf->phys.end())
    {
      phy_info& phy = (*found);
      phy.id = req->pnf_phy_rf_config.phy_rf_config[i].phy_id;
      printf("[PNF] pnf config request assigned phy_id %d to phy_config_index %d\n", phy.id, req->pnf_phy_rf_config.phy_rf_config[i].phy_config_index);
    }
    else
    {
      // did not find the phy
      printf("[PNF] pnf config request did not find phy_config_index %d\n", req->pnf_phy_rf_config.phy_rf_config[i].phy_config_index);
    }

  }
#endif
  //DJP
  phy_info *phy = pnf->phys;
  phy->id = req->pnf_phy_rf_config.phy_rf_config[0].phy_id;
  printf("[PNF] pnf config request assigned phy_id %d to phy_config_index %d\n", phy->id, req->pnf_phy_rf_config.phy_rf_config[0].phy_config_index);
  //DJP

  nfapi_pnf_config_response_t resp;
  memset(&resp, 0, sizeof(resp));
  resp.header.message_id = NFAPI_PNF_CONFIG_RESPONSE;
  resp.error_code = NFAPI_MSG_OK;
  nfapi_pnf_pnf_config_resp(config, &resp);
  printf("[PNF] Sent pnf_config_resp\n");

  return 0;
}

void nfapi_send_pnf_start_resp(nfapi_pnf_config_t* config, uint16_t phy_id)
{
  printf("Sending NFAPI_START_RESPONSE config:%p phy_id:%d\n", config, phy_id);

  nfapi_start_response_t start_resp;
  memset(&start_resp, 0, sizeof(start_resp));
  start_resp.header.message_id = NFAPI_START_RESPONSE;
  start_resp.header.phy_id = phy_id;
  start_resp.error_code = NFAPI_MSG_OK;

  nfapi_pnf_start_resp(config, &start_resp);
}

int pnf_start_request(nfapi_pnf_config_t* config, nfapi_pnf_start_request_t* req)
{
  printf("Received NFAPI_PNF_START_REQUEST\n");

  pnf_info* pnf = (pnf_info*)(config->user_data);

  // start all phys that have been configured
  //for(phy_info& phy : pnf->phys)
  phy_info* phy = pnf->phys;
  if(phy->id != 0)
  {
    //auto found = std::find_if(pnf->phys.begin(), pnf->phys.end(), [&](phy_info& item)
    //		{ return item.id == req->header.phy_id; });
    //
    //	if(found != pnf->phys.end())
    //	{
    //		phy_info& phy = (*found);
    //}

    nfapi_pnf_start_response_t resp;
    memset(&resp, 0, sizeof(resp));
    resp.header.message_id = NFAPI_PNF_START_RESPONSE;
    resp.error_code = NFAPI_MSG_OK;
    nfapi_pnf_pnf_start_resp(config, &resp);
    printf("[PNF] Sent NFAPI_PNF_START_RESP\n");
  }
  return 0;
}

int pnf_stop_request(nfapi_pnf_config_t* config, nfapi_pnf_stop_request_t* req)
{
  printf("[PNF] Received NFAPI_PNF_STOP_REQ\n");

  nfapi_pnf_stop_response_t resp;
  memset(&resp, 0, sizeof(resp));
  resp.header.message_id = NFAPI_PNF_STOP_RESPONSE;
  resp.error_code = NFAPI_MSG_OK;
  nfapi_pnf_pnf_stop_resp(config, &resp);
  printf("[PNF] Sent NFAPI_PNF_STOP_REQ\n");

  return 0;
}

int param_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_param_request_t* req)
{
  printf("[PNF] Received NFAPI_PARAM_REQUEST phy_id:%d\n", req->header.phy_id);

  //pnf_info* pnf = (pnf_info*)(config->user_data);

  nfapi_param_response_t nfapi_resp;

627
628
  pnf_info* pnf = (pnf_info*)(config->user_data);

629
630
631
632
633
634
635
  memset(&nfapi_resp, 0, sizeof(nfapi_resp));
  nfapi_resp.header.message_id = NFAPI_PARAM_RESPONSE;
  nfapi_resp.header.phy_id = req->header.phy_id;
  nfapi_resp.error_code = 0; // DJP - what value???

  struct sockaddr_in pnf_p7_sockaddr;

636
  pnf_p7_sockaddr.sin_addr.s_addr = inet_addr(pnf->phys[0].local_addr);
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
670
671
672
673
674
675
676
677
678
679
680
681
682
  nfapi_resp.nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG;
  memcpy(nfapi_resp.nfapi_config.p7_pnf_address_ipv4.address, &pnf_p7_sockaddr.sin_addr.s_addr, 4);
  nfapi_resp.num_tlv++;

  // P7 PNF Port
  nfapi_resp.nfapi_config.p7_pnf_port.tl.tag = NFAPI_NFAPI_P7_PNF_PORT_TAG;
  nfapi_resp.nfapi_config.p7_pnf_port.value = 32123; // DJP - hard code alert!!!! FIXME TODO
  nfapi_resp.num_tlv++;

  nfapi_pnf_param_resp(config, &nfapi_resp);

  printf("[PNF] Sent NFAPI_PARAM_RESPONSE phy_id:%d number_of_tlvs:%u\n", req->header.phy_id, nfapi_resp.num_tlv);
#if 0
  //DJP
  auto found = std::find_if(pnf->phys.begin(), pnf->phys.end(), [&](phy_info& item)
      { return item.id == req->header.phy_id; });

  if(found != pnf->phys.end())
#endif
  {
    //DJP phy_info& phy_info = (*found);
    //phy_info *phy_info = pnf->phys;

  }
#if 0
  else
  {
    // did not find the phy
  }
#endif

  printf("[PNF] param request .. exit\n");

  return 0;
}

// From MAC config.c
extern uint32_t from_earfcn(int eutra_bandP,uint32_t dl_earfcn);
extern int32_t get_uldl_offset(int eutra_bandP);

int config_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_config_request_t* req)
{
  printf("[PNF] Received NFAPI_CONFIG_REQ phy_id:%d\n", req->header.phy_id);

  pnf_info* pnf = (pnf_info*)(config->user_data);
  uint8_t num_tlv = 0;
683
684
  struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701

#if 0
  //DJP
  auto found = std::find_if(pnf->phys.begin(), pnf->phys.end(), [&](phy_info& item)
      { return item.id == req->header.phy_id; });

  if(found != pnf->phys.end())
  {
    phy_info& phy_info = (*found);
  }
#endif
  //DJP 
  phy_info* phy_info = pnf->phys;

  if(req->nfapi_config.timing_window.tl.tag == NFAPI_NFAPI_TIMING_WINDOW_TAG)
  {
    phy_info->timing_window = req->nfapi_config.timing_window.value;
702
    printf("Phy_info:Timing window:%u NFAPI_CONFIG:timing_window:%u\n", phy_info->timing_window, req->nfapi_config.timing_window.value);
703
704
705
706
707
    num_tlv++;
  }

  if(req->nfapi_config.timing_info_mode.tl.tag == NFAPI_NFAPI_TIMING_INFO_MODE_TAG)
  {
708
    printf("timing info mode:%d\n", req->nfapi_config.timing_info_mode.value);
709
710
711
712
713
714
715
716
717
718
719
    phy_info->timing_info_mode = req->nfapi_config.timing_info_mode.value;
    num_tlv++;
  }
  else 
  {
    phy_info->timing_info_mode = 0;
    printf("NO timing info mode provided\n");
  }

  if(req->nfapi_config.timing_info_period.tl.tag == NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG)
  {
720
    printf("timing info period provided value:%d\n", req->nfapi_config.timing_info_period.value);
721
722
723
724
725
726
727
728
729
730
731
    phy_info->timing_info_period = req->nfapi_config.timing_info_period.value;
    num_tlv++;
  }
  else 
  {
    phy_info->timing_info_period = 0;
  }

  if(req->rf_config.dl_channel_bandwidth.tl.tag == NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG)
  {
    phy_info->dl_channel_bw_support = req->rf_config.dl_channel_bandwidth.value;
732
    fp->N_RB_DL = req->rf_config.dl_channel_bandwidth.value;
733
    num_tlv++;
734
    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG N_RB_DL:%u\n", __FUNCTION__, fp->N_RB_DL);
735
736
737
738
739
740
741
742
743
  }
  else
  {
    NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() Missing NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG\n", __FUNCTION__);
  }

  if(req->rf_config.ul_channel_bandwidth.tl.tag == NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG)
  {
    phy_info->ul_channel_bw_support = req->rf_config.ul_channel_bandwidth.value;
744
    fp->N_RB_UL = req->rf_config.ul_channel_bandwidth.value;
745
746
747
748
749
750
    num_tlv++;
  }

  if(req->nfapi_config.rf_bands.tl.tag == NFAPI_NFAPI_RF_BANDS_TAG)
  {
    pnf->rfs[0].band = req->nfapi_config.rf_bands.rf_band[0];
751
    fp->eutra_band = req->nfapi_config.rf_bands.rf_band[0];
752
753
754
755
756
    num_tlv++;
  }

  if(req->nfapi_config.earfcn.tl.tag == NFAPI_NFAPI_EARFCN_TAG)
  {
757
758
    fp->dl_CarrierFreq = from_earfcn(fp->eutra_band, req->nfapi_config.earfcn.value); // DJP - TODO FIXME - hard coded to first rf
    fp->ul_CarrierFreq = fp->dl_CarrierFreq - (get_uldl_offset(fp->eutra_band) * 1e5);
759
760
761
    num_tlv++;

    NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() earfcn:%u dl_carrierFreq:%u ul_CarrierFreq:%u band:%u N_RB_DL:%u\n", 
762
        __FUNCTION__, req->nfapi_config.earfcn.value, fp->dl_CarrierFreq, fp->ul_CarrierFreq, pnf->rfs[0].band, fp->N_RB_DL);
763
764
765
766
  }

  if (req->subframe_config.duplex_mode.tl.tag == NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG)
  {
767
    fp->frame_type = req->subframe_config.duplex_mode.value==0 ? TDD : FDD;
768
    num_tlv++;
769
    NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() frame_type:%d\n", __FUNCTION__, fp->frame_type);
770
771
772
  }
  if (req->subframe_config.dl_cyclic_prefix_type.tl.tag == NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG)
  {
773
    fp->Ncp = req->subframe_config.dl_cyclic_prefix_type.value;
774
775
776
777
778
    num_tlv++;
  }

  if (req->subframe_config.ul_cyclic_prefix_type.tl.tag == NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG)
  {
779
    fp->Ncp_UL = req->subframe_config.ul_cyclic_prefix_type.value;
780
781
782
    num_tlv++;
  }

783
  fp->num_MBSFN_config = 0; // DJP - hard code alert
784
785
786

  if (req->sch_config.physical_cell_id.tl.tag == NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG)
  {
787
788
    fp->Nid_cell = req->sch_config.physical_cell_id.value;
    fp->nushift = fp->Nid_cell%6;
789
790
791
792
793
    num_tlv++;
  }

  if (req->rf_config.tx_antenna_ports.tl.tag == NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG)
  {
794
795
    fp->nb_antennas_tx = req->rf_config.tx_antenna_ports.value;
    fp->nb_antenna_ports_eNB = 1;
796
797
798
799
800
    num_tlv++;
  }

  if (req->rf_config.rx_antenna_ports.tl.tag == NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG)
  {
801
    fp->nb_antennas_rx = req->rf_config.rx_antenna_ports.value;
802
803
804
805
806
    num_tlv++;
  }

  if (req->phich_config.phich_resource.tl.tag == NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG)
  {
807
    fp->phich_config_common.phich_resource = req->phich_config.phich_resource.value;
808
809
810
811
812
    num_tlv++;
  }

  if (req->phich_config.phich_duration.tl.tag == NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG)
  {
813
    fp->phich_config_common.phich_duration = req->phich_config.phich_duration.value;
814
815
816
817
818
819
    num_tlv++;
  }

  if (req->phich_config.phich_power_offset.tl.tag == NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG)
  {
    LOG_E(PHY, "%s() NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG tag:%d not supported\n", __FUNCTION__, req->phich_config.phich_power_offset.tl.tag);
820
    //fp->phich_config_common.phich_power_offset = req->phich_config.
821
822
823
824
825
826
    num_tlv++;
  }

  // UL RS Config
  if (req->uplink_reference_signal_config.cyclic_shift_1_for_drms.tl.tag == NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG)
  {
827
    fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = req->uplink_reference_signal_config.cyclic_shift_1_for_drms.value;
828
829
830
831
832
    num_tlv++;
  }

  if (req->uplink_reference_signal_config.uplink_rs_hopping.tl.tag == NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG)
  {
833
    fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = req->uplink_reference_signal_config.uplink_rs_hopping.value;
834
835
836
837
838
    num_tlv++;
  }

  if (req->uplink_reference_signal_config.group_assignment.tl.tag == NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG)
  {
839
    fp->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = req->uplink_reference_signal_config.group_assignment.value;
840
841
842
843
844
    num_tlv++;
  }

  if (req->pusch_config.hopping_mode.tl.tag == NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG) { }  // DJP - not being handled?

845
  fp->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; // DJP - not being handled
846
847
848

  if (req->prach_config.configuration_index.tl.tag == NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG)
  {
849
    fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=req->prach_config.configuration_index.value;
850
851
852
853
854
    num_tlv++;
  }

  if (req->prach_config.root_sequence_index.tl.tag == NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG)
  {
855
    fp->prach_config_common.rootSequenceIndex=req->prach_config.root_sequence_index.value;
856
857
858
859
860
    num_tlv++;
  }

  if (req->prach_config.zero_correlation_zone_configuration.tl.tag == NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG)
  {
861
    fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=req->prach_config.zero_correlation_zone_configuration.value;
862
863
864
865
866
    num_tlv++;
  }

  if (req->prach_config.high_speed_flag.tl.tag == NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG)
  {
867
    fp->prach_config_common.prach_ConfigInfo.highSpeedFlag=req->prach_config.high_speed_flag.value;
868
869
870
871
872
    num_tlv++;
  }

  if (req->prach_config.frequency_offset.tl.tag == NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG)
  {
873
    fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset=req->prach_config.frequency_offset.value;
874
875
876
877
878
879
880
881
882
883
884
885
886
    num_tlv++;
  }

  printf("[PNF] CONFIG_REQUEST[num_tlv:%d] TLVs processed:%d\n", req->num_tlv, num_tlv);

  printf("[PNF] Simulating PHY CONFIG - DJP\n");
  PHY_Config_t phy_config;
  phy_config.Mod_id = 0;
  phy_config.CC_id=0;
  phy_config.cfg = req;

  phy_config_request(&phy_config);

887
  dump_frame_parms(fp);
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924

  phy_info->remote_port = req->nfapi_config.p7_vnf_port.value;

  struct sockaddr_in vnf_p7_sockaddr;
  memcpy(&vnf_p7_sockaddr.sin_addr.s_addr, &(req->nfapi_config.p7_vnf_address_ipv4.address[0]), 4);
  phy_info->remote_addr = inet_ntoa(vnf_p7_sockaddr.sin_addr);

  printf("[PNF] %d vnf p7 %s:%d timing %d %d %d\n", phy_info->id, phy_info->remote_addr, phy_info->remote_port, 
      phy_info->timing_window, phy_info->timing_info_mode, phy_info->timing_info_period);

  nfapi_config_response_t nfapi_resp;
  memset(&nfapi_resp, 0, sizeof(nfapi_resp));
  nfapi_resp.header.message_id = NFAPI_CONFIG_RESPONSE;
  nfapi_resp.header.phy_id = phy_info->id;
  nfapi_resp.error_code = 0; // DJP - some value resp->error_code;
  nfapi_pnf_config_resp(config, &nfapi_resp);
  printf("[PNF] Sent NFAPI_CONFIG_RESPONSE phy_id:%d\n", phy_info->id);

  return 0;
}

nfapi_p7_message_header_t* pnf_phy_allocate_p7_vendor_ext(uint16_t message_id, uint16_t* msg_size)
{
  if(message_id == P7_VENDOR_EXT_REQ)
  {
    (*msg_size) = sizeof(vendor_ext_p7_req);
    return (nfapi_p7_message_header_t*)malloc(sizeof(vendor_ext_p7_req));
  }

  return 0;
}

void pnf_phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t* header)
{
  free(header);
}

925
926
int pnf_phy_hi_dci0_req(nfapi_pnf_p7_config_t* pnf_p7, nfapi_hi_dci0_request_t* req)
{
927
  LOG_D(PHY,"[PNF] hi dci0 request sfn_sf:%d dci:%d hi:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), req->hi_dci0_request_body.number_of_dci, req->hi_dci0_request_body.number_of_hi);
928

929
930
  //phy_info* phy = (phy_info*)(pnf_p7->user_data);

931
932
  struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
  eNB_rxtx_proc_t *proc = &eNB->proc.proc_rxtx[0];
933

934
  for (int i=0; i<req->hi_dci0_request_body.number_of_dci + req->hi_dci0_request_body.number_of_hi; i++)
935
  {
936
    //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d]\n", NFAPI_SFNSF2DEC(req->sfn_sf), i);
937

938
    if (req->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE)
939
    {
940
      LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d] - NFAPI_HI_DCI0_DCI_PDU_TYPE\n", NFAPI_SFNSF2DEC(req->sfn_sf), i);
941

942
943
944
945
946
      nfapi_hi_dci0_request_pdu_t *hi_dci0_req_pdu = &req->hi_dci0_request_body.hi_dci0_pdu_list[i];

      handle_nfapi_hi_dci0_dci_pdu(eNB,proc,hi_dci0_req_pdu);

      eNB->pdcch_vars[NFAPI_SFNSF2SF(req->sfn_sf)&1].num_dci++;
947
    }
948
949
950
    else if (req->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type == NFAPI_HI_DCI0_HI_PDU_TYPE)
    {
      LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d] - NFAPI_HI_DCI0_HI_PDU_TYPE\n", NFAPI_SFNSF2DEC(req->sfn_sf), i);
951

952
      nfapi_hi_dci0_request_pdu_t *hi_dci0_req_pdu = &req->hi_dci0_request_body.hi_dci0_pdu_list[i];
953

954
      handle_nfapi_hi_dci0_hi_pdu(eNB, proc, hi_dci0_req_pdu);
955
    }
956
957
958
959
    else
    {
      LOG_E(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d] - unknown pdu type:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), i, req->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type);
    }
960
961
  }

962
963
  return 0;
}
964

965
966
int pnf_phy_dl_config_req(nfapi_pnf_p7_config_t* pnf_p7, nfapi_dl_config_request_t* req)
{
967
  LOG_D(PHY,"[PNF] %s() sfn_sf:%d pdcch:%u dl_cfg[dci:%u pdus:%d pdsch_rnti:%d] pcfich:%u\n", __FUNCTION__,NFAPI_SFNSF2DEC(req->sfn_sf), req->dl_config_request_body.number_pdcch_ofdm_symbols, req->dl_config_request_body.number_dci, req->dl_config_request_body.number_pdu, req->dl_config_request_body.number_pdsch_rnti, req->dl_config_request_body.transmission_power_pcfich);
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983

  if (RC.ru == 0)
  {
    return -1;
  }

  if (RC.eNB == 0)
  {
    return -2;
  }

  if (RC.eNB[0][0] == 0)
  {
    return -3;
  }

984
985
986
987
  if (sync_var != 0)
  { 
    NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() Main system not up - is this a dummy subframe?\n", __FUNCTION__);
    return -4;
988
989
  }

990
  int sfn = NFAPI_SFNSF2SFN(req->sfn_sf);
991
  int sf = NFAPI_SFNSF2SF(req->sfn_sf);
992

993
994
995
  struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
  eNB_rxtx_proc_t *proc = &eNB->proc.proc_rxtx[0];
  nfapi_dl_config_request_pdu_t* dl_config_pdu_list = req->dl_config_request_body.dl_config_pdu_list;
996
997
998
999
  LTE_eNB_PDCCH *pdcch_vars = &eNB->pdcch_vars[sf&1];

  pdcch_vars->num_pdcch_symbols = req->dl_config_request_body.number_pdcch_ofdm_symbols;
  pdcch_vars->num_dci = 0;
1000

1001
  //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() TX:%d/%d RX:%d/%d sfn_sf:%d DCI:%d PDU:%d\n", __FUNCTION__, proc->frame_tx, proc->subframe_tx, proc->frame_rx, proc->subframe_rx, NFAPI_SFNSF2DEC(req->sfn_sf), req->dl_config_request_body.number_dci, req->dl_config_request_body.number_pdu);
1002

1003
  for (int i=0;i<req->dl_config_request_body.number_pdu;i++)
1004
  {
1005
    //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() sfn/sf:%d PDU[%d] size:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), i, dl_config_pdu_list[i].pdu_size);
1006

1007
1008
1009
    if (dl_config_pdu_list[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
    {
      handle_nfapi_dci_dl_pdu(eNB,proc,&dl_config_pdu_list[i]);
1010

1011
      pdcch_vars->num_dci++; // Is actually number of DCI PDUs
1012
1013

      //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() pdcch_vars->num_dci:%d\n", __FUNCTION__, pdcch_vars->num_dci);
1014
1015
1016
    }
    else if (dl_config_pdu_list[i].pdu_type == NFAPI_DL_CONFIG_BCH_PDU_TYPE)
    {
1017
      nfapi_dl_config_bch_pdu *bch_pdu = &dl_config_pdu_list[i].bch_pdu;
1018
      uint16_t pdu_index = bch_pdu->bch_pdu_rel8.pdu_index;
1019

1020
1021
1022
      if (tx_request_pdu[sfn][sf][pdu_index] != NULL)
      {
        uint8_t *sdu = malloc(tx_request_pdu[sfn][sf][pdu_index]->segments[0].segment_length);
1023

1024
1025
1026
        memcpy(sdu, tx_request_pdu[sfn][sf][pdu_index]->segments[0].segment_data, tx_request_pdu[sfn][sf][pdu_index]->segments[0].segment_length);

        //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() PDU:%d BCH: pdu_index:%u pdu_length:%d sdu_length:%d BCH_SDU:%x,%x,%x\n", __FUNCTION__, i, pdu_index, bch_pdu->bch_pdu_rel8.length, tx_request_pdu[sfn][sf][pdu_index]->segments[0].segment_length, sdu[0], sdu[1], sdu[2]);
1027

1028
1029
1030
1031
1032
1033
1034
1035
        handle_nfapi_bch_pdu(eNB, proc, &dl_config_pdu_list[i], sdu);

        eNB->pbch_configured=1;
      }
      else
      {
        NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() BCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), pdu_index); 
      }
1036
1037
1038
    }
    else if (dl_config_pdu_list[i].pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE)
    {
1039
1040
      nfapi_dl_config_dlsch_pdu *dlsch_pdu = &dl_config_pdu_list[i].dlsch_pdu;
      nfapi_dl_config_dlsch_pdu_rel8_t *rel8_pdu = &dlsch_pdu->dlsch_pdu_rel8;
1041
      nfapi_tx_request_pdu_t *tx_pdu = tx_request_pdu[sfn][sf][rel8_pdu->pdu_index];
1042

1043
      if (tx_pdu != NULL)
1044
      {
1045
        uint8_t *dlsch_sdu = malloc(tx_pdu->segments[0].segment_length);
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056

// **********************************************************************
// THIS IS CREATING AN INTENTIONAL LEAK - I think...
//
// nFAPI won't be managing dlsch_sdu
//
// not sure about the stack, but it does seem to allow it to stay up!!!
//
// I THINK I NEED TO FIX THIS - unless it IS getting freed by the stack
//
// **********************************************************************
1057
      memcpy(dlsch_sdu, tx_pdu->segments[0].segment_data, tx_pdu->segments[0].segment_length);
1058

1059
      //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() DLSCH:pdu_index:%d handle_nfapi_dlsch_pdu(eNB, proc_rxtx, dlsch_pdu, transport_blocks:%d sdu:%p) eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols:%d\n", __FUNCTION__, rel8_pdu->pdu_index, rel8_pdu->transport_blocks, dlsch_sdu, eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols);
1060

1061
1062
1063
1064
1065
1066
      handle_nfapi_dlsch_pdu(
          eNB,
          &eNB->proc.proc_rxtx[0],
          &dl_config_pdu_list[i],
          rel8_pdu->transport_blocks-1,
          dlsch_sdu);
1067
1068
1069
1070
1071
      }
      else
      {
        NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() DLSCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), rel8_pdu->pdu_index);
      }
1072
1073
1074
1075
1076
1077
1078
1079
1080
    }
    else
    {
      NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() UNKNOWN:%d\n", __FUNCTION__, dl_config_pdu_list[i].pdu_type);
    }
  }

  if(req->vendor_extension)
    free(req->vendor_extension);
1081
1082
1083
1084
1085
1086

  return 0;
}

int  pnf_phy_tx_req(nfapi_pnf_p7_config_t* pnf_p7, nfapi_tx_request_t* req)
{
1087
1088
  uint16_t sfn = NFAPI_SFNSF2SFN(req->sfn_sf);
  uint16_t sf = NFAPI_SFNSF2SF(req->sfn_sf);
1089

David Price's avatar
David Price committed
1090
1091
  if (req->tx_request_body.number_of_pdus==0)
    LOG_D(PHY,"%s() SFN/SF:%d%d PDUs:%d\n", __FUNCTION__, sfn, sf, req->tx_request_body.number_of_pdus);
1092

1093
  if (req->tx_request_body.tl.tag==NFAPI_TX_REQUEST_BODY_TAG)
1094
  {
1095
    for (int i=0; i<req->tx_request_body.number_of_pdus; i++)
1096
    {
1097
      LOG_D(PHY,"%s() SFN/SF:%d%d number_of_pdus:%d [PDU:%d] pdu_length:%d pdu_index:%d num_segments:%d\n",
1098
1099
          __FUNCTION__,
          sfn, sf,
1100
          req->tx_request_body.number_of_pdus,
1101
1102
1103
1104
1105
1106
1107
          i,
          req->tx_request_body.tx_pdu_list[i].pdu_length,
          req->tx_request_body.tx_pdu_list[i].pdu_index,
          req->tx_request_body.tx_pdu_list[i].num_segments
          );

      tx_request_pdu[sfn][sf][i] = &req->tx_request_body.tx_pdu_list[i];
1108
1109
    }
  }
1110
1111

  return 0;
1112
1113
}

1114
1115
int pnf_phy_ul_config_req(nfapi_pnf_p7_config_t* pnf_p7, nfapi_ul_config_request_t* req)
{
David Price's avatar
David Price committed
1116
  if (0)LOG_D(PHY,"[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d rach_prach_frequency_resources:%d srs_present:%u\n", 
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
      __FUNCTION__,
      NFAPI_SFNSF2DEC(req->sfn_sf), 
      req->ul_config_request_body.number_of_pdus,
      req->ul_config_request_body.rach_prach_frequency_resources,
      req->ul_config_request_body.srs_present
      );

  if (RC.ru == 0)
  {
    return -1;
  }

  if (RC.eNB == 0)
  {
    return -2;
  }

  if (RC.eNB[0][0] == 0)
  {
    return -3;
  }

  if (sync_var != 0)
  { 
    NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() Main system not up - is this a dummy subframe?\n", __FUNCTION__);
    return -4;
  }

1145
1146
  uint16_t curr_sfn = NFAPI_SFNSF2SFN(req->sfn_sf);
  uint16_t curr_sf = NFAPI_SFNSF2SF(req->sfn_sf);
1147
1148
1149
1150
1151
1152
1153

  struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
  eNB_rxtx_proc_t *proc = &eNB->proc.proc_rxtx[0];
  nfapi_ul_config_request_pdu_t* ul_config_pdu_list = req->ul_config_request_body.ul_config_pdu_list;

  for (int i=0;i<req->ul_config_request_body.number_of_pdus;i++)
  {
David Price's avatar
David Price committed
1154
    //LOG_D(PHY, "%s() sfn/sf:%d PDU[%d] size:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), i, ul_config_pdu_list[i].pdu_size);
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165

    if (
        ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE ||
        ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE ||
        ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE ||
        ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE ||
        ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE ||
        ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE ||
        ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE
       )
    {
David Price's avatar
David Price committed
1166
      //LOG_D(PHY, "%s() handle_nfapi_ul_pdu() for PDU:%d\n", __FUNCTION__, i);
1167

1168
      handle_nfapi_ul_pdu(eNB,proc,&ul_config_pdu_list[i],curr_sfn,curr_sf,req->ul_config_request_body.srs_present);
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
    }
    else
    {
      NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() PDU:%i UNKNOWN type :%d\n", __FUNCTION__, i, ul_config_pdu_list[i].pdu_type);
    }
  }

  return 0;
}

1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
int pnf_phy_lbt_dl_config_req(nfapi_pnf_p7_config_t* config, nfapi_lbt_dl_config_request_t* req)
{
  //printf("[PNF] lbt dl config request\n");
  return 0;
}

int pnf_phy_vendor_ext(nfapi_pnf_p7_config_t* config, nfapi_p7_message_header_t* msg)
{
  if(msg->message_id == P7_VENDOR_EXT_REQ)
  {
    //vendor_ext_p7_req* req = (vendor_ext_p7_req*)msg;
    //printf("[PNF] vendor request (1:%d 2:%d)\n", req->dummy1, req->dummy2);
  }
  else
  {
    printf("[PNF] unknown vendor ext\n");
  }
  return 0;
}

int pnf_phy_pack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t** ppWritePackedMsg, uint8_t *end, nfapi_p7_codec_config_t* codex)
{
  //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
  if(header->message_id == P7_VENDOR_EXT_IND)
  {
    vendor_ext_p7_ind* ind = (vendor_ext_p7_ind*)(header);
    if(!push16(ind->error_code, ppWritePackedMsg, end))
      return 0;

    return 1;
  }
  return -1;
}

int pnf_phy_unpack_p7_vendor_extension(nfapi_p7_message_header_t* header, uint8_t** ppReadPackedMessage, uint8_t *end, nfapi_p7_codec_config_t* codec)
{
  if(header->message_id == P7_VENDOR_EXT_REQ)
  {
    //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
    vendor_ext_p7_req* req = (vendor_ext_p7_req*)(header);
    if(!(pull16(ppReadPackedMessage, &req->dummy1, end) &&
1220
          pull16(ppReadPackedMessage, &req->dummy2, end)))
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
      return 0;
    return 1;
  }
  return -1;
}

int pnf_phy_unpack_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMessage, uint8_t* end, void** ve, nfapi_p7_codec_config_t* config)
{
  //NFAPI_TRACE(NFAPI_TRACE_INFO, "pnf_phy_unpack_vendor_extension_tlv\n");

  switch(tl->tag)
  {
    case VENDOR_EXT_TLV_1_TAG:
      *ve = malloc(sizeof(vendor_ext_tlv_1));
      if(!pull32(ppReadPackedMessage, &((vendor_ext_tlv_1*)(*ve))->dummy, end))
	return 0;

      return 1;
      break;
  }

  return -1;
}

int pnf_phy_pack_vendor_extention_tlv(void* ve, uint8_t **ppWritePackedMsg, uint8_t* end, nfapi_p7_codec_config_t* config)
{
  //printf("%s\n", __FUNCTION__);
  (void)ve;
  (void)ppWritePackedMsg;
  return -1;
}

int pnf_sim_unpack_vendor_extension_tlv(nfapi_tl_t* tl, uint8_t **ppReadPackedMessage, uint8_t *end, void** ve, nfapi_p4_p5_codec_config_t* config)
{
  //NFAPI_TRACE(NFAPI_TRACE_INFO, "pnf_sim_unpack_vendor_extension_tlv\n");

  switch(tl->tag)
  {
    case VENDOR_EXT_TLV_2_TAG:
      *ve = malloc(sizeof(vendor_ext_tlv_2));
      if(!pull32(ppReadPackedMessage, &((vendor_ext_tlv_2*)(*ve))->dummy, end))
	return 0;

      return 1;
      break;
  }

  return -1;
}

int pnf_sim_pack_vendor_extention_tlv(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
{
  //printf("%s\n", __FUNCTION__);
  (void)ve;
  (void)ppWritePackedMsg;
  return -1;
}

1279
1280
1281
1282
1283
nfapi_dl_config_request_t dummy_dl_config_req;
nfapi_tx_request_t dummy_tx_req;

nfapi_pnf_p7_subframe_buffer_t dummy_subframe;

1284
1285
1286
1287
int start_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_start_request_t* req)
{
  printf("[PNF] Received NFAPI_START_REQ phy_id:%d\n", req->header.phy_id);

1288
1289
  nfapi_set_trace_level(NFAPI_TRACE_INFO);

1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
  pnf_info* pnf = (pnf_info*)(config->user_data);

#if 0
  //DJP
  auto found = std::find_if(pnf->phys.begin(), pnf->phys.end(), [&](phy_info& item)
      { return item.id == req->header.phy_id; });

  if(found != pnf->phys.end())
#endif
  {
    //DJP phy_info& phy_info = (*found);
    phy_info* phy_info = pnf->phys;

    nfapi_pnf_p7_config_t* p7_config = nfapi_pnf_p7_config_create();

    p7_config->phy_id = phy->phy_id;

    p7_config->remote_p7_port = phy_info->remote_port;
    p7_config->remote_p7_addr = phy_info->remote_addr;
    p7_config->local_p7_port = 32123; // DJP - good grief cannot seem to get the right answer phy_info->local_port;
    //DJP p7_config->local_p7_addr = (char*)phy_info->local_addr.c_str();
    p7_config->local_p7_addr = phy_info->local_addr;

    printf("[PNF] P7 remote:%s:%d local:%s:%d\n", p7_config->remote_p7_addr, p7_config->remote_p7_port, p7_config->local_p7_addr, p7_config->local_p7_port);

    p7_config->user_data = phy_info;

    p7_config->malloc = &pnf_allocate;
    p7_config->free = &pnf_deallocate;
    p7_config->codec_config.allocate = &pnf_allocate;
    p7_config->codec_config.deallocate = &pnf_deallocate;

1322
    p7_config->trace = &pnf_nfapi_trace;
1323
1324
1325
1326

    phy->user_data = p7_config;

    p7_config->subframe_buffer_size = phy_info->timing_window;
1327
    printf("subframe_buffer_size configured using phy_info->timing_window:%d\n", phy_info->timing_window);
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
    if(phy_info->timing_info_mode & 0x1)
    {
      p7_config->timing_info_mode_periodic = 1;
      p7_config->timing_info_period = phy_info->timing_info_period;
    }

    if(phy_info->timing_info_mode & 0x2)
    {
      p7_config->timing_info_mode_aperiodic = 1;
    }

    p7_config->dl_config_req = &pnf_phy_dl_config_req;
    p7_config->ul_config_req = &pnf_phy_ul_config_req;
    p7_config->hi_dci0_req = &pnf_phy_hi_dci0_req;
    p7_config->tx_req = &pnf_phy_tx_req;
    p7_config->lbt_dl_config_req = &pnf_phy_lbt_dl_config_req;

1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
    memset(&dummy_dl_config_req, 0, sizeof(dummy_dl_config_req));
    dummy_dl_config_req.dl_config_request_body.tl.tag=NFAPI_DL_CONFIG_REQUEST_BODY_TAG;
    dummy_dl_config_req.dl_config_request_body.number_pdcch_ofdm_symbols=1;
    dummy_dl_config_req.dl_config_request_body.number_dci=0;
    dummy_dl_config_req.dl_config_request_body.number_pdu=0;
    dummy_dl_config_req.dl_config_request_body.number_pdsch_rnti=0;
    dummy_dl_config_req.dl_config_request_body.transmission_power_pcfich=6000;
    dummy_dl_config_req.dl_config_request_body.dl_config_pdu_list=0;

    memset(&dummy_tx_req, 0, sizeof(dummy_tx_req));
    dummy_tx_req.tx_request_body.number_of_pdus=0;
    dummy_tx_req.tx_request_body.tl.tag=NFAPI_TX_REQUEST_BODY_TAG;

    dummy_subframe.dl_config_req = &dummy_dl_config_req;
    dummy_subframe.tx_req = 0;//&dummy_tx_req;

    dummy_subframe.ul_config_req=0;
    dummy_subframe.hi_dci0_req=0;
    dummy_subframe.lbt_dl_config_req=0;

    p7_config->dummy_subframe = dummy_subframe;

1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
    p7_config->vendor_ext = &pnf_phy_vendor_ext;

    p7_config->allocate_p7_vendor_ext = &pnf_phy_allocate_p7_vendor_ext;
    p7_config->deallocate_p7_vendor_ext = &pnf_phy_deallocate_p7_vendor_ext;

    p7_config->codec_config.unpack_p7_vendor_extension = &pnf_phy_unpack_p7_vendor_extension;
    p7_config->codec_config.pack_p7_vendor_extension = &pnf_phy_pack_p7_vendor_extension;
    p7_config->codec_config.unpack_vendor_extension_tlv = &pnf_phy_unpack_vendor_extension_tlv;
    p7_config->codec_config.pack_vendor_extension_tlv = &pnf_phy_pack_vendor_extention_tlv;

    NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating P7 thread %s\n", __FUNCTION__);
    pthread_t p7_thread;
    pthread_create(&p7_thread, NULL, &pnf_p7_thread_start, p7_config);

    //((pnf_phy_user_data_t*)(phy_info->fapi->user_data))->p7_config = p7_config;

    NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Calling l1_north_init_eNB() %s\n", __FUNCTION__);
    l1_north_init_eNB();

    NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] DJP - HACK - Set p7_config global ready for subframe ind%s\n", __FUNCTION__);
    p7_config_g = p7_config;

1389
1390
    // Need to wait for main thread to create RU structures
    while(config_sync_var<0)
1391
    {
1392
1393
1394
1395
1396
      usleep(5000000);
      printf("[PNF] waiting for OAI to be configured (eNB/RU)\n");
    }
    printf("[PNF] OAI eNB/RU configured\n");

1397
1398
    //printf("[PNF] About to call phy_init_RU() for RC.ru[0]:%p\n", RC.ru[0]);
    //phy_init_RU(RC.ru[0]);
1399

1400
    printf("[PNF] About to call init_eNB_afterRU()\n");
1401
1402
1403
1404
1405
1406
1407
1408
    init_eNB_afterRU();

    // Signal to main thread that it can carry on - otherwise RU will startup too quickly and it is not initialised
    {
      pthread_mutex_lock(&nfapi_sync_mutex);
      nfapi_sync_var=0;
      pthread_cond_broadcast(&nfapi_sync_cond);
      pthread_mutex_unlock(&nfapi_sync_mutex);
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
    }

    while(sync_var<0)
    {
      usleep(5000000);
      printf("[PNF] waiting for OAI to be started\n");
    }

    printf("[PNF] Sending PNF_START_RESP\n");
    nfapi_send_pnf_start_resp(config, p7_config->phy_id);

    printf("[PNF] Sending first P7 subframe ind\n");
    nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // DJP - SFN_SF set to zero - correct???
1422
    printf("[PNF] Sent first P7 subframe ind\n");
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
  }

  return 0;
}

int measurement_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_measurement_request_t* req)
{
  nfapi_measurement_response_t resp;
  memset(&resp, 0, sizeof(resp));
  resp.header.message_id = NFAPI_MEASUREMENT_RESPONSE;
  resp.header.phy_id = req->header.phy_id;
  resp.error_code = NFAPI_MSG_OK;
  nfapi_pnf_measurement_resp(config, &resp);
  return 0;
}

int rssi_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_rssi_request_t* req)
{
  nfapi_rssi_response_t resp;
  memset(&resp, 0, sizeof(resp));
  resp.header.message_id = NFAPI_RSSI_RESPONSE;
  resp.header.phy_id = req->header.phy_id;
  resp.error_code = NFAPI_P4_MSG_OK;
  nfapi_pnf_rssi_resp(config, &resp);

  nfapi_rssi_indication_t ind;
  memset(&ind, 0, sizeof(ind));
  ind.header.message_id = NFAPI_RSSI_INDICATION;
  ind.header.phy_id = req->header.phy_id;
  ind.error_code = NFAPI_P4_MSG_OK;
  ind.rssi_indication_body.tl.tag = NFAPI_RSSI_INDICATION_TAG;
  ind.rssi_indication_body.number_of_rssi = 1;
  ind.rssi_indication_body.rssi[0] = -42;
  nfapi_pnf_rssi_ind(config, &ind);
  return 0;
}

int cell_search_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_cell_search_request_t* req)
{
  nfapi_cell_search_response_t resp;
  memset(&resp, 0, sizeof(resp));
  resp.header.message_id = NFAPI_CELL_SEARCH_RESPONSE;
  resp.header.phy_id = req->header.phy_id;
  resp.error_code = NFAPI_P4_MSG_OK;
  nfapi_pnf_cell_search_resp(config, &resp);

  nfapi_cell_search_indication_t ind;
  memset(&ind, 0, sizeof(ind));
  ind.header.message_id = NFAPI_CELL_SEARCH_INDICATION;
  ind.header.phy_id = req->header.phy_id;
  ind.error_code = NFAPI_P4_MSG_OK;

  switch(req->rat_type)
  {
    case NFAPI_RAT_TYPE_LTE:
      {
        ind.lte_cell_search_indication.tl.tag = NFAPI_LTE_CELL_SEARCH_INDICATION_TAG;
        ind.lte_cell_search_indication.number_of_lte_cells_found = 1;
        ind.lte_cell_search_indication.lte_found_cells[0].pci = 123;
        ind.lte_cell_search_indication.lte_found_cells[0].rsrp = 123;
        ind.lte_cell_search_indication.lte_found_cells[0].rsrq = 123;
        ind.lte_cell_search_indication.lte_found_cells[0].frequency_offset = 123;
      }
      break;
    case NFAPI_RAT_TYPE_UTRAN:
      {
        ind.utran_cell_search_indication.tl.tag = NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG;
        ind.utran_cell_search_indication.number_of_utran_cells_found = 1;
        ind.utran_cell_search_indication.utran_found_cells[0].psc = 89;
        ind.utran_cell_search_indication.utran_found_cells[0].rscp = 89;
        ind.utran_cell_search_indication.utran_found_cells[0].ecno = 89;
        ind.utran_cell_search_indication.utran_found_cells[0].frequency_offset = -89;

      }
      break;
    case NFAPI_RAT_TYPE_GERAN:
      {
        ind.geran_cell_search_indication.tl.tag = NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG;
        ind.geran_cell_search_indication.number_of_gsm_cells_found = 1;
        ind.geran_cell_search_indication.gsm_found_cells[0].bsic = 23;
        ind.geran_cell_search_indication.gsm_found_cells[0].rxlev = 23;
        ind.geran_cell_search_indication.gsm_found_cells[0].rxqual = 23;
        ind.geran_cell_search_indication.gsm_found_cells[0].frequency_offset = -23;
        ind.geran_cell_search_indication.gsm_found_cells[0].sfn_offset = 230;

      }
      break;
  }

  ind.pnf_cell_search_state.tl.tag = NFAPI_PNF_CELL_SEARCH_STATE_TAG;
  ind.pnf_cell_search_state.length = 3;

  nfapi_pnf_cell_search_ind(config, &ind);	

  return 0;
}

int broadcast_detect_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_broadcast_detect_request_t* req)
{
  nfapi_broadcast_detect_response_t resp;
  memset(&resp, 0, sizeof(resp));
  resp.header.message_id = NFAPI_BROADCAST_DETECT_RESPONSE;
  resp.header.phy_id = req->header.phy_id;
  resp.error_code = NFAPI_P4_MSG_OK;
  nfapi_pnf_broadcast_detect_resp(config, &resp);

  nfapi_broadcast_detect_indication_t ind;
  memset(&ind, 0, sizeof(ind));
  ind.header.message_id = NFAPI_BROADCAST_DETECT_INDICATION;
  ind.header.phy_id = req->header.phy_id;
  ind.error_code = NFAPI_P4_MSG_OK;

  switch(req->rat_type)
  {
    case NFAPI_RAT_TYPE_LTE:
      {
        ind.lte_broadcast_detect_indication.tl.tag = NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG;
        ind.lte_broadcast_detect_indication.number_of_tx_antenna = 1;
        ind.lte_broadcast_detect_indication.mib_length = 4;
        //ind.lte_broadcast_detect_indication.mib...
        ind.lte_broadcast_detect_indication.sfn_offset = 77;

      }
      break;
    case NFAPI_RAT_TYPE_UTRAN:
      {
        ind.utran_broadcast_detect_indication.tl.tag = NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG;
        ind.utran_broadcast_detect_indication.mib_length = 4;
        //ind.utran_broadcast_detect_indication.mib...
        // ind.utran_broadcast_detect_indication.sfn_offset; DJP - nonsense line

      }
      break;
  }

  ind.pnf_cell_broadcast_state.tl.tag = NFAPI_PNF_CELL_BROADCAST_STATE_TAG;
  ind.pnf_cell_broadcast_state.length = 3;

  nfapi_pnf_broadcast_detect_ind(config, &ind);	

  return 0;
}

int system_information_schedule_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_system_information_schedule_request_t* req)
{
  nfapi_system_information_schedule_response_t resp;
  memset(&resp, 0, sizeof(resp));
  resp.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE;
  resp.header.phy_id = req->header.phy_id;
  resp.error_code = NFAPI_P4_MSG_OK;
  nfapi_pnf_system_information_schedule_resp(config, &resp);

  nfapi_system_information_schedule_indication_t ind;
  memset(&ind, 0, sizeof(ind));
  ind.header.message_id = NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION;
  ind.header.phy_id = req->header.phy_id;
  ind.error_code = NFAPI_P4_MSG_OK;

  ind.lte_system_information_indication.tl.tag = NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG;
  ind.lte_system_information_indication.sib_type = 3;
  ind.lte_system_information_indication.sib_length = 5;
  //ind.lte_system_information_indication.sib...

  nfapi_pnf_system_information_schedule_ind(config, &ind);		

  return 0;
}

int system_information_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_system_information_request_t* req)
{
  nfapi_system_information_response_t resp;
  memset(&resp, 0, sizeof(resp));
  resp.header.message_id = NFAPI_SYSTEM_INFORMATION_RESPONSE;
  resp.header.phy_id = req->header.phy_id;
  resp.error_code = NFAPI_P4_MSG_OK;
  nfapi_pnf_system_information_resp(config, &resp);

  nfapi_system_information_indication_t ind;
  memset(&ind, 0, sizeof(ind));
  ind.header.message_id = NFAPI_SYSTEM_INFORMATION_INDICATION;
  ind.header.phy_id = req->header.phy_id;
  ind.error_code = NFAPI_P4_MSG_OK;

  switch(req->rat_type)
  {
    case NFAPI_RAT_TYPE_LTE:
      {
        ind.lte_system_information_indication.tl.tag = NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG;
        ind.lte_system_information_indication.sib_type = 1;
        ind.lte_system_information_indication.sib_length = 3;
        //ind.lte_system_information_indication.sib...
      }
      break;
    case NFAPI_RAT_TYPE_UTRAN:
      {
        ind.utran_system_information_indication.tl.tag = NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG;
        ind.utran_system_information_indication.sib_length = 3;
        //ind.utran_system_information_indication.sib...

      }
      break;
    case NFAPI_RAT_TYPE_GERAN:
      {
        ind.geran_system_information_indication.tl.tag = NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG;
        ind.geran_system_information_indication.si_length = 3;
        //ind.geran_system_information_indication.si...

      }
      break;
  }

  nfapi_pnf_system_information_ind(config, &ind);		

  return 0;
}

int nmm_stop_request(nfapi_pnf_config_t* config, nfapi_pnf_phy_config_t* phy, nfapi_nmm_stop_request_t* req)
{
  nfapi_nmm_stop_response_t resp;
  memset(&resp, 0, sizeof(resp));
  resp.header.message_id = NFAPI_NMM_STOP_RESPONSE;
  resp.header.phy_id = req->header.phy_id;
  resp.error_code = NFAPI_P4_MSG_OK;
  nfapi_pnf_nmm_stop_resp(config, &resp);
  return 0;
}

int vendor_ext(nfapi_pnf_config_t* config, nfapi_p4_p5_message_header_t* msg)
{
  NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] P5 %s %p\n", __FUNCTION__, msg);

  switch(msg->message_id)
  {
    case P5_VENDOR_EXT_REQ:
      {
        vendor_ext_p5_req* req = (vendor_ext_p5_req*)msg;
        NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] P5 Vendor Ext Req (%d %d)\n", req->dummy1, req->dummy2);
        // send back the P5_VENDOR_EXT_RSP
        vendor_ext_p5_rsp rsp;
        memset(&rsp, 0, sizeof(rsp));
        rsp.header.message_id = P5_VENDOR_EXT_RSP;
        rsp.error_code = NFAPI_MSG_OK;
        nfapi_pnf_vendor_extension(config, &rsp.header, sizeof(vendor_ext_p5_rsp));
      }
      break;
  }

  return 0;
}

nfapi_p4_p5_message_header_t* pnf_sim_allocate_p4_p5_vendor_ext(uint16_t message_id, uint16_t* msg_size)
{
  if(message_id == P5_VENDOR_EXT_REQ)
  {
    (*msg_size) = sizeof(vendor_ext_p5_req);
    return (nfapi_p4_p5_message_header_t*)malloc(sizeof(vendor_ext_p5_req));
  }

  return 0;
}

void pnf_sim_deallocate_p4_p5_vendor_ext(nfapi_p4_p5_message_header_t* header)
{
  free(header);
}

int pnf_sim_pack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t* header, uint8_t** ppWritePackedMsg, uint8_t *end, nfapi_p4_p5_codec_config_t* config)
{
  //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
  if(header->message_id == P5_VENDOR_EXT_RSP)
  {
    vendor_ext_p5_rsp* rsp = (vendor_ext_p5_rsp*)(header);
    return (!push16(rsp->error_code, ppWritePackedMsg, end));
  }
  return 0;
}

int pnf_sim_unpack_p4_p5_vendor_extension(nfapi_p4_p5_message_header_t* header, uint8_t** ppReadPackedMessage, uint8_t *end, nfapi_p4_p5_codec_config_t* codec)
{
  //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
  if(header->message_id == P5_VENDOR_EXT_REQ)
  {
    vendor_ext_p5_req* req = (vendor_ext_p5_req*)(header);
    return (!(pull16(ppReadPackedMessage, &req->dummy1, end) &&
          pull16(ppReadPackedMessage, &req->dummy2, end)));

    //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s (%d %d)\n", __FUNCTION__, req->dummy1, req->dummy2);
  }
  return 0;
}

/*------------------------------------------------------------------------------*/

void* pnf_start_thread(void* ptr)
{
  NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] IN PNF NFAPI start thread %s\n", __FUNCTION__);

  nfapi_pnf_config_t *config = (nfapi_pnf_config_t*)ptr;

David Price's avatar
David Price committed
1722
1723
1724
1725
  struct sched_param sp;
  sp.sched_priority = 20;
  pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp);

1726
1727
1728
1729
1730
  nfapi_pnf_start(config);

  return (void*)0;
}

1731
void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port)
1732
{
1733
  nfapi_mode = 1;  // PNF!
1734

1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
  nfapi_pnf_config_t* config = nfapi_pnf_config_create();

  config->vnf_ip_addr = vnf_ip_addr;
  config->vnf_p5_port = vnf_p5_port;

  pnf.phys[0].udp.enabled = 1;
  pnf.phys[0].udp.rx_port = pnf_p7_port;
  pnf.phys[0].udp.tx_port = vnf_p7_port;
  strcpy(pnf.phys[0].udp.tx_addr, vnf_ip_addr);

1745
1746
1747
  strcpy(pnf.phys[0].local_addr, pnf_ip_addr);

  printf("%s() VNF:%s:%d PNF_PHY[addr:%s UDP:tx_addr:%s:%d rx:%d]\n", 
1748
1749
      __FUNCTION__, 
      config->vnf_ip_addr, config->vnf_p5_port, 
1750
      pnf.phys[0].local_addr,
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
      pnf.phys[0].udp.tx_addr, pnf.phys[0].udp.tx_port,
      pnf.phys[0].udp.rx_port);

  config->pnf_param_req = &pnf_param_request;
  config->pnf_config_req = &pnf_config_request;
  config->pnf_start_req = &pnf_start_request;
  config->pnf_stop_req = &pnf_stop_request;
  config->param_req = &param_request;
  config->config_req = &config_request;
  config->start_req = &start_request;

  config->measurement_req = &measurement_request;
  config->rssi_req = &rssi_request;
  config->cell_search_req = &cell_search_request;
  config->broadcast_detect_req = &broadcast_detect_request;
  config->system_information_schedule_req = &system_information_schedule_request;
  config->system_information_req = &system_information_request;
  config->nmm_stop_req = &nmm_stop_request;

  config->vendor_ext = &vendor_ext;

1772
  config->trace = &pnf_nfapi_trace;
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787

  config->user_data = &pnf;

  // To allow custom vendor extentions to be added to nfapi
  config->codec_config.unpack_vendor_extension_tlv = &pnf_sim_unpack_vendor_extension_tlv;
  config->codec_config.pack_vendor_extension_tlv = &pnf_sim_pack_vendor_extention_tlv;

  config->allocate_p4_p5_vendor_ext = &pnf_sim_allocate_p4_p5_vendor_ext;
  config->deallocate_p4_p5_vendor_ext = &pnf_sim_deallocate_p4_p5_vendor_ext;

  config->codec_config.unpack_p4_p5_vendor_extension = &pnf_sim_unpack_p4_p5_vendor_extension;
  config->codec_config.pack_p4_p5_vendor_extension = &pnf_sim_pack_p4_p5_vendor_extension;

  NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating PNF NFAPI start thread %s\n", __FUNCTION__);
  pthread_create(&pnf_start_pthread, NULL, &pnf_start_thread, config);
David Price's avatar
David Price committed
1788
1789
1790

  pthread_setname_np(pnf_start_pthread, "NFAPI_PNF");

1791
1792
}

1793
void oai_subframe_ind(uint16_t sfn, uint16_t sf)
1794
{
1795
  //LOG_D(PHY,"%s(sfn:%d, sf:%d)\n", __FUNCTION__, sfn, sf);
1796

1797
1798