Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
trx-ecpri
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
trx-ecpri
Commits
ada02d83
Commit
ada02d83
authored
Mar 07, 2022
by
Joanne Hugé
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix multiple bugs with amarisoft integration
parent
8c9fa1b5
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
851 additions
and
123 deletions
+851
-123
ecpri-tests/test-dpdk-ecpri.c
ecpri-tests/test-dpdk-ecpri.c
+69
-55
ecpri-tests/test.sh
ecpri-tests/test.sh
+5
-4
enb.cfg
enb.cfg
+620
-0
launch-phc2sys
launch-phc2sys
+5
-1
launch-ptp
launch-ptp
+3
-0
trx_ecpri_dpdk.c
trx_ecpri_dpdk.c
+149
-63
No files found.
ecpri-tests/test-dpdk-ecpri.c
View file @
ada02d83
...
@@ -31,12 +31,15 @@
...
@@ -31,12 +31,15 @@
#include <time.h>
#include <time.h>
#include <unistd.h>
#include <unistd.h>
#include "trx_driver.h"
typedef
struct
{
typedef
struct
{
const
char
*
re_mac
;
const
char
*
re_mac
;
const
char
*
rec_mac
;
const
char
*
rec_mac
;
const
char
*
rec_if
;
const
char
*
rec_if
;
const
char
*
dpdk_options
;
const
char
*
dpdk_options
;
const
char
*
trace_file
;
const
char
*
trace_file
;
const
char
*
stats_file
;
int
recv_affinity
;
int
recv_affinity
;
int
send_affinity
;
int
send_affinity
;
int
prepare_affinity
;
int
prepare_affinity
;
...
@@ -47,6 +50,7 @@ typedef struct {
...
@@ -47,6 +50,7 @@ typedef struct {
int
sample_rate
;
int
sample_rate
;
int
trace_period
;
int
trace_period
;
}
TRXEcpriState
;
}
TRXEcpriState
;
static
void
log_error
(
const
char
*
section
,
const
char
*
msg
,
...)
{
static
void
log_error
(
const
char
*
section
,
const
char
*
msg
,
...)
{
time_t
t
;
time_t
t
;
struct
tm
ts
;
struct
tm
ts
;
...
@@ -79,7 +83,37 @@ static void log_info(const char * section, const char * msg, ...) {
...
@@ -79,7 +83,37 @@ static void log_info(const char * section, const char * msg, ...) {
va_end
(
arglist
);
va_end
(
arglist
);
puts
(
line
);
puts
(
line
);
}
}
int
startdpdk
(
TRXEcpriState
*
s
);
// Timestamps utils
#define NSEC_PER_SEC INT64_C(1000000000)
static
struct
timespec
int_to_ts
(
int64_t
t
)
{
struct
timespec
ts
;
ts
.
tv_sec
=
t
/
NSEC_PER_SEC
;
ts
.
tv_nsec
=
t
-
(
ts
.
tv_sec
*
NSEC_PER_SEC
);
return
ts
;
}
static
int64_t
ts_to_int
(
struct
timespec
ts
)
{
return
ts
.
tv_sec
*
NSEC_PER_SEC
+
ts
.
tv_nsec
;
}
static
void
add_ns
(
struct
timespec
*
t
,
int64_t
ns
)
{
t
->
tv_nsec
+=
ns
;
while
(
t
->
tv_nsec
>=
((
int64_t
)
NSEC_PER_SEC
))
{
t
->
tv_sec
+=
1
;
t
->
tv_nsec
-=
NSEC_PER_SEC
;
}
}
static
int64_t
calcdiff_ns
(
struct
timespec
t1
,
struct
timespec
t2
)
{
int64_t
diff
;
diff
=
NSEC_PER_SEC
*
((
int
)
t1
.
tv_sec
-
(
int
)
t2
.
tv_sec
);
diff
+=
((
int
)
t1
.
tv_nsec
-
(
int
)
t2
.
tv_nsec
);
return
diff
;
}
TRXState
s1
;
float
**
tx_samples
;
float
**
rx_samples
;
void
dummy_enb_init
(
TRXState
*
s1
,
TRXEcpriState
*
s
);
static
void
enb
(
TRXState
*
s1
,
TRXEcpriState
*
s
);
int
main
(
int
argc
,
char
*
argv
[])
{
int
main
(
int
argc
,
char
*
argv
[])
{
(
void
)
argc
;
(
void
)
argc
;
...
@@ -95,59 +129,11 @@ int main(int argc, char * argv[]) {
...
@@ -95,59 +129,11 @@ int main(int argc, char * argv[]) {
s
=
malloc
(
sizeof
(
TRXEcpriState
));
s
=
malloc
(
sizeof
(
TRXEcpriState
));
memset
(
s
,
0
,
sizeof
(
*
s
));
memset
(
s
,
0
,
sizeof
(
*
s
));
#if 0
// tiogapass-003 MT27710
s->rec_mac = "b8:59:9f:07:7e:2a";
//s->re_mac = "04:09:a5:0f:9f:4c"; // Lille M6424 Switch
s->re_mac = "b8:59:9f:07:86:42"; // tiogapass-004 MT27710
//s->re_mac = "b4:96:91:a7:1c:f4"; // tiogapass-004 XXV710DA2T port0
s->rec_if = "ens9f0";
s->dpdk_options = "-l 10,20 -b 0000:04:00.0 -b 0000:5e:00.1 ";
#endif
#if 0
// tiogapass-003 MT27710 port1
s->rec_mac = "b8:59:9f:07:7e:2b";
s->re_mac = "04:09:a5:0f:9f:4c"; // Lille M6424 Switch
//s->re_mac = "b8:59:9f:07:86:42"; // tiogapass-004 MT27710
//s->re_mac = "b4:96:91:a7:1c:f5"; // tiogapass-004 XXV710DA2T port1
s->rec_if = "ens9f1";
s->dpdk_options = "-l 10,20 -b 0000:04:00.0 -b 0000:5e:00.0 ";
#endif
#if 0
// hfr-tiogapass-001 MT27710
s->rec_mac = "b8:59:9f:07:82:ca";
s->re_mac = "04:09:a5:0f:76:1c"; // HFR M6424 switch
s->rec_if = "ens9f0";
s->dpdk_options = "-l 10,20 -b 0000:04:00.0 -b 0000:18:00.0 -b 0000:18:00.1 -b 0000:5e:00.1 ";
#endif
#if 0
// hfr-tiogapass-001 XXV710DA2T
s->rec_mac = "b4:96:91:a7:1b:28";
s->re_mac = "04:09:a5:0f:76:1c"; // HFR M6424 switch
s->rec_if = "ens1f0";
s->dpdk_options = "-l 10,20 -b 0000:04:00.0 -b 0000:18:00.1 -b 0000:5e:00.0 -b 0000:5e:00.1 ";
#endif
#if 1
// tiogapass-004 MT27710
s
->
rec_mac
=
"b8:59:9f:07:86:42"
;
//s->re_mac = "04:09:a5:0f:9f:4c"; // Lille M6424 Switch
s
->
re_mac
=
"b8:59:9f:07:7e:2a"
;
// tiogapass-003 MT27710
s
->
rec_if
=
"ens9f0"
;
s
->
dpdk_options
=
"-l 10,20 -b 0000:04:00.0 -b 0000:3b:00.0 -b 0000:3b:00.1 -b 0000:5e:00.1 "
;
#endif
#if 0
// tiogapass-004 XXV710DA2T
s
->
rec_mac
=
"b4:96:91:a7:1c:f4"
;
s
->
rec_mac
=
"b4:96:91:a7:1c:f4"
;
s->re_mac = "04:09:a5:0f:9f:4c";
// Lille M6424 Switch
s
->
re_mac
=
"04:09:a5:0f:9f:4c"
;
s->re_mac = "b8:59:9f:07:7e:2a";
// tiogapass-003 MT27710
s
->
re_mac
=
"b8:59:9f:07:7e:2a"
;
s
->
rec_if
=
"ens5f0"
;
s
->
rec_if
=
"ens5f0"
;
s
->
dpdk_options
=
"-l 10,20 -b 0000:04:00.0 -b 0000:3b:00.1 -b 0000:5e:00.0 -b 0000:5e:00.1 "
;
s
->
dpdk_options
=
"-l 10,20 -b 0000:04:00.0 -b 0000:3b:00.1 -b 0000:5e:00.0 -b 0000:5e:00.1 "
;
#endif
s
->
recv_affinity
=
39
;
s
->
recv_affinity
=
39
;
s
->
send_affinity
=
38
;
s
->
send_affinity
=
38
;
...
@@ -158,17 +144,45 @@ int main(int argc, char * argv[]) {
...
@@ -158,17 +144,45 @@ int main(int argc, char * argv[]) {
s
->
flow_id
=
0
;
s
->
flow_id
=
0
;
s
->
sample_rate
=
122880000
;
s
->
sample_rate
=
122880000
;
s
->
trace_file
=
"/root/ecpri_trace"
;
s
->
trace_file
=
"/root/ecpri-logs/rx.trace"
;
s
->
stats_file
=
"/root/ecpri-logs/ecpri.stats"
;
s
->
trace_period
=
1000000
;
s
->
trace_period
=
1000000
;
log_info
(
"TEST-DPDK-ECPRI"
,
"Starting test...
\n
"
);
log_info
(
"TEST-DPDK-ECPRI"
,
"Starting test...
\n
"
);
log_info
(
"TEST-DPDK-ECPRI"
,
"rec-mac: %s, re-mac: %s, rec-if: %s"
,
s
->
rec_mac
,
s
->
re_mac
,
s
->
rec_if
);
log_info
(
"TEST-DPDK-ECPRI"
,
"rec-mac: %s, re-mac: %s, rec-if: %s"
,
s
->
rec_mac
,
s
->
re_mac
,
s
->
rec_if
);
startdpdk
(
s
);
dummy_enb_init
(
&
s1
,
s
);
enb
(
&
s1
,
s
);
}
for
(;;)
{
static
void
enb
(
TRXState
*
s1
,
TRXEcpriState
*
s
)
{
sleep
(
1
);
struct
timespec
next
;
trx_timestamp_t
ptimestamp
;
int64_t
p
=
1000000
*
100
;
int
m
=
1
;
clock_gettime
(
CLOCK_TAI
,
&
next
);
tx_samples
=
(
float
**
)
malloc
(
sizeof
(
float
*
)
*
4
);
rx_samples
=
(
float
**
)
malloc
(
sizeof
(
float
*
)
*
4
);
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
tx_samples
[
i
]
=
(
float
*
)
malloc
(
sizeof
(
float
)
*
65536
);
rx_samples
[
i
]
=
(
float
*
)
malloc
(
sizeof
(
float
)
*
65536
);
for
(
int
j
=
0
;
j
<
65536
;
j
++
)
{
tx_samples
[
i
][
j
]
=
i
*
j
;
}
}
}
for
(
int
i
=
0
;;
i
++
)
{
int64_t
tx_timestamp
=
256
*
(
INT64_C
(
3840000
)
*
((
int64_t
)
p
*
i
+
p
))
/
(
INT64_C
(
1000000000
));
add_ns
(
&
next
,
p
);
s1
->
trx_read_func2
(
s1
,
&
ptimestamp
,
rx_samples
,
256
*
m
,
0
,
NULL
);
s1
->
trx_write_func2
(
s1
,
tx_timestamp
,
tx_samples
,
256
*
m
,
0
,
NULL
);
s1
->
trx_write_func2
(
s1
,
tx_timestamp
+
256
*
m
+
100
,
tx_samples
,
256
*
m
,
0
,
NULL
);
s1
->
trx_write_func2
(
s1
,
tx_timestamp
+
2
*
256
*
m
+
110
,
tx_samples
,
256
*
m
,
0
,
NULL
);
clock_nanosleep
(
CLOCK_TAI
,
TIMER_ABSTIME
,
&
next
,
NULL
);
}
}
}
ecpri-tests/test.sh
View file @
ada02d83
#!/bin/bash
#!/bin/bash
cd
..
;
make
;
cd
ecpri-tests
;
make all
;
export
LD_LIBRARY_PATH
=
"/root/ecpri-priv:
$LD_LIBRARY_PATH
"
export
LD_LIBRARY_PATH
=
"/root/ecpri-priv:
$LD_LIBRARY_PATH
"
cd
..
&&
make
&&
cd
ecpri-tests
&&
make all
&&
./test-dpdk-ecpri
./test-dpdk-ecpri
enb.cfg
0 → 100644
View file @
ada02d83
/* lteenb configuration file version ##VERSION##
* Copyright (C) 2019-2021 Amarisoft
* NR SA FDD or TDD cell */
#define TDD 1 // Values: 0 (NR FDD), 1(NR TDD)
#define TDD_CONFIG 2 // Values: 1, 2 or 3
#define N_ANTENNA_DL 4 // Values: 1 (SISO), 2 (MIMO 2x2), 4 (MIMO 4x4)
#define N_ANTENNA_UL 1 // Values: 1, 2, 4
#define BANDWIDTH 100 // NR cell bandwidth
#define CPRI 1
#define NR_TEST_MODE -1
/* define to 1 to enable periodic SRS with N_ANTENNA_UL ports. Uplink
SU-MIMO is also enabled if N_ANTENNA_UL >= 2. Not all UEs support
uplink SU-MIMO. */
#define USE_SRS 0
{
//log_options: "all.level=debug,all.max_size=1",
log_options: "all.level=error,all.max_size=0,nas.level=debug,nas.max_size=1,ngap.level=debug,ngap.max_size=1,xnap.level=debug,xnap.max_size=1,rrc.level=debug,rrc.max_size=1",
log_filename: "/tmp/gnb0.log",
/* Enable remote API and Web interface */
com_addr: "0.0.0.0:9001",
rf_driver: {
name: "ecpri",
//rec_mac: "b8:59:9f:07:86:42",
//re_mac: "04:09:a5:0f:9f:4a", /* HFR Switch */
//rec_if: "ens9f1",
//dpdk_options: "-l 10,20 -b 0000:04:00.0 -b 0000:3b:00.0 -b 0000:3b:00.1 -b 0000:5e:00.1 ",
rec_mac: "b8:59:9f:07:86:43",
re_mac: "b8:59:9f:07:7e:2b", /* HFR Switch */
rec_if: "ens9f1",
dpdk_options: "-l 10,20 -b 0000:04:00.0 -b 0000:3b:00.0 -b 0000:3b:00.1 -b 0000:5e:00.0 ",
recv_affinity: 39,
send_affinity: 38,
prepare_affinity: 37,
decompress_affinity: 36,
statistic_affinity: 35,
ecpri_period: 800,
flow_id: 0,
trace_period: 10000000,
trace_file: "/root/ecpri-logs/rx.trace",
stats_file: "/root/ecpri-logs/ecpri.stats",
},
tx_gain: 90.0, /* TX gain (in dB) */
rx_gain: 60.0, /* RX gain (in dB) */
sample_rate: 122.88, /* MHz */
amf_list: [
{
/* address of AMF for NGAP connection. Must be modified if the AMF runs on a different host. */
amf_addr: "127.0.1.100",
},
],
/* GTP bind address (=address of the ethernet interface connected to
the AMF). Must be modified if the AMF runs on a different host. */
gtp_addr: "127.0.1.1",
gnb_id_bits: 28,
gnb_id: 0x12345,
nr_support: true,
/* list of cells */
cell_list: [],
nr_cell_list: [
{
rf_port: 0,
cell_id: 0x01,
#if TDD == 1
band: 78,
//dl_nr_arfcn: 632628, /* 3489.42 MHz */
dl_nr_arfcn: 640000, /* For Sunwave CBRS RRH: 3600 MHz */
#else
band: 7,
dl_nr_arfcn: 536020, /* 2680 MHz */
ssb_subcarrier_spacing: 15,
#endif
},
], /* nr_cell_list */
nr_cell_default: {
subcarrier_spacing: 30, /* kHz */
bandwidth: BANDWIDTH, /* MHz */
n_antenna_dl: N_ANTENNA_DL,
n_antenna_ul: N_ANTENNA_UL,
/* force the timing TA offset (optional) */
// n_timing_advance_offset: 39936,
#if TDD == 1
tdd_ul_dl_config: {
pattern1: {
#if TDD_CONFIG == 1
period: 5, /* in ms */
dl_slots: 7,
dl_symbols: /* 6 */ 2,
ul_slots: 2,
ul_symbols: 2,
#elif TDD_CONFIG == 2 // Sunwave conf: Case C DDDDDDDSUU DDDDDDDSUU 6:4:4
period: 5, /* in ms */
dl_slots: 7,
dl_symbols: 6,
ul_slots: 2,
ul_symbols: 4,
#elif TDD_CONFIG == 3
period: 5, /* in ms */
dl_slots: 6,
dl_symbols: 2,
ul_slots: 3,
ul_symbols: 2,
#endif
},
},
ssb_pos_bitmap: "10000000",
#else
ssb_pos_bitmap: "1000",
#endif
ssb_period: 20, /* in ms */
n_id_cell: 500,
plmn_list: [ {
tac: 100,
plmn: "00101",
reserved: false,
nssai: [
{
sst: 1,
},
/*{
sst: 2,
},
{
sst: 3,
sd: 50,
},*/
],
},
],
/*sib_sched_list: [
{
filename: "sib2_nr.asn",
si_periodicity: 16,
},
{
filename: "sib3_nr.asn",
si_periodicity: 16,
},
{
filename: "sib4_nr.asn",
si_periodicity: 32,
},
],
sib9: {
si_periodicity: 32
},*/
si_window_length: 40,
cell_barred: false,
intra_freq_reselection: true,
q_rx_lev_min: -70,
q_qual_min: -20,
p_max: 10, /* dBm */
root_sequence_index: 1, /* PRACH root sequence index */
/* Scheduling request period (slots). */
sr_period: 40,
dmrs_type_a_pos: 2,
/* to limit the number of HARQ feedback in UL, use pdsch_harq_ack_max;
allows to workaround issues with SM-G977N for example */
//pdsch_harq_ack_max: 2,
prach: {
#if TDD == 1
prach_config_index: 160, /* format B4, subframe 9 */
msg1_subcarrier_spacing: 30, /* kHz */
#else
prach_config_index: 16, /* subframe 1 every frame */
#endif
msg1_fdm: 1,
msg1_frequency_start: 0,
zero_correlation_zone_config: 15,
preamble_received_target_power: -110, /* in dBm */
preamble_trans_max: 7,
power_ramping_step: 4, /* in dB */
ra_response_window: 20, /* in slots */
restricted_set_config: "unrestricted_set",
ra_contention_resolution_timer: 64, /* in ms */
ssb_per_prach_occasion: 1,
cb_preambles_per_ssb: 8,
},
pdcch: {
n_rb_coreset0: 48,
n_symb_coreset0: 1,
search_space0_index: 0,
dedicated_coreset: {
rb_start: -1, /* -1 to have the maximum bandwidth */
l_crb: -1, /* -1 means all the bandwidth */
duration: 1,
precoder_granularity: "sameAsREG_bundle",
},
css: {
n_candidates: [ 0, 0, 1, 0, 0 ],
},
rar_al_index: 2,
si_al_index: 2,
uss: {
n_candidates: [ 0, 2, 1, 0, 0 ],
dci_0_1_and_1_1: true,
},
al_index: 1,
},
pdsch: {
mapping_type: "typeA",
dmrs_add_pos: 1,
dmrs_type: 1,
dmrs_max_len: 1,
k0: 0, /* delay in slots from DCI to PDSCH */
/* delay in slots from PDSCH to PUCCH/PUSCH ACK/NACK */
#if TDD == 1
#if TDD_CONFIG == 1
k1: [ 8, 7, 7, 6, 5, 4, 12 /* , 11 */ ],
#elif TDD_CONFIG == 2
k1: [ 8, 7, 7, 6, 5, 4, 12, 11 ],
#elif TDD_CONFIG == 3
k1: [ 7, 6, 6, 5, 5, 4 ],
#endif
#else
k1: 4,
#endif
mcs_table: "qam256",
rar_mcs: 2,
si_mcs: 6,
/* If defined, force the PDSCH MCS for all UEs. Otherwise it is computed
* based on DL channel quality estimation */
/* mcs: 24, */
#if NR_TEST_MODE != -1
/* hardcoded scheduling parameters */
n_layer: N_ANTENNA_DL,
#if N_ANTENNA_DL >= 4
n_dmrs_cdm_groups: 2,
#else
n_dmrs_cdm_groups: 1,
#endif
/* If defined, force the PDSCH MCS for all UEs. Otherwise it is computed
* based on DL channel quality estimation */
mcs: 28,
fer: 0,
#endif
},
csi_rs: {
nzp_csi_rs_resource: [
{
csi_rs_id: 0,
#if N_ANTENNA_DL == 1
n_ports: 1,
frequency_domain_allocation: "row2",
bitmap: "100000000000",
cdm_type: "no_cdm",
#elif N_ANTENNA_DL == 2
n_ports: 2,
frequency_domain_allocation: "other",
bitmap: "100000",
cdm_type: "fd_cdm2",
#elif N_ANTENNA_DL == 4
n_ports: 4,
frequency_domain_allocation: "row4",
bitmap: "100",
cdm_type: "fd_cdm2",
#elif N_ANTENNA_DL == 8
n_ports: 8,
frequency_domain_allocation: "other",
bitmap: "110011",
cdm_type: "fd_cdm2",
#else
#error unsupported number of DL antennas
#endif
density: 1,
first_symb: 4,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
power_control_offset: 0, /* dB */
power_control_offset_ss: 0, /* dB */
period: 80,
offset: 1, /* != 0 to avoid collision with SSB */
qcl_info_periodic_csi_rs: 0,
},
#define USE_TRS
#ifdef USE_TRS
/* TRS : period of 40 ms, slots 1 & 2, symbols 4 and 8 */
{
csi_rs_id: 1,
n_ports: 1,
frequency_domain_allocation: "row1",
bitmap: "0001",
cdm_type: "no_cdm",
density: 3,
first_symb: 4,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
power_control_offset: 0, /* dB */
power_control_offset_ss: 0, /* dB */
period: 40,
offset: 11,
qcl_info_periodic_csi_rs: 0,
},
{
csi_rs_id: 2,
n_ports: 1,
frequency_domain_allocation: "row1",
bitmap: "0001",
cdm_type: "no_cdm",
density: 3,
first_symb: 8,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
power_control_offset: 0, /* dB */
power_control_offset_ss: 0, /* dB */
period: 40,
offset: 11,
qcl_info_periodic_csi_rs: 0,
},
{
csi_rs_id: 3,
n_ports: 1,
frequency_domain_allocation: "row1",
bitmap: "0001",
cdm_type: "no_cdm",
density: 3,
first_symb: 4,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
power_control_offset: 0, /* dB */
power_control_offset_ss: 0, /* dB */
period: 40,
offset: 12,
qcl_info_periodic_csi_rs: 0,
},
{
csi_rs_id: 4,
n_ports: 1,
frequency_domain_allocation: "row1",
bitmap: "0001",
cdm_type: "no_cdm",
density: 3,
first_symb: 8,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
power_control_offset: 0, /* dB */
power_control_offset_ss: 0, /* dB */
period: 40,
offset: 12,
qcl_info_periodic_csi_rs: 0,
},
#endif
],
nzp_csi_rs_resource_set: [
{
csi_rs_set_id: 0,
nzp_csi_rs_resources: [ 0 ],
repetition: false,
},
#ifdef USE_TRS
{
csi_rs_set_id: 1,
nzp_csi_rs_resources: [ 1, 2, 3, 4 ],
repetition: false,
trs_info: true,
},
#endif
],
csi_im_resource: [
{
csi_im_id: 0,
pattern: 1,
subcarrier_location: 8,
symbol_location: 8,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
period: 80,
offset: 1, /* != 0 to avoid collision with SSB */
},
],
csi_im_resource_set: [
{
csi_im_set_id: 0,
csi_im_resources: [ 0 ],
}
],
/* ZP CSI-RS to set the CSI-IM REs to zero */
zp_csi_rs_resource: [
{
csi_rs_id: 0,
frequency_domain_allocation: "row4",
bitmap: "100",
n_ports: 4,
cdm_type: "fd_cdm2",
first_symb: 8,
density: 1,
rb_start: 0,
l_crb: -1, /* -1 means from rb_start to the end of the bandwidth */
period: 80,
offset: 1,
},
],
p_zp_csi_rs_resource_set: [
{
zp_csi_rs_resources: [ 0 ],
},
],
csi_resource_config: [
{
csi_rsc_config_id: 0,
nzp_csi_rs_resource_set_list: [ 0 ],
resource_type: "periodic",
},
{
csi_rsc_config_id: 1,
csi_im_resource_set_list: [ 0 ],
resource_type: "periodic",
},
#ifdef USE_TRS
{
csi_rsc_config_id: 2,
nzp_csi_rs_resource_set_list: [ 1 ],
resource_type: "periodic",
},
#endif
],
csi_report_config: [
{
resources_for_channel_measurement: 0,
csi_im_resources_for_interference: 1,
report_config_type: "periodic",
period: 80,
report_quantity: "CRI_RI_PMI_CQI",
#if N_ANTENNA_DL > 1
codebook_config: {
codebook_type: "type1",
sub_type: "typeI_SinglePanel",
#if N_ANTENNA_DL == 2
#elif N_ANTENNA_DL == 4
n1: 2,
n2: 1,
codebook_mode: 1,
#elif N_ANTENNA_DL == 8
n1: 4,
n2: 1,
codebook_mode: 1,
#endif
},
#endif
cqi_table: 2,
subband_size: "value1",
},
],
},
pucch: {
pucch_group_hopping: "neither",
hopping_id: -1, /* -1 = n_cell_id */
p0_nominal: -90,
#if 0
pucch0: {
initial_cyclic_shift: 1,
n_symb: 1,
},
#else
pucch1: {
n_cs: 3,
n_occ: 3,
freq_hopping: true,
},
#endif
#if 1
pucch2: {
n_symb: 2,
n_prb: 1,
freq_hopping: true,
simultaneous_harq_ack_csi: false,
max_code_rate: 0.25,
},
#endif
#if 0
pucch3: {
bpsk: false,
additional_dmrs: false,
freq_hopping: true,
n_prb: 1,
simultaneous_harq_ack_csi: false,
max_code_rate: 0.25,
},
#endif
#if 0
pucch4: {
occ_len: 4,
bpsk: false,
additional_dmrs: false,
freq_hopping: true,
simultaneous_harq_ack_csi: false,
max_code_rate: 0.25,
},
#endif
},
#if USE_SRS
srs: {
#if TDD_CONFIG == 1 || TDD_CONFIG == 2
srs_symbols: [ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 ],
#elif TDD_CONFIG == 3
srs_symbols: [ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 ],
#endif
srs_resource: [
{
srs_resource_id: 0,
n_ports: N_ANTENNA_UL,
resource_type: "periodic",
period: 80, /* in slots */
}
],
srs_resource_set: [
{
srs_resource_id_list: [ 0 ],
},
],
},
#endif
pusch: {
mapping_type: "typeA",
n_symb: 14,
dmrs_add_pos: 1,
dmrs_type: 1,
dmrs_max_len: 1,
tf_precoding: false,
mcs_table: "qam256", /* without transform precoding */
mcs_table_tp: "qam256", /* with transform precoding */
ldpc_max_its: 5,
k2: 4, /* delay in slots from DCI to PUSCH */
p0_nominal_with_grant: -76,
msg3_k2: 7,
msg3_mcs: 4,
msg3_delta_power: 0, /* in dB */
beta_offset_ack_index: 9,
/* if defined, force the PUSCH MCS for all UEs. Otherwise it is
computed from the last received PUSCH. */
/* mcs: 16, */
},
/* MAC configuration */
mac_config: {
msg3_max_harq_tx: 5,
ul_max_harq_tx: 5, /* max number of HARQ transmissions for uplink */
dl_max_harq_tx: 5, /* max number of HARQ transmissions for downlink */
ul_max_consecutive_retx: 30, /* disconnect UE if reached */
dl_max_consecutive_retx: 30, /* disconnect UE if reached */
periodic_bsr_timer: 20,
retx_bsr_timer: 320,
periodic_phr_timer: 500,
prohibit_phr_timer: 200,
phr_tx_power_factor_change: "dB3",
sr_prohibit_timer: 0, /* in ms, 0 to disable the timer */
sr_trans_max: 64,
},
cipher_algo_pref: [],
integ_algo_pref: [2, 1],
inactivity_timer: 10000,
drb_config: "drb_nr.cfg",
#if NR_TEST_MODE != -1
#if NR_TEST_MODE == 0
test_mode: {
type: "pdsch",
rnti: 0x100,
pdsch_retx: 0,
},
#elif NR_TEST_MODE == 1
test_mode: {
type: "pusch",
rnti: 0x100,
pusch_retx: 0,
},
#else
test_mode: {
type: "load",
ue_count: UE_COUNT,
},
#endif
#endif
},
}
launch-phc2sys
View file @
ada02d83
chrt -f 97 taskset -c 39 phc2sys -m -c ens5f0 -s CLOCK_REALTIME -O0 -f $HOME/linuxptp/configs/G.8275.1.cfg
# Tiogapass004 test
#chrt -f 97 taskset -c 2 phc2sys -m -c ens9f1 -s CLOCK_REALTIME -O0 -f $HOME/linuxptp/configs/G.8275.1.cfg
#chrt -f 97 taskset -c 2 phc2sys -m -s ens9f1 -c CLOCK_REALTIME -O0 -f $HOME/linuxptp/configs/G.8275.1.cfg
# HFR Switch
chrt -f 97 taskset -c 39 phc2sys -m -c ens9f0 -s CLOCK_REALTIME -O0 -f $HOME/linuxptp/configs/G.8275.1.cfg
launch-ptp
View file @
ada02d83
# Tiogapass003 test
#chrt -f 97 taskset -c 38 ptp4l -H -i ens9f1 -m -f $HOME/linuxptp/configs/G.8275.1.cfg
# HFR Switch
chrt -f 97 taskset -c 38 ptp4l -H -i ens9f0 -m -f $HOME/linuxptp/configs/G.8275.1.cfg
chrt -f 97 taskset -c 38 ptp4l -H -i ens9f0 -m -f $HOME/linuxptp/configs/G.8275.1.cfg
trx_ecpri_dpdk.c
View file @
ada02d83
...
@@ -53,7 +53,7 @@
...
@@ -53,7 +53,7 @@
/* eCPRI Send and Recv */
/* eCPRI Send and Recv */
#define N_SAMPLES 256
#define N_SAMPLES 256
#define PACKET_SIZE 262
#define PACKET_SIZE 262
#define DATA_SIZE 24
4
#define DATA_SIZE 24
8
#define FRAME_FREQ INT64_C(3840000)
#define FRAME_FREQ INT64_C(3840000)
//#define SEND_LIMIT (1250 * 10)
//#define SEND_LIMIT (1250 * 10)
#define TRX_WB_MAX_PARTS 1000
#define TRX_WB_MAX_PARTS 1000
...
@@ -77,6 +77,27 @@ static void log_error(const char * section, const char * msg, ...) {
...
@@ -77,6 +77,27 @@ static void log_error(const char * section, const char * msg, ...) {
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
static
volatile
int64_t
limit_counter
=
0
;
static
inline
void
log_limit
(
const
char
*
section
,
const
char
*
msg
,
...)
{
time_t
t
;
struct
tm
ts
;
char
line
[
256
];
va_list
arglist
;
if
(
limit_counter
++
%
1000000
)
return
;
time
(
&
t
);
ts
=
*
localtime
(
&
t
);
strftime
(
line
,
80
,
"%m-%d %H:%M:%S"
,
&
ts
);
sprintf
(
line
+
strlen
(
line
),
" DEBUG [%s] "
,
section
);
va_start
(
arglist
,
msg
);
vsprintf
(
line
+
strlen
(
line
),
msg
,
arglist
);
va_end
(
arglist
);
puts
(
line
);
}
static
void
log_info
(
const
char
*
section
,
const
char
*
msg
,
...)
{
static
void
log_info
(
const
char
*
section
,
const
char
*
msg
,
...)
{
time_t
t
;
time_t
t
;
struct
tm
ts
;
struct
tm
ts
;
...
@@ -179,6 +200,7 @@ typedef struct {
...
@@ -179,6 +200,7 @@ typedef struct {
const
char
*
rec_if
;
const
char
*
rec_if
;
const
char
*
dpdk_options
;
const
char
*
dpdk_options
;
const
char
*
trace_file
;
const
char
*
trace_file
;
const
char
*
stats_file
;
int
recv_affinity
;
int
recv_affinity
;
int
send_affinity
;
int
send_affinity
;
int
prepare_affinity
;
int
prepare_affinity
;
...
@@ -191,12 +213,14 @@ typedef struct {
...
@@ -191,12 +213,14 @@ typedef struct {
}
TRXEcpriState
;
}
TRXEcpriState
;
// Buffers
// Buffers
static
ring_buffer_t
rx_rbuf
;
static
ring_buffer_t
rx_rbuf
;
// Received packets
static
ring_buffer_t
trx_read_rbuf
;
static
ring_buffer_t
trx_read_rbuf
;
// Decoded IQ samples
static
ring_buffer_t
tx_rbuf
;
static
ring_buffer_t
tx_rbuf
;
// Packets to send
static
ring_buffer_t
trx_write_rbuf
;
static
ring_buffer_t
trx_write_rbuf
;
// Uncompressed IQ samples
static
volatile
int
trx_wb_part
[
TRX_WB_MAX_PARTS
];
// TODO write next index instead of curr
ent
// List of timestamps at which data should be s
ent
static
volatile
int64_t
trx_wb_ts
[
TRX_WB_MAX_PARTS
];
static
volatile
int64_t
trx_wb_ts
[
TRX_WB_MAX_PARTS
];
// List of corresponding indexes in trx_write_rbuf
static
volatile
int
trx_wb_part
[
TRX_WB_MAX_PARTS
];
// TODO write next index instead of current
static
int
trx_wb_part_read_index
;
static
int
trx_wb_part_read_index
;
static
int
trx_wb_part_write_index
;
static
int
trx_wb_part_write_index
;
// Locks
// Locks
...
@@ -206,6 +230,8 @@ pthread_mutex_t rx_mutex;
...
@@ -206,6 +230,8 @@ pthread_mutex_t rx_mutex;
pthread_cond_t
rx_cond
;
pthread_cond_t
rx_cond
;
pthread_mutex_t
tx_ready_mutex
;
pthread_mutex_t
tx_ready_mutex
;
pthread_cond_t
tx_ready_cond
;
pthread_cond_t
tx_ready_cond
;
pthread_mutex_t
trx_write_mutex
;
pthread_cond_t
trx_write_cond
;
sem_t
trx_read_sem
;
sem_t
trx_read_sem
;
// Counters
// Counters
static
volatile
counter_stat_t
prepared_counter
;
// compressed samples
static
volatile
counter_stat_t
prepared_counter
;
// compressed samples
...
@@ -252,17 +278,17 @@ static void rbuf_update_read_index(ring_buffer_t * rbuf) {
...
@@ -252,17 +278,17 @@ static void rbuf_update_read_index(ring_buffer_t * rbuf) {
rbuf
->
read_index
=
(
rbuf
->
read_index
+
1
)
%
rbuf
->
buf_len
;
rbuf
->
read_index
=
(
rbuf
->
read_index
+
1
)
%
rbuf
->
buf_len
;
}
}
static
int
rbuf_read_amount
(
const
ring_buffer_t
*
rbuf
)
{
static
int
rbuf_read_amount
(
const
ring_buffer_t
*
rbuf
)
{
return
(
rbuf
->
read_index
+
rbuf
->
buf_len
-
rbuf
->
write
_index
)
%
rbuf
->
buf_len
;
return
(
rbuf
->
write_index
+
rbuf
->
buf_len
-
rbuf
->
read
_index
)
%
rbuf
->
buf_len
;
}
}
static
int
rbuf_write_amount
(
const
ring_buffer_t
*
rbuf
)
{
static
int
rbuf_write_amount
(
const
ring_buffer_t
*
rbuf
)
{
return
(
rbuf
->
write_index
+
rbuf
->
buf_len
-
rbuf
->
read
_index
)
%
rbuf
->
buf_len
;
return
(
rbuf
->
read_index
+
rbuf
->
buf_len
-
rbuf
->
write
_index
)
%
rbuf
->
buf_len
;
}
}
#define RBUF_READ(rbuf, type) (((type *) rbuf.buffer) + (rbuf.read_index * rbuf.len))
#define RBUF_READ(rbuf, type) (((type *) rbuf.buffer) + (rbuf.read_index * rbuf.len))
#define RBUF_WRITE(rbuf, type) (((type *) rbuf.buffer) + (rbuf.write_index * rbuf.len))
#define RBUF_WRITE(rbuf, type) (((type *) rbuf.buffer) + (rbuf.write_index * rbuf.len))
#define RBUF_INIT(rbuf, _name, _buf_len, _len, type) do\
#define RBUF_INIT(rbuf, _name, _buf_len, _len, type) do\
{\
{\
log_debug("TRX_ECPRI", "Allocating %s with %d bytes\n", _name, (_buf_len * _len));\
log_debug("TRX_ECPRI", "Allocating %s with %d bytes\n", _name, (_buf_len * _len
* sizeof(type)
));\
rbuf.buffer = (type *) malloc(_buf_len * _len);\
rbuf.buffer = (type *) malloc(_buf_len * _len
* sizeof(type)
);\
strcpy(rbuf.name, _name);\
strcpy(rbuf.name, _name);\
rbuf.buf_len = _buf_len;\
rbuf.buf_len = _buf_len;\
rbuf.len = _len;\
rbuf.len = _len;\
...
@@ -280,7 +306,7 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
...
@@ -280,7 +306,7 @@ static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
struct
rte_mempool
*
mbuf_pool
;
struct
rte_mempool
*
mbuf_pool
;
struct
rte_ether_addr
s_addr
;
struct
rte_ether_addr
s_addr
;
struct
rte_ether_addr
d_addr
;
struct
rte_ether_addr
d_addr
;
int8_t
data
[
BURST_SIZE
][
DATA
_SIZE
];
int8_t
data
[
BURST_SIZE
][
PACKET
_SIZE
];
static
const
struct
rte_eth_conf
port_conf_default
=
{
static
const
struct
rte_eth_conf
port_conf_default
=
{
.
rxmode
=
{
.
max_lro_pkt_size
=
RTE_ETHER_MAX_LEN
}
.
rxmode
=
{
.
max_lro_pkt_size
=
RTE_ETHER_MAX_LEN
}
};
};
...
@@ -366,7 +392,6 @@ static void send_packets(int port) {
...
@@ -366,7 +392,6 @@ static void send_packets(int port) {
#endif
#endif
eth_hdr
->
ether_type
=
htons
(
0xaefe
);
eth_hdr
->
ether_type
=
htons
(
0xaefe
);
memcpy
(
rte_pktmbuf_mtod_offset
(
pkt
[
i
],
uint8_t
*
,
sizeof
(
struct
rte_ether_hdr
)),
data
[
i
],
DATA_SIZE
);
memcpy
(
rte_pktmbuf_mtod_offset
(
pkt
[
i
],
uint8_t
*
,
sizeof
(
struct
rte_ether_hdr
)),
data
[
i
],
DATA_SIZE
);
//pkt_size = DATA_SIZE + sizeof(struct rte_ether_hdr);
pkt_size
=
PACKET_SIZE
;
pkt_size
=
PACKET_SIZE
;
pkt
[
i
]
->
data_len
=
pkt_size
;
pkt
[
i
]
->
data_len
=
pkt_size
;
pkt
[
i
]
->
pkt_len
=
pkt_size
;
pkt
[
i
]
->
pkt_len
=
pkt_size
;
...
@@ -385,7 +410,6 @@ static void send_packets(int port) {
...
@@ -385,7 +410,6 @@ static void send_packets(int port) {
}
}
}
}
// TODO store received packets' data in buffer
static
int
recv_packets
(
int
port
)
{
static
int
recv_packets
(
int
port
)
{
struct
rte_mbuf
*
pkt
[
1024
];
struct
rte_mbuf
*
pkt
[
1024
];
uint8_t
*
buf
;
uint8_t
*
buf
;
...
@@ -396,7 +420,7 @@ static int recv_packets(int port) {
...
@@ -396,7 +420,7 @@ static int recv_packets(int port) {
for
(
int
i
=
0
;
i
<
nb_rx
;
i
++
)
{
for
(
int
i
=
0
;
i
<
nb_rx
;
i
++
)
{
buf
=
((
uint8_t
*
)
rx_rbuf
.
buffer
)
+
(
rx_rbuf
.
write_index
*
rx_rbuf
.
len
);
buf
=
((
uint8_t
*
)
rx_rbuf
.
buffer
)
+
(
rx_rbuf
.
write_index
*
rx_rbuf
.
len
);
rtebuf
=
(
uint8_t
*
)
(
pkt
[
i
])
->
buf_addr
+
(
pkt
[
i
])
->
data_off
;
rtebuf
=
(
uint8_t
*
)
(
pkt
[
i
])
->
buf_addr
+
(
pkt
[
i
])
->
data_off
;
memcpy
(
buf
,
rtebuf
,
PACKET_SIZE
);
memcpy
(
buf
,
rtebuf
,
(
pkt
[
i
])
->
pkt_len
);
rbuf_update_write_index
(
&
rx_rbuf
);
rbuf_update_write_index
(
&
rx_rbuf
);
rte_pktmbuf_free
(
pkt
[
i
]);
rte_pktmbuf_free
(
pkt
[
i
]);
}
}
...
@@ -445,10 +469,6 @@ static void *recv_thread(void *p) {
...
@@ -445,10 +469,6 @@ static void *recv_thread(void *p) {
update_counter
(
&
recv_counter
,
recv_packets
(
0
));
update_counter
(
&
recv_counter
,
recv_packets
(
0
));
//for(int j = 0; j < ecpri_period_mult; j++) {
// TODO write rx_buf
//}
pthread_mutex_lock
(
&
rx_mutex
);
pthread_mutex_lock
(
&
rx_mutex
);
pthread_cond_signal
(
&
rx_cond
);
pthread_cond_signal
(
&
rx_cond
);
pthread_mutex_unlock
(
&
rx_mutex
);
pthread_mutex_unlock
(
&
rx_mutex
);
...
@@ -461,6 +481,7 @@ static void *send_thread(void *p) {
...
@@ -461,6 +481,7 @@ static void *send_thread(void *p) {
cpu_set_t
mask
;
cpu_set_t
mask
;
struct
timespec
initial
,
next
;
struct
timespec
initial
,
next
;
TRXEcpriState
*
s
=
(
TRXEcpriState
*
)
p
;
TRXEcpriState
*
s
=
(
TRXEcpriState
*
)
p
;
log_info
(
"SEND_THREAD"
,
"Thread init"
);
log_info
(
"SEND_THREAD"
,
"Thread init"
);
// Set thread CPU affinity
// Set thread CPU affinity
...
@@ -489,6 +510,12 @@ static void *send_thread(void *p) {
...
@@ -489,6 +510,12 @@ static void *send_thread(void *p) {
}
}
#endif
#endif
// Prevent overflow
if
(
i
>=
3000000
)
{
add_ns
(
&
initial
,
(
ecpri_period_mult
*
NSEC_PER_SEC
*
i
)
/
FRAME_FREQ
);
i
=
0
;
}
next
=
initial
;
next
=
initial
;
// Multiply by i everytime to prevent any frequence drift
// Multiply by i everytime to prevent any frequence drift
add_ns
(
&
next
,
(
ecpri_period_mult
*
NSEC_PER_SEC
*
i
)
/
FRAME_FREQ
);
add_ns
(
&
next
,
(
ecpri_period_mult
*
NSEC_PER_SEC
*
i
)
/
FRAME_FREQ
);
...
@@ -516,6 +543,7 @@ static void *prepare_thread(void *p) {
...
@@ -516,6 +543,7 @@ static void *prepare_thread(void *p) {
cpu_set_t
mask
;
cpu_set_t
mask
;
TRXEcpriState
*
s
=
(
TRXEcpriState
*
)
p
;
TRXEcpriState
*
s
=
(
TRXEcpriState
*
)
p
;
int
tx_ready_buffer_full
=
0
;
int
tx_ready_buffer_full
=
0
;
int
tx_started
=
0
;
log_info
(
"PREPARE_THREAD"
,
"Thread init"
);
log_info
(
"PREPARE_THREAD"
,
"Thread init"
);
// Set thread CPU affinity
// Set thread CPU affinity
...
@@ -529,13 +557,30 @@ static void *prepare_thread(void *p) {
...
@@ -529,13 +557,30 @@ static void *prepare_thread(void *p) {
// If we have frames to prepare
// If we have frames to prepare
int
n
=
rbuf_write_amount
(
&
tx_rbuf
);
int
n
=
rbuf_write_amount
(
&
tx_rbuf
);
n
=
n
<
500
?
n
:
500
;
if
((
i
==
0
)
||
n
)
{
if
((
i
==
0
)
||
n
)
{
// If there are frames from trx_write callback to prepare
// If there are frames from trx_write callback to prepare
if
(
rbuf_read_amount
(
&
trx_write_rbuf
))
{
if
(
rbuf_read_amount
(
&
trx_write_rbuf
))
{
int64_t
ts
=
trx_wb_ts
[
trx_wb_part_read_index
];
int64_t
ts
;
int
empty_frames_ahead
=
ts
-
prepared_counter
.
counter
;
if
(
!
tx_started
)
prepared_counter
.
counter
=
0
;
tx_started
=
1
;
if
(
trx_wb_part_read_index
==
trx_wb_part_write_index
)
{
pthread_mutex_lock
(
&
trx_write_mutex
);
pthread_cond_signal
(
&
trx_write_cond
);
pthread_mutex_unlock
(
&
trx_write_mutex
);
continue
;
}
// Get the next timestamp at which we should write
ts
=
trx_wb_ts
[
trx_wb_part_read_index
];
// Number of empty frames to insert before next write
int64_t
empty_frames_ahead
=
ts
-
prepared_counter
.
counter
;
// We are sending only n frames in this iteration
empty_frames_ahead
=
empty_frames_ahead
<
n
?
empty_frames_ahead
:
n
;
empty_frames_ahead
=
empty_frames_ahead
<
n
?
empty_frames_ahead
:
n
;
if
(
empty_frames_ahead
>
0
)
{
if
(
empty_frames_ahead
>
0
)
{
// Send the empty frames
for
(
int
j
=
0
;
j
<
empty_frames_ahead
;
j
++
)
{
for
(
int
j
=
0
;
j
<
empty_frames_ahead
;
j
++
)
{
*
((
uint16_t
*
)
(
RBUF_WRITE
(
tx_rbuf
,
uint8_t
)
+
20
))
=
htons
(
seq_id
++
);
*
((
uint16_t
*
)
(
RBUF_WRITE
(
tx_rbuf
,
uint8_t
)
+
20
))
=
htons
(
seq_id
++
);
rbuf_update_write_index
(
&
tx_rbuf
);
rbuf_update_write_index
(
&
tx_rbuf
);
...
@@ -543,9 +588,15 @@ static void *prepare_thread(void *p) {
...
@@ -543,9 +588,15 @@ static void *prepare_thread(void *p) {
}
}
}
}
else
if
(
empty_frames_ahead
==
0
)
{
else
if
(
empty_frames_ahead
==
0
)
{
int
m
=
trx_wb_part
[(
trx_wb_part_read_index
+
1
)
%
TRX_WB_MAX_PARTS
]
-
trx_write_rbuf
.
read_index
;
int
next_trx_index
=
trx_wb_part
[(
trx_wb_part_read_index
+
1
)
%
TRX_WB_MAX_PARTS
];
m
=
m
<
n
?
m
:
n
;
// TRX frames to read and encode
for
(
int
j
=
0
;
j
<
m
;
j
++
)
{
int
nb_frames
=
next_trx_index
-
trx_write_rbuf
.
read_index
;
int
left_frames
=
nb_frames
;
nb_frames
=
nb_frames
<
n
?
nb_frames
:
n
;
left_frames
-=
nb_frames
;
for
(
int
j
=
0
;
j
<
nb_frames
;
j
++
)
{
float
*
const
trx_samples
=
RBUF_READ
(
trx_write_rbuf
,
float
);
float
*
const
trx_samples
=
RBUF_READ
(
trx_write_rbuf
,
float
);
uint8_t
*
const
tx_frame
=
RBUF_WRITE
(
tx_rbuf
,
uint8_t
);
uint8_t
*
const
tx_frame
=
RBUF_WRITE
(
tx_rbuf
,
uint8_t
);
memset
(
samples_int
,
0
,
512
);
memset
(
samples_int
,
0
,
512
);
...
@@ -562,14 +613,19 @@ static void *prepare_thread(void *p) {
...
@@ -562,14 +613,19 @@ static void *prepare_thread(void *p) {
rbuf_update_read_index
(
&
trx_write_rbuf
);
rbuf_update_read_index
(
&
trx_write_rbuf
);
update_counter
(
&
prepared_counter
,
1
);
update_counter
(
&
prepared_counter
,
1
);
}
}
if
(
m
==
0
)
if
(
left_frames
==
0
)
{
trx_wb_part_read_index
=
(
trx_wb_part_read_index
+
1
)
%
TRX_WB_MAX_PARTS
;
trx_wb_part_read_index
=
(
trx_wb_part_read_index
+
1
)
%
TRX_WB_MAX_PARTS
;
}
else
{
trx_wb_ts
[
trx_wb_part_read_index
]
+=
nb_frames
;
}
}
}
// We have sent too much empty frames and missed a timestamp
else
{
else
{
log_error
(
"
PREPARE_THREAD"
,
"missed trx_write timestamp"
);
log_error
(
"
TRX_ECPRI_SEND"
,
"Missed trx_write timestamp: p %015li ts %015li r %015li n %015li e %015li"
,
prepared_counter
.
counter
,
ts
,
rbuf_read_amount
(
&
trx_write_rbuf
),
n
,
empty_frames_ahead
);
}
}
}
}
else
{
else
if
(
!
tx_started
)
{
*
((
uint16_t
*
)
(
RBUF_WRITE
(
tx_rbuf
,
uint8_t
)
+
6
))
=
htons
(
seq_id
++
);
*
((
uint16_t
*
)
(
RBUF_WRITE
(
tx_rbuf
,
uint8_t
)
+
6
))
=
htons
(
seq_id
++
);
rbuf_update_write_index
(
&
tx_rbuf
);
rbuf_update_write_index
(
&
tx_rbuf
);
update_counter
(
&
prepared_counter
,
1
);
update_counter
(
&
prepared_counter
,
1
);
...
@@ -593,7 +649,6 @@ static void *decompress_thread(void *p) {
...
@@ -593,7 +649,6 @@ static void *decompress_thread(void *p) {
cpu_set_t
mask
;
cpu_set_t
mask
;
TRXEcpriState
*
s
=
(
TRXEcpriState
*
)
p
;
TRXEcpriState
*
s
=
(
TRXEcpriState
*
)
p
;
int
rx_ready
=
0
;
const
float
mult
=
1
.
/
32767
.;
const
float
mult
=
1
.
/
32767
.;
FILE
*
trace_file_desc
;
FILE
*
trace_file_desc
;
...
@@ -608,49 +663,54 @@ static void *decompress_thread(void *p) {
...
@@ -608,49 +663,54 @@ static void *decompress_thread(void *p) {
if
(
sched_setaffinity
(
0
,
sizeof
(
mask
),
&
mask
))
if
(
sched_setaffinity
(
0
,
sizeof
(
mask
),
&
mask
))
error
(
EXIT_FAILURE
,
errno
,
"Could not set CPU affinity to CPU %d
\n
"
,
s
->
decompress_affinity
);
error
(
EXIT_FAILURE
,
errno
,
"Could not set CPU affinity to CPU %d
\n
"
,
s
->
decompress_affinity
);
for
(
u
int64_t
k
=
0
;;)
{
for
(
int64_t
k
=
0
;;)
{
int
n
=
rbuf_read_amount
(
&
rx_rbuf
);
int
n
=
rbuf_read_amount
(
&
rx_rbuf
);
if
(
n
)
{
if
(
n
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
for
(
int
j
=
0
;
j
<
n
;
j
++
)
{
int16_t
samples_int
[
N_SAMPLES
];
int16_t
samples_int
[
N_SAMPLES
];
const
uint8_t
*
dst_mac
=
RBUF_READ
(
rx_rbuf
,
uint8_t
);
const
uint8_t
*
dst_mac
=
RBUF_READ
(
rx_rbuf
,
uint8_t
);
const
uint8_t
*
src_mac
=
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
6
;
const
uint8_t
*
src_mac
=
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
6
;
const
uint16_t
ether_type
=
(
uint16_t
)
*
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
12
);
const
uint16_t
ether_type
=
*
((
uint16_t
*
)
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
12
)
);
const
uint8_t
ecpri_protocol_rev
=
*
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
14
);
const
uint8_t
ecpri_protocol_rev
=
*
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
14
);
const
uint8_t
ecpri_message_type
=
*
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
15
);
const
uint8_t
ecpri_message_type
=
*
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
15
);
const
uint
8_t
ecpri_payload_size
=
*
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
16
);
const
uint
16_t
ecpri_payload_size
=
*
((
uint16_t
*
)
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
16
)
);
const
uint16_t
pc_id
=
(
uint16_t
)
*
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
18
);
const
uint16_t
pc_id
=
*
((
uint16_t
*
)
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
18
)
);
const
uint16_t
seq_id
=
(
uint16_t
)
*
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
20
);
const
uint16_t
seq_id
=
*
((
uint16_t
*
)
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
20
)
);
const
uint8_t
*
rx_samples
=
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
22
;
const
uint8_t
*
rx_samples
=
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
22
;
if
(
s
->
trace_period
&&
!
(
k
%
s
->
trace_period
))
{
if
(
s
->
trace_period
&&
!
(
k
%
s
->
trace_period
))
{
fprintf
(
trace_file_desc
,
fprintf
(
trace_file_desc
,
"%010"
PRIu64
" %x:%x:%x:%x:%x:%x %x:%x:%x:%x:%x:%x %x
\n
"
"%010"
PRIu64
" %x:%x:%x:%x:%x:%x %x:%x:%x:%x:%x:%x %x"
"
%x %x %u
\n
"
"
%x %x %x
"
"
%x %x
\n
"
,
" %x %x
\n
"
,
k
,
k
,
dst_mac
[
0
],
dst_mac
[
1
],
dst_mac
[
2
],
dst_mac
[
3
],
dst_mac
[
4
],
dst_mac
[
5
],
dst_mac
[
0
],
dst_mac
[
1
],
dst_mac
[
2
],
dst_mac
[
3
],
dst_mac
[
4
],
dst_mac
[
5
],
src_mac
[
0
],
src_mac
[
1
],
src_mac
[
2
],
src_mac
[
3
],
src_mac
[
4
],
src_mac
[
5
],
src_mac
[
0
],
src_mac
[
1
],
src_mac
[
2
],
src_mac
[
3
],
src_mac
[
4
],
src_mac
[
5
],
ether_type
,
ether_type
,
ecpri_protocol_rev
,
ecpri_message_type
,
ecpri_payload_size
,
ecpri_protocol_rev
,
ecpri_message_type
,
ecpri_payload_size
,
pc_id
,
seq_id
);
pc_id
,
seq_id
);
fprintf
(
trace_file_desc
,
"RAW PACKET: "
);
for
(
int
l
=
0
;
l
<
262
;
l
++
)
fprintf
(
trace_file_desc
,
"|%x"
,
*
(
RBUF_READ
(
rx_rbuf
,
uint8_t
)
+
l
));
fprintf
(
trace_file_desc
,
"
\n
"
);
fflush
(
trace_file_desc
);
}
}
k
++
;
k
++
;
// TODO : analyze seq_id, ecpri packet type etc... ?
// TODO : set rx_ready at some point (when ?)
rbuf_update_read_index
(
&
rx_rbuf
);
rbuf_update_read_index
(
&
rx_rbuf
);
if
(
rx_ready
)
{
#if 1
memset
(
samples_int
,
0
,
512
);
if
(
ecpri_payload_size
==
0xf400
)
{
memset
((
uint8_t
*
)
samples_int
,
0
,
512
);
decode_bf1
(
samples_int
,
rx_samples
,
16
);
decode_bf1
(
samples_int
,
rx_samples
,
16
);
decode_bf1
(
samples_int
+
64
,
rx_samples
+
60
,
16
);
decode_bf1
(
samples_int
+
64
,
rx_samples
+
60
,
16
);
decode_bf1
(
samples_int
+
128
,
rx_samples
+
120
,
16
);
decode_bf1
(
samples_int
+
128
,
rx_samples
+
120
,
16
);
decode_bf1
(
samples_int
+
192
,
rx_samples
+
180
,
16
);
decode_bf1
(
samples_int
+
192
,
rx_samples
+
180
,
16
);
int16_to_float
(
RBUF_WRITE
(
trx_read_rbuf
,
float
),
samples_int
,
N_SAMPLES
,
mult
);
int16_to_float
(
RBUF_WRITE
(
trx_read_rbuf
,
float
),
samples_int
,
N_SAMPLES
,
mult
);
rbuf_update_write_index
(
&
trx_read_rbuf
);
rbuf_update_write_index
(
&
trx_read_rbuf
);
sem_post
(
&
trx_read_sem
);
sem_post
(
&
trx_read_sem
);
}
}
#endif
}
}
}
}
else
{
else
{
...
@@ -666,9 +726,14 @@ static void *statistic_thread(void *p) {
...
@@ -666,9 +726,14 @@ static void *statistic_thread(void *p) {
cpu_set_t
mask
;
cpu_set_t
mask
;
int64_t
duration_ns
;
int64_t
duration_ns
;
TRXEcpriState
*
s
=
(
TRXEcpriState
*
)
p
;
TRXEcpriState
*
s
=
(
TRXEcpriState
*
)
p
;
FILE
*
stats_file_desc
;
log_info
(
"STATISTIC_THREAD"
,
"Thread init"
);
log_info
(
"STATISTIC_THREAD"
,
"Thread init"
);
stats_file_desc
=
fopen
(
s
->
stats_file
,
"w+"
);
if
(
!
stats_file_desc
)
error
(
EXIT_FAILURE
,
errno
,
"Couldn't open %s
\n
"
,
s
->
stats_file
);
// Set thread CPU affinity
// Set thread CPU affinity
CPU_ZERO
(
&
mask
);
CPU_ZERO
(
&
mask
);
CPU_SET
(
s
->
statistic_affinity
,
&
mask
);
CPU_SET
(
s
->
statistic_affinity
,
&
mask
);
...
@@ -677,7 +742,8 @@ static void *statistic_thread(void *p) {
...
@@ -677,7 +742,8 @@ static void *statistic_thread(void *p) {
clock_gettime
(
CLOCK_TAI
,
&
initial
);
clock_gettime
(
CLOCK_TAI
,
&
initial
);
next
=
initial
;
next
=
initial
;
log_info
(
"STATS"
,
"%14s - %14s - %14s - %14s - %14s %14s "
,
fprintf
(
stats_file_desc
,
"%14s - %14s - %14s - %14s - %14s %14s
\n
"
,
"prepared"
,
"prepared"
,
"read"
,
"read"
,
"sent"
,
"sent"
,
...
@@ -686,13 +752,15 @@ static void *statistic_thread(void *p) {
...
@@ -686,13 +752,15 @@ static void *statistic_thread(void *p) {
"ppsr"
);
"ppsr"
);
for
(;;)
{
for
(;;)
{
add_ns
(
&
next
,
STATISTIC_REFRESH_RATE
);
add_ns
(
&
next
,
STATISTIC_REFRESH_RATE
);
log_info
(
"STATS"
,
"%14"
PRIi64
" - %14"
PRIi64
" - %14"
PRIi64
" - %14"
PRIi64
" - %14"
PRIi64
"pps %14"
PRIi64
"pps"
,
fprintf
(
stats_file_desc
,
"%14"
PRIi64
" - %14"
PRIi64
" - %14"
PRIi64
" - %14"
PRIi64
" - %14"
PRIi64
"pps %14"
PRIi64
"pps
\n
"
,
prepared_counter
.
counter
,
prepared_counter
.
counter
,
read_counter
.
counter
,
read_counter
.
counter
,
sent_counter
.
counter
,
sent_counter
.
counter
,
recv_counter
.
counter
,
recv_counter
.
counter
,
sent_counter
.
pps
,
sent_counter
.
pps
,
recv_counter
.
pps
);
recv_counter
.
pps
);
fflush
(
stats_file_desc
);
clock_nanosleep
(
CLOCK_TAI
,
TIMER_ABSTIME
,
&
next
,
NULL
);
clock_nanosleep
(
CLOCK_TAI
,
TIMER_ABSTIME
,
&
next
,
NULL
);
}
}
pthread_exit
(
EXIT_SUCCESS
);
pthread_exit
(
EXIT_SUCCESS
);
...
@@ -781,14 +849,14 @@ static int start_threads(TRXEcpriState * s) {
...
@@ -781,14 +849,14 @@ static int start_threads(TRXEcpriState * s) {
if
(
pthread_attr_setinheritsched
(
&
statistic_attr
,
PTHREAD_EXPLICIT_SCHED
))
if
(
pthread_attr_setinheritsched
(
&
statistic_attr
,
PTHREAD_EXPLICIT_SCHED
))
log_error
(
"TRX_ECPRI"
,
"pthread setinheritsched failed
\n
"
);
log_error
(
"TRX_ECPRI"
,
"pthread setinheritsched failed
\n
"
);
if
(
pthread_create
(
&
recv_pthread
,
NULL
,
recv_thread
,
s
))
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create recv thread"
);
if
(
pthread_create
(
&
send_pthread
,
NULL
,
send_thread
,
s
))
if
(
pthread_create
(
&
send_pthread
,
NULL
,
send_thread
,
s
))
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create send thread"
);
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create send thread"
);
if
(
pthread_create
(
&
prepare_pthread
,
NULL
,
prepare_thread
,
s
))
if
(
pthread_create
(
&
prepare_pthread
,
NULL
,
prepare_thread
,
s
))
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create prepare thread"
);
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create prepare thread"
);
if
(
pthread_create
(
&
decompress_pthread
,
NULL
,
decompress_thread
,
s
))
if
(
pthread_create
(
&
decompress_pthread
,
NULL
,
decompress_thread
,
s
))
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create decompress thread"
);
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create decompress thread"
);
if
(
pthread_create
(
&
recv_pthread
,
NULL
,
recv_thread
,
s
))
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create recv thread"
);
if
(
pthread_create
(
&
statistic_pthread
,
NULL
,
statistic_thread
,
s
))
if
(
pthread_create
(
&
statistic_pthread
,
NULL
,
statistic_thread
,
s
))
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create statistic thread"
);
error
(
EXIT_FAILURE
,
errno
,
"Couldn't create statistic thread"
);
...
@@ -825,7 +893,7 @@ int startdpdk(TRXEcpriState * s) {
...
@@ -825,7 +893,7 @@ int startdpdk(TRXEcpriState * s) {
}
}
init_dpdk
(
argc
,
argv
);
init_dpdk
(
argc
,
argv
);
log_
debug
(
"TRX_ECPRI"
,
"s
tart"
);
log_
info
(
"TRX_ECPRI"
,
"S
tart"
);
//set_latency_target();
//set_latency_target();
...
@@ -875,9 +943,10 @@ int startdpdk(TRXEcpriState * s) {
...
@@ -875,9 +943,10 @@ int startdpdk(TRXEcpriState * s) {
/* Standard Header */
/* Standard Header */
ecpri_message
[
0
]
=
0x10
;
// Protocol data revision 0x1, C = 0
ecpri_message
[
0
]
=
0x10
;
// Protocol data revision 0x1, C = 0
// Message type = 0x00, IQ data
// Message type = 0x00, IQ data
// Payload size
// Payload size
*
((
uint16_t
*
)
(
ecpri_message
+
2
))
=
htons
(
DATA_SIZE
);
*
((
uint16_t
*
)
(
ecpri_message
+
2
))
=
htons
(
244
);
*
((
uint16_t
*
)
(
ecpri_message
+
4
))
=
htons
(
s
->
flow_id
);
*
((
uint16_t
*
)
(
ecpri_message
+
4
))
=
htons
(
s
->
flow_id
);
for
(
int
i
=
0
;
i
<
rxtx_buf_size
;
i
++
)
for
(
int
i
=
0
;
i
<
rxtx_buf_size
;
i
++
)
...
@@ -898,37 +967,44 @@ static void trx_ecpri_write(TRXState *s1, trx_timestamp_t timestamp, const void
...
@@ -898,37 +967,44 @@ static void trx_ecpri_write(TRXState *s1, trx_timestamp_t timestamp, const void
{
{
(
void
)
s1
;
(
void
)
s1
;
float
**
_samples
=
(
float
**
)
__samples
;
float
**
_samples
=
(
float
**
)
__samples
;
int
write_count
=
count
>>
5
;
int
write_count
=
count
/
256
;
int64_t
ts
=
timestamp
>>
5
;
int64_t
ts
=
timestamp
/
256
;
if
(
!
__samples
)
return
;
pthread_mutex_lock
(
&
trx_write_mutex
);
pthread_cond_signal
(
&
trx_write_cond
);
pthread_mutex_unlock
(
&
trx_write_mutex
);
trx_wb_part
[
trx_wb_part_write_index
]
=
trx_write_rbuf
.
write_index
;
trx_wb_part
[
trx_wb_part_write_index
]
=
trx_write_rbuf
.
write_index
;
trx_wb_ts
[
trx_wb_part_write_index
]
=
ts
;
trx_wb_ts
[
trx_wb_part_write_index
]
=
ts
;
for
(
int
k
=
0
;
k
<
write_count
;
k
++
)
{
for
(
int
k
=
0
;
k
<
write_count
;
k
++
)
{
for
(
int
i
=
0
;
i
<
4
;
i
++
)
for
(
int
i
=
0
;
i
<
4
;
i
++
)
for
(
int
j
=
0
;
j
<
64
;
j
++
)
for
(
int
j
=
0
;
j
<
64
;
j
++
)
{
RBUF_WRITE
(
trx_write_rbuf
,
float
)[
i
*
64
+
j
]
=
_samples
[
i
][
j
+
(
k
<<
6
)];
RBUF_WRITE
(
trx_write_rbuf
,
float
)[
i
*
64
+
j
]
=
_samples
[
i
][
j
+
(
k
*
64
)];
}
rbuf_update_write_index
(
&
trx_write_rbuf
);
rbuf_update_write_index
(
&
trx_write_rbuf
);
}
}
trx_wb_part_write_index
=
(
trx_wb_part_write_index
+
1
)
%
TRX_WB_MAX_PARTS
;
trx_wb_part_write_index
=
(
trx_wb_part_write_index
+
1
)
%
TRX_WB_MAX_PARTS
;
trx_wb_part
[
trx_wb_part_write_index
]
=
trx_write_rbuf
.
write_index
+
write_count
;
trx_wb_part
[
trx_wb_part_write_index
]
=
trx_write_rbuf
.
write_index
;
}
}
static
int
trx_ecpri_read
(
TRXState
*
s1
,
trx_timestamp_t
*
ptimestamp
,
void
**
__samples
,
int
count
,
int
rx_port_index
,
TRXReadMetadata
*
md
)
static
int
trx_ecpri_read
(
TRXState
*
s1
,
trx_timestamp_t
*
ptimestamp
,
void
**
__samples
,
int
count
,
int
rx_port_index
,
TRXReadMetadata
*
md
)
{
{
(
void
)
s1
;
(
void
)
s1
;
float
**
_samples
=
(
float
**
)
__samples
;
float
**
_samples
=
(
float
**
)
__samples
;
int
read_count
=
count
>>
5
;
int
read_count
=
(
count
/
256
)
;
for
(
int
k
=
0
;
k
<
read_count
;
k
++
)
{
for
(
int
k
=
0
;
k
<
read_count
;
k
++
)
{
float
*
trx_samples
;
float
*
trx_samples
;
sem_wait
(
&
trx_read_sem
);
sem_wait
(
&
trx_read_sem
);
trx_samples
=
RBUF_READ
(
trx_read_rbuf
,
float
);
trx_samples
=
RBUF_READ
(
trx_read_rbuf
,
float
);
for
(
int
i
=
0
;
i
<
4
;
i
++
)
for
(
int
i
=
0
;
i
<
256
;
i
++
)
for
(
int
j
=
0
;
j
<
64
;
j
++
)
_samples
[
0
][
i
]
=
trx_samples
[
i
];
_samples
[
i
][
j
+
(
k
<<
6
)]
=
trx_samples
[
i
*
64
+
j
];
rbuf_update_read_index
(
&
trx_read_rbuf
);
rbuf_update_read_index
(
&
trx_read_rbuf
);
}
}
*
ptimestamp
=
read_counter
.
counter
<<
5
;
*
ptimestamp
=
read_counter
.
counter
*
256
;
update_counter
(
&
read_counter
,
read_count
);
update_counter
(
&
read_counter
,
read_count
);
return
count
;
return
count
;
...
@@ -947,7 +1023,10 @@ static int trx_ecpri_start(TRXState *s1, const TRXDriverParams *params)
...
@@ -947,7 +1023,10 @@ static int trx_ecpri_start(TRXState *s1, const TRXDriverParams *params)
{
{
TRXEcpriState
*
s
=
s1
->
opaque
;
TRXEcpriState
*
s
=
s1
->
opaque
;
log_debug
(
"TRX_ECPRI_START"
,
"Start"
);
log_info
(
"TRX_ECPRI_START"
,
"Start"
);
log_info
(
"TRX_ECPRI_START"
,
"trx_api_version: %d"
,
s1
->
trx_api_version
);
log_info
(
"TRX_ECPRI_START"
,
"config file: %s"
,
s1
->
path
);
s
->
sample_rate
=
params
->
sample_rate
[
0
].
num
/
params
->
sample_rate
[
0
].
den
;
s
->
sample_rate
=
params
->
sample_rate
[
0
].
num
/
params
->
sample_rate
[
0
].
den
;
...
@@ -956,6 +1035,12 @@ static int trx_ecpri_start(TRXState *s1, const TRXDriverParams *params)
...
@@ -956,6 +1035,12 @@ static int trx_ecpri_start(TRXState *s1, const TRXDriverParams *params)
return
0
;
return
0
;
}
}
void
dummy_enb_init
(
TRXState
*
s1
,
TRXEcpriState
*
s
)
{
s1
->
trx_write_func2
=
trx_ecpri_write
;
s1
->
trx_read_func2
=
trx_ecpri_read
;
startdpdk
(
s
);
}
int
trx_driver_init
(
TRXState
*
s1
)
int
trx_driver_init
(
TRXState
*
s1
)
{
{
TRXEcpriState
*
s
;
TRXEcpriState
*
s
;
...
@@ -1004,6 +1089,7 @@ int trx_driver_init(TRXState *s1)
...
@@ -1004,6 +1089,7 @@ int trx_driver_init(TRXState *s1)
s
->
rec_if
=
trx_get_param_string
(
s1
,
"rec_if"
);
s
->
rec_if
=
trx_get_param_string
(
s1
,
"rec_if"
);
s
->
dpdk_options
=
trx_get_param_string
(
s1
,
"dpdk_options"
);
s
->
dpdk_options
=
trx_get_param_string
(
s1
,
"dpdk_options"
);
s
->
trace_file
=
trx_get_param_string
(
s1
,
"trace_file"
);
s
->
trace_file
=
trx_get_param_string
(
s1
,
"trace_file"
);
s
->
stats_file
=
trx_get_param_string
(
s1
,
"stats_file"
);
s1
->
opaque
=
s
;
s1
->
opaque
=
s
;
s1
->
trx_end_func
=
trx_ecpri_end
;
s1
->
trx_end_func
=
trx_ecpri_end
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment