* INTC Contribution to the O-RAN F Release for O-DU Low
[o-du/phy.git] / fhi_lib / test / master.py
1 #!/usr/bin/python
2 #******************************************************************************
3 #
4 #   Copyright (c) 2020 Intel.
5 #
6 #   Licensed under the Apache License, Version 2.0 (the "License");
7 #   you may not use this file except in compliance with the License.
8 #   You may obtain a copy of the License at
9 #
10 #       http://www.apache.org/licenses/LICENSE-2.0
11 #
12 #   Unless required by applicable law or agreed to in writing, software
13 #   distributed under the License is distributed on an "AS IS" BASIS,
14 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 #   See the License for the specific language governing permissions and
16 #   limitations under the License.
17 #
18 #******************************************************************************/
19
20 """This script runs test cases with O-DU and O-RU
21 """
22 import logging
23 import sys
24 import argparse
25 import re
26 import signal
27 import subprocess
28 import os
29 import shutil
30 import copy
31 from itertools import dropwhile
32 from datetime import datetime
33 from time import gmtime, strftime
34 import json
35 from threading import Timer
36 import socket
37
38 timeout_sec = 60*5 #5 min max
39
40 nLteNumRbsPerSymF1 = [
41     #  5MHz    10MHz   15MHz   20 MHz
42         [25,    50,     75,     100]  # LTE Numerology 0 (15KHz)
43 ]
44
45 nNumRbsPerSymF1 = [
46     #  5MHz    10MHz   15MHz   20 MHz  25 MHz  30 MHz  40 MHz  50MHz   60 MHz  70 MHz  80 MHz   90 MHz  100 MHz
47         [25,    52,     79,     106,    133,    160,    216,    270,    0,         0,      0,      0,      0],         # Numerology 0 (15KHz)
48         [11,    24,     38,     51,     65,     78,     106,    133,    162,       0,    217,    245,    273],         # Numerology 1 (30KHz)
49         [0,     11,     18,     24,     31,     38,     51,     65,     79,        0,    107,    121,    135]          # Numerology 2 (60KHz)
50 ]
51
52 nNumRbsPerSymF2 = [
53     # 50Mhz  100MHz  200MHz   400MHz
54     [66,    132,    264,     0],       # Numerology 2 (60KHz)
55     [32,    66,     132,     264]      # Numerology 3 (120KHz)
56 ]
57
58
59 nRChBwOptions_keys = ['5','10','15','20', '25', '30', '40', '50', '60','70', '80', '90', '100', '200', '400']
60 nRChBwOptions_values = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
61 nRChBwOptions = dict(zip(nRChBwOptions_keys, nRChBwOptions_values))
62
63 nRChBwOptions_keys_mu2and3 = ['50', '100', '200', '400']
64 nRChBwOptions_values_mu2and3 = [0,1,2,3]
65 nRChBwOptions_mu2and3 = dict(zip(nRChBwOptions_keys_mu2and3, nRChBwOptions_values_mu2and3))
66
67 vf_addr_o_xu=[]
68
69 # values for Jenkins server
70 vf_addr_o_xu_jenkins = [
71     #vf_addr_o_xu_a                     vf_addr_o_xu_b                vf_addr_o_xu_c                vf_addr_o_xu_d
72     ["0000:18:01.0,0000:18:01.1", "0000:18:09.0,0000:18:09.1", "0000:18:11.0,0000:18:11.1", "0000:18:19.0,0000:18:19.1" ], #O-DU
73     ["0000:af:01.0,0000:af:01.1", "0000:af:09.0,0000:af:09.1", "0000:af:11.0,0000:af:11.1", "0000:af:19.0,0000:af:19.1" ], #O-RU
74 ]
75
76 vf_addr_o_xu_sc12 = [ # 2x2x25G with loopback FVL0:port0 to FVL1:port 0 FVL0:port1 to FVL1:port 1
77     #vf_addr_o_xu_a                     vf_addr_o_xu_b                vf_addr_o_xu_c
78     ["0000:88:02.0,0000:88:0a.0", "0000:88:02.1,0000:88:0a.1", "0000:88:02.2,0000:88:0a.2", "0000:88:02.3,0000:88:0a.3" ], #O-DU
79     ["0000:86:02.0,0000:86:0a.0", "0000:86:02.1,0000:86:0a.1", "0000:86:02.2,0000:86:0a.2", "0000:86:02.3,0000:86:0a.3" ], #O-RU
80 ]
81
82 vf_addr_o_xu_sc12_cvl = [
83     #vf_addr_o_xu_a                     vf_addr_o_xu_b                vf_addr_o_xu_c
84     ["0000:af:01.0,0000:af:09.0", "0000:af:11.0,0000:af:19.0", "0000:1b:01.0,0000:1b:09.0", "0000:1b:11.0,0000:1b:19.0" ], #O-DU
85     ["0000:af:01.0,0000:af:09.0", "0000:af:11.0,0000:af:19.0", "0000:1a:01.0,0000:1a:09.0", "0000:1a:11.0,0000:1a:19.0" ], #O-RU
86 ]
87
88 vf_addr_o_xu_scs1_30 = [
89     ["0000:65:01.0,0000:65:01.1,0000:65:01.2,0000:65:01.3", "0000:65:01.4,0000:65:01.5,0000:65:01.6,0000:65:01.7", "0000:65:02.0,0000:65:02.1,0000:65:02.2,0000:65:02.3", "0000:65:02.4,0000:65:02.5,0000:65:02.6,0000:65:02.7" ], #O-DU
90     ["0000:65:09.0,0000:65:09.1,0000:65:09.2,0000:65:09.3", "0000:65:09.4,0000:65:09.5,0000:65:09.6,0000:65:09.7", "0000:65:0a.0,0000:65:0a.1,0000:65:0a.2,0000:65:0a.3", "0000:65:0a.4,0000:65:0a.5,0000:65:0a.6,0000:65:0a.7" ], #O-RU
91 ]
92
93 vf_addr_o_xu_scs1_repo = [
94     ["0000:18:01.0,0000:18:01.1,0000:18:01.2,0000:18:01.3", "0000:18:01.4,0000:18:01.5,0000:18:01.6,0000:18:01.7", "0000:18:02.0,0000:18:02.1,0000:18:02.2,0000:18:02.3", "0000:18:02.4,0000:18:02.5,0000:18:02.6,0000:18:02.7" ], #O-DU
95     ["0000:18:11.0,0000:18:11.1,0000:18:11.2,0000:18:11.3", "0000:18:11.4,0000:18:11.5,0000:18:11.6,0000:18:11.7", "0000:18:12.0,0000:18:12.1,0000:18:12.2,0000:18:12.3", "0000:18:12.4,0000:18:12.5,0000:18:12.6,0000:18:12.7" ], #O-RU
96 ]
97
98 vf_addr_o_xu_icelake_scs1_1 = [
99         #vf_addr_o_xu_a                  vf_addr_o_xu_b               vf_addr_o_xu_c            vf_addr_o_xu_d
100     ["0000:51:01.0,0000:51:09.0", "0000:51:11.0,0000:51:19.0", "0000:18:01.0,0000:18:09.0", "0000:18:01.1,0000:18:09.1" ], #O-DU
101     ["0000:17:01.0,0000:17:09.0", "0000:17:11.0,0000:17:19.0", "0000:65:01.0,0000:65:09.0", "0000:65:01.1,0000:65:09.1" ], #O-RU
102 ]
103
104 vf_addr_o_xu_icx_npg_scs1_coyote4 = [
105         #vf_addr_o_xu_a                  vf_addr_o_xu_b              vf_addr_o_xu_c             vf_addr_o_xu_d
106     ["0000:51:01.0,0000:51:09.0", "0000:51:11.0,0000:51:19.0", "0000:51:11.1,0000:51:19.1", "0000:51:01.1,0000:51:09.1" ], #O-DU
107     ["0000:17:01.0,0000:17:09.0", "0000:17:11.0,0000:17:19.0", "0000:17:11.1,0000:17:19.1", "0000:17:01.1,0000:17:09.1" ], #O-RU
108 ]
109
110 vf_addr_o_xu_scs1_35 = [
111     ["0000:86:01.0,0000:86:01.1,0000:86:01.2,0000:86:01.3", "0000:86:01.4,0000:86:01.5,0000:86:01.6,0000:86:01.7", "0000:86:02.0,0000:86:02.1,0000:86:02.2,0000:86:02.3", "0000:86:02.4,0000:86:02.5,0000:86:02.6,0000:86:02.7" ], #O-DU
112     ["0000:86:11.0,0000:86:11.1,0000:86:11.2,0000:86:11.3", "0000:86:11.4,0000:86:11.5,0000:86:11.6,0000:86:11.7", "0000:86:12.0,0000:86:12.1,0000:86:12.2,0000:86:12.3", "0000:86:12.4,0000:86:12.5,0000:86:12.6,0000:86:12.7" ], #O-RU
113 ]
114
115 vf_addr_o_xu_csl_npg_scs1_33 = [
116     #vf_addr_o_xu_a                     vf_addr_o_xu_b                vf_addr_o_xu_c
117     ["0000:1a:01.0,0000:1a:01.1", "0000:1a:01.2,0000:1a:01.3", "0000:1a:01.4,0000:1a:01.5", "0000:1a:01.6,0000:1a:01.7" ], #O-DU
118     ["0000:1a:11.0,0000:1a:11.1", "0000:1a:11.2,0000:1a:11.3", "0000:1a:11.4,0000:1a:11.5", "0000:1a:11.6,0000:1a:11.7" ], #O-RU
119 ]
120
121 vf_addr_o_xu_skx_5gnr_sd6 = [
122     #vf_addr_o_xu_a                     vf_addr_o_xu_b                vf_addr_o_xu_c             vf_addr_o_xu_d
123     ["0000:af:01.0,0000:af:09.0", "0000:af:11.0,0000:af:19.0", "0000:af:11.1,0000:af:19.1", "0000:af:01.1,0000:af:09.1"], #O-DU
124     ["0000:18:01.0,0000:18:09.0", "0000:18:11.0,0000:18:19.0", "0000:18:11.1,0000:18:19.1", "0000:18:01.1,0000:18:09.1"], #O-RU
125 ]
126
127
128 # table of all test cases
129 #                 (ran, cat, mu, bw, test case, "test case description")
130 #Cat A
131 NR_test_cases_A = [(0,  0,   0,  5,   0,  "NR_Sub6_Cat_A_5MHz_1_Cell_0"),
132                    (0,  0,   0,  10,  12, "NR_Sub6_Cat_A_10MHz_12_Cell_12"),
133                    (0,  0,   0,  20,  12, "NR_Sub6_Cat_A_20MHz_12_Cell_12"),
134                    (0,  0,   0,  20,  20, "NR_Sub6_Cat_A_20MHz_1_Cell_owd_req_resp"),
135                    (0,  0,   1,  100, 0,  "NR_Sub6_Cat_A_100MHz_1_Cell_0"),
136                    (0,  0,   3,  100, 7,  "NR_mmWave_Cat_A_100MHz_1_Cell_0_sc"),
137 ]
138
139 NR_test_cases_A_ext = [(0,  0,   0,  5,   0,  "NR_Sub6_Cat_A_5MHz_1_Cell_0"),
140                    (0,  0,   0,  10,  0,  "NR_Sub6_Cat_A_10MHz_1_Cell_0"),
141                    (0,  0,   0,  10,  12, "NR_Sub6_Cat_A_10MHz_12_Cell_12"),
142                    (0,  0,   0,  20,  0,  "NR_Sub6_Cat_A_20MHz_1_Cell_0"),
143                    (0,  0,   0,  20,  12, "NR_Sub6_Cat_A_20MHz_12_Cell_12"),
144                    (0,  0,   0,  20,  20, "NR_Sub6_Cat_A_20MHz_1_Cell_owd_req_resp"),
145                    (0,  0,   0,  20,  21, "NR_Sub6_Cat_A_20MHz_1_Cell_owd_rem_req"),
146                    (0,  0,   0,  20,  22, "NR_Sub6_Cat_A_20MHz_1_Cell_owd_req_wfup"),
147                    (0,  0,   0,  20,  23, "NR_Sub6_Cat_A_20MHz_1_Cell_owd_rem_req_wfup"),
148                    (0,  0,   1,  100, 0,  "NR_Sub6_Cat_A_100MHz_1_Cell_0"),
149                    (0,  0,   3,  100, 0,  "NR_mmWave_Cat_A_100MHz_1_Cell_0"),
150                    (0,  0,   3,  100, 7,  "NR_mmWave_Cat_A_100MHz_1_Cell_0_sc"),
151 ]
152
153 j_test_cases_A   = [(0,  0,  1, 100, 204,"NR_Sub6_Cat_A_100MHz_4_O_RU_2Ant"),
154                     (0,  0,  1, 100, 404,"NR_Sub6_Cat_A_100MHz_4_O_RU_4Ant")
155 ]
156
157 j_test_cases_A_ext  = [(0,  0,  1, 100, 201,"NR_Sub6_Cat_A_100MHz_1_O_RU_2Ant"),
158                     (0,  0,  1, 100, 202,"NR_Sub6_Cat_A_100MHz_2_O_RU_2Ant"),
159                     (0,  0,  1, 100, 203,"NR_Sub6_Cat_A_100MHz_3_O_RU_2Ant"),
160                     (0,  0,  1, 100, 204,"NR_Sub6_Cat_A_100MHz_4_O_RU_2Ant"),
161                     (0,  0,  1, 100, 401,"NR_Sub6_Cat_A_100MHz_1_O_RU_4Ant"),
162                     (0,  0,  1, 100, 402,"NR_Sub6_Cat_A_100MHz_2_O_RU_4Ant"),
163                     (0,  0,  1, 100, 403,"NR_Sub6_Cat_A_100MHz_3_O_RU_4Ant"),
164                     (0,  0,  1, 100, 404,"NR_Sub6_Cat_A_100MHz_4_O_RU_4Ant")
165 ]
166
167
168 LTE_test_cases_A = [(1,  0,   0,  5,   0, "LTE_Cat_A_5Hz_1_Cell_0"),
169                     (1,  0,   0,  10,  0, "LTE_Cat_A_10Hz_1_Cell_0"),
170                     (1,  0,   0,  20,  0, "LTE_Cat_A_20Hz_1_Cell_0"),
171 ]
172
173 DSS_test_cases_A = [(2,  0,   0,  20,  10, "DSS_Cat_A_20MHz_FDD_1_Cell"),
174                     (2,  0,   0,  20,  11, "DSS_Cat_A_20MHz_TDD_1_Cell"),
175                     (2,  0,   0,  20,  60, "DSS_Cat_A_20MHz_FDD_6_Cell"),
176                     (2,  0,   0,  20,  61, "DSS_Cat_A_20MHz_TDD_6_Cell"),
177                     (2,  0,   0,  10,  10, "DSS_Cat_A_10MHz_FDD_1_Cell"),
178                     (2,  0,   0,  10,  11, "DSS_Cat_A_10MHz_TDD_1_Cell"),
179                     (2,  0,   0,  10,  60, "DSS_Cat_A_10MHz_FDD_6_Cell"),
180                     (2,  0,   0,  10,  61, "DSS_Cat_A_10MHz_TDD_6_Cell"),
181                     (2,  0,   0,   5,  10, "DSS_Cat_A_5MHz_FDD_1_Cell"),
182                     (2,  0,   0,   5,  11, "DSS_Cat_A_5MHz_TDD_1_Cell"),
183                     (2,  0,   0,   5,  60, "DSS_Cat_A_5MHz_FDD_6_Cell"),
184                     (2,  0,   0,   5,  61, "DSS_Cat_A_5MHz_TDD_6_Cell"),
185 ]
186
187 #Cat B
188 NR_test_cases_B  =  [(0, 1,   1,  100, 0, "NR_Sub6_Cat_B_100MHz_1_Cell_0"),
189                      (0, 1,   1,  100, 216, "NR_Sub6_Cat_B_100MHz_1_Cell_216"),
190 ]
191
192 NR_test_cases_B_ext =  [(0, 1,   1,  100, 0, "NR_Sub6_Cat_B_100MHz_1_Cell_0"),
193                      (0, 1,   1,  100, 1, "NR_Sub6_Cat_B_100MHz_1_Cell_1"),
194                      (0, 1,   1,  100, 2, "NR_Sub6_Cat_B_100MHz_1_Cell_1_ext1"),
195                      (0, 1,   1,  100, 101, "NR_Sub6_Cat_B_100MHz_1_Cell_101"),
196                      (0, 1,   1,  100, 102, "NR_Sub6_Cat_B_100MHz_1_Cell_102"),
197                      (0, 1,   1,  100, 103, "NR_Sub6_Cat_B_100MHz_1_Cell_103"),
198                      (0, 1,   1,  100, 104, "NR_Sub6_Cat_B_100MHz_1_Cell_104"),
199                      (0, 1,   1,  100, 105, "NR_Sub6_Cat_B_100MHz_1_Cell_105"),
200                      (0, 1,   1,  100, 106, "NR_Sub6_Cat_B_100MHz_1_Cell_106"),
201                      (0, 1,   1,  100, 107, "NR_Sub6_Cat_B_100MHz_1_Cell_107"),
202                      (0, 1,   1,  100, 108, "NR_Sub6_Cat_B_100MHz_1_Cell_108"),
203                      (0, 1,   1,  100, 109, "NR_Sub6_Cat_B_100MHz_1_Cell_109"),
204                      (0, 1,   1,  100, 201, "NR_Sub6_Cat_B_100MHz_1_Cell_201"),
205                      (0, 1,   1,  100, 202, "NR_Sub6_Cat_B_100MHz_1_Cell_202"),
206                      (0, 1,   1,  100, 203, "NR_Sub6_Cat_B_100MHz_1_Cell_203"),
207                      (0, 1,   1,  100, 204, "NR_Sub6_Cat_B_100MHz_1_Cell_204"),
208                      (0, 1,   1,  100, 205, "NR_Sub6_Cat_B_100MHz_1_Cell_205"),
209                      (0, 1,   1,  100, 206, "NR_Sub6_Cat_B_100MHz_1_Cell_206"),
210                      (0, 1,   1,  100, 211, "NR_Sub6_Cat_B_100MHz_1_Cell_211"),
211                      (0, 1,   1,  100, 212, "NR_Sub6_Cat_B_100MHz_1_Cell_212"),
212                      (0, 1,   1,  100, 213, "NR_Sub6_Cat_B_100MHz_1_Cell_213"),
213                      (0, 1,   1,  100, 214, "NR_Sub6_Cat_B_100MHz_1_Cell_214"),
214                      (0, 1,   1,  100, 215, "NR_Sub6_Cat_B_100MHz_1_Cell_215"),
215                      (0, 1,   1,  100, 216, "NR_Sub6_Cat_B_100MHz_1_Cell_216"),
216 ]
217
218 LTE_test_cases_B = [(1,  1,   0,  20,  0, "LTE_Cat_B_20MHz_1_Cell_0"),
219 ]
220
221 LTE_test_cases_B_ext = [(1,  1,   0,   5,  0, "LTE_Cat_B_5MHz_1_Cell_0"),
222                     (1,  1,   0,  10,  0, "LTE_Cat_B_10MHz_1_Cell_0"),
223                     (1,  1,   0,  20,  0, "LTE_Cat_B_20MHz_1_Cell_0"),
224                     (1,  1,   0,  5,   1, "LTE_Cat_B_5Hz_1_Cell_0_sc"),
225                     (1,  1,   0,  10,  1, "LTE_Cat_B_10Hz_1_Cell_0_sc"),
226                     (1,  1,   0,  20,  1, "LTE_Cat_B_20Hz_1_Cell_0_sc"),
227
228 ]
229
230
231 V_test_cases_B = [
232                     # (0,  1,   1,  100,  301, "NR_Sub6_Cat_B_100MHz_1_Cell_301"),
233                     (0,  1,   1,  100,  602, "NR_Sub6_Cat_B_100MHz_1_Cell_602_sc"),
234 ]
235
236 V_test_cases_B_ext = [
237                     (0,  1,   1,  100,  301, "NR_Sub6_Cat_B_100MHz_1_Cell_301"),
238                     (0,  1,   1,  100,  302, "NR_Sub6_Cat_B_100MHz_1_Cell_302"),
239                     (0,  1,   1,  100,  303, "NR_Sub6_Cat_B_100MHz_1_Cell_303"),
240                     (0,  1,   1,  100,  304, "NR_Sub6_Cat_B_100MHz_1_Cell_304"),
241                     (0,  1,   1,  100,  305, "NR_Sub6_Cat_B_100MHz_1_Cell_305"),
242                     (0,  1,   1,  100,  306, "NR_Sub6_Cat_B_100MHz_1_Cell_306"),
243                     (0,  1,   1,  100,  602, "NR_Sub6_Cat_B_100MHz_1_Cell_602_sc"),
244 ]
245
246
247 V_test_cases_B_2xUL = [
248                   #  (0,  1,   1,  100,  311, "NR_Sub6_Cat_B_100MHz_1_Cell_311"),
249                     (0,  1,   1,  100,  612, "NR_Sub6_Cat_B_100MHz_1_Cell_612_sc"),
250
251 ]
252
253 V_test_cases_B_2xUL_ext = [
254                     (0,  1,   1,  100,  311, "NR_Sub6_Cat_B_100MHz_1_Cell_311"),
255                     (0,  1,   1,  100,  312, "NR_Sub6_Cat_B_100MHz_1_Cell_312"),
256                     (0,  1,   1,  100,  313, "NR_Sub6_Cat_B_100MHz_1_Cell_313"),
257                     (0,  1,   1,  100,  314, "NR_Sub6_Cat_B_100MHz_1_Cell_314"),
258                     (0,  1,   1,  100,  315, "NR_Sub6_Cat_B_100MHz_1_Cell_315"),
259                     (0,  1,   1,  100,  316, "NR_Sub6_Cat_B_100MHz_1_Cell_316"),
260                     (0,  1,   1,  100,  612, "NR_Sub6_Cat_B_100MHz_1_Cell_612_sc"),
261
262 ]
263
264 V_test_cases_B_mtu_1500 = [
265                     (0,  1,   1,  100,  501, "NR_Sub6_Cat_B_100MHz_1_Cell_501"),
266                     (0,  1,   1,  100,  502, "NR_Sub6_Cat_B_100MHz_1_Cell_502"),
267                     (0,  1,   1,  100,  503, "NR_Sub6_Cat_B_100MHz_1_Cell_503"),
268                     (0,  1,   1,  100,  504, "NR_Sub6_Cat_B_100MHz_1_Cell_504"),
269                     (0,  1,   1,  100,  505, "NR_Sub6_Cat_B_100MHz_1_Cell_505"),
270                     (0,  1,   1,  100,  506, "NR_Sub6_Cat_B_100MHz_1_Cell_506"),
271                     (0,  1,   1,  100,  802, "NR_Sub6_Cat_B_100MHz_1_Cell_802_sc"),
272 ]
273
274 V_test_cases_B_mtu_1500_2xUL = [
275                     (0,  1,   1,  100,  511, "NR_Sub6_Cat_B_100MHz_1_Cell_511"),
276                     (0,  1,   1,  100,  512, "NR_Sub6_Cat_B_100MHz_1_Cell_512"),
277                     (0,  1,   1,  100,  513, "NR_Sub6_Cat_B_100MHz_1_Cell_513"),
278                     (0,  1,   1,  100,  514, "NR_Sub6_Cat_B_100MHz_1_Cell_514"),
279                     (0,  1,   1,  100,  515, "NR_Sub6_Cat_B_100MHz_1_Cell_515"),
280                     (0,  1,   1,  100,  516, "NR_Sub6_Cat_B_100MHz_1_Cell_516"),
281                     (0,  1,   1,  100,  812, "NR_Sub6_Cat_B_100MHz_1_Cell_812_sc"),
282 ]
283
284 V_test_cases_B_3Cells = [
285                     (0,  1,   1,  100,  3301, "NR_Sub6_Cat_B_100MHz_1_Cell_3301"),
286                     (0,  1,   1,  100,  3311, "NR_Sub6_Cat_B_100MHz_1_Cell_3311")
287 ]
288
289 V_test_cases_B_3Cells_mtu_1500 = [
290                     (0,  1,   1,  100,  3501, "NR_Sub6_Cat_B_100MHz_1_Cell_3501"),
291                     (0,  1,   1,  100,  3511, "NR_Sub6_Cat_B_100MHz_1_Cell_3511")
292 ]
293
294
295 J_test_cases_B_4Cells = [
296                     (0,  1,   1,  100,  1421, "NR_Sub6_Cat_B_100MHz_1_Cell_DL4UL2"),
297                     (0,  1,   1,  100,  4424, "NR_Sub6_Cat_B_100MHz_4_Cell_DL4UL2")
298 ]
299
300 J_test_cases_B_4Cells_ext = [
301                     (0,  1,   1,  100,  1421, "NR_Sub6_Cat_B_100MHz_1_Cell_DL4UL2"),
302                     (0,  1,   1,  100,  2422, "NR_Sub6_Cat_B_100MHz_2_Cell_DL4UL2"),
303                     (0,  1,   1,  100,  3423, "NR_Sub6_Cat_B_100MHz_3_Cell_DL4UL2"),
304                     (0,  1,   1,  100,  4424, "NR_Sub6_Cat_B_100MHz_4_Cell_DL4UL2")
305 ]
306
307 Ext1_test_cases_B_4Cells = [
308                     (0,  1,   1,  100,  142, "NR_Sub6_Cat_B_100MHz_ext1_1_Cell_DL4UL2"),
309                     (0,  1,   1,  100,  242, "NR_Sub6_Cat_B_100MHz_ext1_2_Cell_DL4UL2"),
310                     (0,  1,   1,  100,  342, "NR_Sub6_Cat_B_100MHz_ext1_3_Cell_DL4UL2"),
311                     (0,  1,   1,  100,  442, "NR_Sub6_Cat_B_100MHz_ext1_4_Cell_DL4UL2")
312 ]
313
314 all_test_cases = []
315
316 #reduced duration test cycle
317 all_test_cases_short = NR_test_cases_A + LTE_test_cases_A + j_test_cases_A + LTE_test_cases_B + NR_test_cases_B + V_test_cases_B + V_test_cases_B_2xUL + J_test_cases_B_4Cells
318
319 all_test_cases_long = NR_test_cases_A_ext + LTE_test_cases_A + j_test_cases_A_ext + DSS_test_cases_A  + LTE_test_cases_B_ext + NR_test_cases_B_ext + V_test_cases_B_ext + V_test_cases_B_2xUL_ext + J_test_cases_B_4Cells_ext + Ext1_test_cases_B_4Cells
320
321 dic_dir      = dict({0:'DL', 1:'UL'})
322 dic_xu       = dict({0:'o-du', 1:'o-ru'})
323 dic_ran_tech = dict({0:'5g_nr', 1:'lte', 2:'dss'})
324
325 def init_logger(console_level, logfile_level):
326     """Initializes console and logfile logger with given logging levels"""
327     # File logger
328     logging.basicConfig(filename="runtests.log",
329                         filemode='w',
330                         format="%(asctime)s: %(levelname)s: %(message)s",
331                         level=logfile_level)
332     # Console logger
333     logger = logging.getLogger()
334     handler = logging.StreamHandler()
335     handler.setLevel(console_level)
336     formatter = logging.Formatter("%(levelname)s: %(message)s")
337     handler.setFormatter(formatter)
338     logger.addHandler(handler)
339
340 def parse_args(args):
341     """Configures parser and parses command line configuration"""
342     # Parser configuration
343     parser = argparse.ArgumentParser(description="Run test cases: category numerology bandwidth test_num")
344
345     parser.add_argument("--rem_o_ru_host", type=str, default="", help="remote host to run O-RU", metavar="root@10.10.10.1", dest="rem_o_ru_host")
346     parser.add_argument("--ran", type=int, default=0, help="Radio Access Technology 0 (5G NR) , 1 (LTE) or 2 DSS (5G NR and LTE)", metavar="ran", dest="rantech")
347     parser.add_argument("--cat", type=int, default=0, help="Category: 0 (A) or 1 (B)", metavar="cat", dest="category")
348     parser.add_argument("--mu", type=int, default=0, help="numerology [0,1,3]", metavar="num", dest="numerology")
349     parser.add_argument("--bw",  type=int, default=20, help="bandwidth [5,10,20,100]", metavar="bw", dest="bandwidth")
350     parser.add_argument("--testcase", type=int, default=0, help="test case number", metavar="testcase", dest="testcase")
351     parser.add_argument("--verbose", type=int, default=0, help="enable verbose output", metavar="verbose", dest="verbose")
352
353
354     # Parse arguments
355     options = parser.parse_args(args)
356     #parser.print_help()
357     logging.info("Options: rem_o_ru_host=%s ran=%d category=%d num=%d bw=%d testcase=%d",
358                   options.rem_o_ru_host, options.rantech, options.category, options.numerology, options.bandwidth, options.testcase)
359     return options
360
361 def is_comment(s):
362     """ function to check if a line
363          starts with some character.
364          Here # for comment
365     """
366     # return true if a line starts with #
367     return s.startswith('#')
368
369 class GetOutOfLoops( Exception ):
370     pass
371
372 def get_re_map(nRB, direction):
373     prb_map        = []
374     PrbElemContent = []
375     if direction == 0:
376         #DL
377         if 'nPrbElemDl' in globals():
378             nPrbElm = nPrbElemDl
379             for i in range(0, nPrbElm):
380                 elm = str('PrbElemDl'+str(i))
381                 #print(elm)
382                 if elm in globals():
383                     PrbElemContent.insert(i,list(globals()[elm]))
384                     xRBStart = PrbElemContent[i][0]
385                     xRBSize  = PrbElemContent[i][1]
386                     #print(PrbElemContent,"RBStart: ", xRBStart, "RBSize: ",xRBSize, list(range(xRBStart, xRBStart + xRBSize)))
387                     prb_map = prb_map + list(range(xRBStart*12, xRBStart*12 + xRBSize*12))
388         else:
389             nPrbElm = 0
390
391     elif direction == 1:
392         #UL
393         if 'nPrbElemUl' in globals():
394             nPrbElm = nPrbElemUl
395             for i in range(0, nPrbElm):
396                 elm = str('PrbElemUl'+str(i))
397                 #print(elm)
398                 if (elm in globals()):
399                     PrbElemContent.insert(i,list(globals()[elm]))
400                     xRBStart = PrbElemContent[i][0]
401                     xRBSize  = PrbElemContent[i][1]
402                     #print(PrbElemContent,"RBStart: ", xRBStart, "RBSize: ",xRBSize, list(range(xRBStart, xRBStart + xRBSize)))
403                     prb_map = prb_map + list(range(xRBStart*12, xRBStart*12 + xRBSize*12))
404         else:
405             nPrbElm = 0
406
407     elif direction == 2:
408         #UL
409         if 'nPrbElemSrs' in globals():
410             nPrbElm = nPrbElemSrs
411             for i in range(0, nPrbElm):
412                 elm = str('PrbElemSrs'+str(i))
413                 #print(elm)
414                 if (elm in globals()):
415                     PrbElemContent.insert(i,list(globals()[elm]))
416                     xRBStart = PrbElemContent[i][0]
417                     xRBSize  = PrbElemContent[i][1]
418                     #print(PrbElemContent,"RBStart: ", xRBStart, "RBSize: ",xRBSize, list(range(xRBStart, xRBStart + xRBSize)))
419                     prb_map = prb_map + list(range(xRBStart*12, xRBStart*12 + xRBSize*12))
420         else:
421             nPrbElm = 0
422
423     if nPrbElm == 0 :
424         prb_map = list(range(0, nRB*12))
425
426     return prb_map
427
428 def get_bfw_map(direction):
429     bfw_map        = []
430     bfwElemContent = []
431     if direction == 0:
432         #DL
433         if 'nPrbElemDl' in globals():
434             nPrbElm = nPrbElemDl
435             numsetBFW_total = 0
436             for i in range(0, nPrbElm):
437                 elm = str('ExtBfwDl'+str(i))
438                 #print(elm)
439                 if elm in globals():
440                     bfwElemContent.insert(i,list(globals()[elm]))
441                     numBundPrb  = bfwElemContent[i][0]
442                     numsetBFW   = bfwElemContent[i][1]
443                     bfw_map = bfw_map + list(range(antElmTRx*numsetBFW_total, antElmTRx*numsetBFW_total + numsetBFW*antElmTRx))
444                     numsetBFW_total += numsetBFW
445         else:
446             nPrbElm = 0
447     if nPrbElm == 0 :
448         bfw_map = list(range(0, (nPrbElm-1)*numsetBFW*antElmTRx))
449
450     return bfw_map, numsetBFW_total
451
452 def check_for_string_present_in_file(file_name, search_string):
453     res = 1
454     with open(file_name, 'r') as read_obj:
455         for line in read_obj:
456              if search_string in line:
457                  read_obj.close()
458                  res = 0
459                  return res
460     read_obj.close()
461     return res
462
463 def check_owdm_test_results(xran_path, o_xu_id):
464     res = 0
465     file_owd_oru = xran_path+"/app/logs/"+"o-ru"+str(o_xu_id)+"-owd_results.txt"
466     file_owd_odu = xran_path+"/app/logs/"+"o-du"+str(o_xu_id)+"-owd_results.txt"
467     print("file_owd_oru :", file_owd_oru)
468     print("file_owd_odu :", file_owd_odu)
469     res = check_for_string_present_in_file(file_owd_oru, 'passed')
470     res = res or check_for_string_present_in_file(file_owd_odu, 'passed')
471     
472     return res
473
474 def compare_results(o_xu_id, rantech, cat, mu, bw, tcase, xran_path, test_cfg, direction):
475     res = 0
476     re_map = []
477     if rantech==2:
478         if mu == 0:
479             nDlRB = nLteNumRbsPerSymF1[mu][nRChBwOptions.get(str(nDLBandwidth))]
480             nUlRB = nLteNumRbsPerSymF1[mu][nRChBwOptions.get(str(nULBandwidth))]
481         else:
482             print("Incorrect arguments\n")
483             res = -1
484             return res
485     elif rantech==1:
486         if mu == 0:
487             nDlRB = nLteNumRbsPerSymF1[mu][nRChBwOptions.get(str(nDLBandwidth))]
488             nUlRB = nLteNumRbsPerSymF1[mu][nRChBwOptions.get(str(nULBandwidth))]
489         else:
490             print("Incorrect arguments\n")
491             res = -1
492             return res
493     elif rantech==0:
494         if mu < 3:
495             nDlRB = nNumRbsPerSymF1[mu][nRChBwOptions.get(str(nDLBandwidth))]
496             nUlRB = nNumRbsPerSymF1[mu][nRChBwOptions.get(str(nULBandwidth))]
497         elif (mu >=2) & (mu <= 3):
498             nDlRB = nNumRbsPerSymF2[mu - 2][nRChBwOptions_mu2and3.get(str(nDLBandwidth))]
499             nUlRB = nNumRbsPerSymF2[mu - 2][nRChBwOptions_mu2and3.get(str(nULBandwidth))]
500             print(nDlRB, nUlRB)
501         else:
502             print("Incorrect arguments\n")
503             res = -1
504             return res
505
506     if 'compression' in globals():
507         comp = compression
508     else:
509         comp = 0
510
511     if 'srsEnable' in globals():
512         srs_enb = srsEnable
513     else:
514         srs_enb = 0
515
516     if 'rachEnable' in globals():
517         rach = rachEnable
518     else:
519         rach = 0
520
521     if 'extType' in globals():
522         ext_type = extType
523     else:
524         ext_type = 0
525
526     print("O-RU {} compare results: {} [compression {}]\n".format(o_xu_id, dic_dir.get(direction), comp))
527
528     #if cat == 1:
529     #    print("WARNING: Skip checking IQs and BF Weights for CAT B for now\n")
530     #    return res
531
532     #get slot config
533     if nFrameDuplexType == 1:
534         SlotConfig = []
535         for i in range(nTddPeriod):
536             if i == 0:
537                 SlotConfig.insert(i, sSlotConfig0)
538             elif i == 1:
539                 SlotConfig.insert(i, sSlotConfig1)
540             elif i == 2:
541                 SlotConfig.insert(i, sSlotConfig2)
542             elif i == 3:
543                 SlotConfig.insert(i, sSlotConfig3)
544             elif i == 4:
545                 SlotConfig.insert(i, sSlotConfig4)
546             elif i == 5:
547                 SlotConfig.insert(i, sSlotConfig5)
548             elif i == 6:
549                 SlotConfig.insert(i, sSlotConfig6)
550             elif i == 7:
551                 SlotConfig.insert(i, sSlotConfig7)
552             elif i == 8:
553                 SlotConfig.insert(i, sSlotConfig8)
554             elif i == 9:
555                 SlotConfig.insert(i, sSlotConfig9)
556             else :
557                 raise Exception('i should not exceed nTddPeriod %d. The value of i was: {}'.format(nTddPeriod, i))
558         #print(SlotConfig, type(sSlotConfig0))
559
560     try:
561
562         if (direction == 1) & (cat == 1): #UL
563             flowId = ccNum*antNumUL
564         else:
565             flowId = ccNum*antNum
566
567         if direction == 0:
568             re_map = get_re_map(nDlRB, direction)
569         elif direction == 1:
570             re_map = get_re_map(nUlRB, direction)
571         else:
572             raise Exception('Direction is not supported %d'.format(direction))
573
574         for i in range(0, flowId):
575             #read ref and test files
576             tst = []
577             ref = []
578             if direction == 0:
579                 # DL
580                 nRB = nDlRB
581                 file_tst = xran_path+"/app/logs/"+"o-ru"+str(o_xu_id)+"-rx_log_ant"+str(i)+".txt"
582                 file_ref = xran_path+"/app/logs/"+"o-du"+str(o_xu_id)+"-play_ant"+str(i)+".txt"
583             elif direction == 1:
584                 # UL
585                 nRB = nUlRB
586                 file_tst = xran_path+"/app/logs/"+"o-du"+str(o_xu_id)+"-rx_log_ant"+str(i)+".txt"
587                 file_ref = xran_path+"/app/logs/"+"o-ru"+str(o_xu_id)+"-play_ant"+str(i)+".txt"
588             else:
589                 raise Exception('Direction is not supported %d'.format(direction))
590
591             print("test result   :", file_tst)
592             print("test reference:", file_ref)
593             if os.path.exists(file_tst):
594                 try:
595                     file_tst = open(file_tst, 'r')
596                 except OSError:
597                     print ("Could not open/read file:", file_tst)
598                     sys.exit()
599             else:
600                 print(file_tst, "doesn't exist")
601                 res = -1
602                 return res
603             if os.path.exists(file_ref):
604                 try:
605                     file_ref = open(file_ref, 'r')
606                 except OSError:
607                     print ("Could not open/read file:", file_ref)
608                     sys.exit()
609             else:
610                 print(file_tst, "doesn't exist")
611                 res = -1
612                 return res
613
614             tst = file_tst.readlines()
615             ref = file_ref.readlines()
616
617             print(len(tst))
618             print(len(ref))
619
620             file_tst.close()
621             file_ref.close()
622
623             print(numSlots)
624
625             #skip last slot for UL as we stop on PPS boundary (OTA) and all symbols might not be received by O-DU
626             for slot_idx in range(0, numSlots - (1*direction)):
627                 for sym_idx in range(0, 14):
628                     if nFrameDuplexType==1:
629                         #skip sym if TDD
630                         if direction == 0:
631                             #DL
632                             sym_dir = SlotConfig[slot_idx%nTddPeriod][sym_idx]
633                             if(sym_dir != 0):
634                                 continue
635                         elif direction == 1:
636                             #UL
637                             sym_dir = SlotConfig[slot_idx%nTddPeriod][sym_idx]
638                             if(sym_dir != 1):
639                                 continue
640
641                     #print("Check:","[",i,"]", slot_idx, sym_idx)
642                     for line_idx in re_map:
643                         offset = (slot_idx*nRB*12*14) + sym_idx*nRB*12 + line_idx
644                         try:
645                             line_tst = tst[offset].rstrip()
646                         except IndexError:
647                             res = -1
648                             print("FAIL:","IndexError on tst: ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx, len(tst))
649                             raise GetOutOfLoops
650                         try:
651                              line_ref = ref[offset].rstrip()
652                         except IndexError:
653                             res = -1
654                             print("FAIL:","IndexError on ref: ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx, len(ref))
655                             raise GetOutOfLoops
656
657                         if comp == 1:
658                             # discard LSB bits as BFP compression is not "bit exact"
659                             tst_i_value = int(line_tst.split(" ")[0]) & 0xFF80
660                             tst_q_value = int(line_tst.split(" ")[1]) & 0xFF80
661                             ref_i_value = int(line_ref.split(" ")[0]) & 0xFF80
662                             ref_q_value = int(line_ref.split(" ")[1]) & 0xFF80
663
664                             #print("check:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")
665                             if (tst_i_value != ref_i_value) or  (tst_q_value != ref_q_value) :
666                                 print("FAIL:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")
667                                 res = -1
668                                 raise GetOutOfLoops
669                         else:
670                             #if line_idx == 0:
671                                 #print("Check:", offset,"[",i,"]", slot_idx, sym_idx,":",line_tst, line_ref)
672                             if line_ref != line_tst:
673                                 print("FAIL:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst:", line_tst, "ref:", line_ref)
674                                 res = -1
675                                 raise GetOutOfLoops
676     except GetOutOfLoops:
677         return res
678
679     if (direction == 1) & (rach == 1) & 0: #UL
680         print("O-RU {} compare results: {} [compression {}]\n".format(o_xu_id, 'PRACH', comp))
681
682         #rach
683         try:
684             if mu == 3: #FR2
685                 re_map = range(0, 144)
686                 nRB = 12
687             elif nFrameDuplexType==0: #FR1 FDD
688                 if prachConfigIndex < 87:
689                     re_map = range(0, 840)
690                     nRB = 70
691                 else:
692                     re_map = range(0, 144)
693                     nRB = 12
694             else: #FR1 TDD
695                 if prachConfigIndex < 67:
696                     re_map = range(0, 144)
697                     nRB = 12
698                 else:
699                     re_map = range(0, 840)
700                     nRB = 70
701             if cat == 1:
702                 flowId = ccNum*antNumUL
703             else:
704                 flowId = ccNum*antNum
705
706             for i in range(0, flowId):
707                 #read ref and test files
708                 tst = []
709                 ref = []
710
711                 file_tst = xran_path+"/app/logs/"+"o-du"+str(o_xu_id)+"-prach_log_ant"+str(i)+".txt"
712                 file_ref = xran_path+"/app/logs/"+"o-ru"+str(o_xu_id)+"-play_prach_ant"+str(i)+".txt"
713                 print("test result   :", file_tst)
714                 print("test reference:", file_ref)
715                 if os.path.exists(file_tst):
716                     try:
717                         file_tst = open(file_tst, 'r')
718                     except OSError:
719                         print ("Could not open/read file:", file_tst)
720                         sys.exit()
721                 else:
722                     print(file_tst, "doesn't exist")
723                     res = -1
724                     return res
725                 if os.path.exists(file_ref):
726                     try:
727                         file_ref = open(file_ref, 'r')
728                     except OSError:
729                         print ("Could not open/read file:", file_ref)
730                         sys.exit()
731                 else:
732                     print(file_tst, "doesn't exist")
733                     res = -1
734                     return res
735
736                 tst = file_tst.readlines()
737                 ref = file_ref.readlines()
738
739                 print(len(tst))
740                 print(len(ref))
741
742                 file_tst.close()
743                 file_ref.close()
744
745                 print(numSlots)
746
747                 #skip last slot for UL as we stop on PPS boundary (OTA) and all symbols might not be received by O-DU
748                 for slot_idx in range(0, numSlots - (1*direction)):
749                 for sym_idx in range(0, 14):
750                     if nFrameDuplexType==1:
751                         #skip sym if TDD
752                         if direction == 0:
753                             #DL
754                             sym_dir = SlotConfig[slot_idx%nTddPeriod][sym_idx]
755                             if(sym_dir != 0):
756                                 continue
757                         elif direction == 1:
758                             #UL
759                             sym_dir = SlotConfig[slot_idx%nTddPeriod][sym_idx]
760                             if(sym_dir != 1):
761                                 continue
762
763                     #print("Check:","[",i,"]", slot_idx, sym_idx)
764                     for line_idx in re_map:
765                         offset = (slot_idx*nRB*12*14) + sym_idx*nRB*12 + line_idx
766                         try:
767                             line_tst = tst[offset].rstrip()
768                         except IndexError:
769                             res = -1
770                             print("FAIL:","IndexError on tst: ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx, len(tst))
771                             raise GetOutOfLoops
772                         try:
773                              line_ref = ref[offset].rstrip()
774                         except IndexError:
775                             res = -1
776                             print("FAIL:","IndexError on ref: ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx, len(ref))
777                             raise GetOutOfLoops
778
779                         if comp == 1:
780                             # discard LSB bits as BFP compression is not "bit exact"
781                             tst_i_value = int(line_tst.split(" ")[0]) & 0xFF80
782                             tst_q_value = int(line_tst.split(" ")[1]) & 0xFF80
783                             ref_i_value = int(line_ref.split(" ")[0]) & 0xFF80
784                             ref_q_value = int(line_ref.split(" ")[1]) & 0xFF80
785
786                             #print("check:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")
787                             if (tst_i_value != ref_i_value) or  (tst_q_value != ref_q_value) :
788                                 print("FAIL:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")
789                                 res = -1
790                                 raise GetOutOfLoops
791                         else:
792                             #if line_idx == 0:
793                                 #print("Check:", offset,"[",i,"]", slot_idx, sym_idx,":",line_tst, line_ref)
794                             if line_ref != line_tst:
795                                 print("FAIL:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst:", line_tst, "ref:", line_ref)
796                                 res = -1
797                                 raise GetOutOfLoops
798     except GetOutOfLoops:
799         return res
800
801     if ((cat == 1) and (direction == 0) and (ext_type == 1)): #Cat B, DL and Extension type = 1
802         try:
803             if (direction == 0) & (cat == 1): #DL
804                 flowId = ccNum*antNum
805             if direction == 0:
806                 bfw_map, numsetBFW_total = get_bfw_map(direction)
807             else:
808                 raise Exception('Direction is not supported %d'.format(direction))
809
810             for i in range(0, flowId):
811                 #read ref and test files
812                 tst = []
813                 ref = []
814                 if direction == 0:
815                     # DL
816                     file_tst = xran_path+"/app/logs/"+"o-ru"+str(o_xu_id)+"-dl_bfw_log_ue"+str(i)+".txt"
817                     file_ref = xran_path+"/app/logs/"+"o-du"+str(o_xu_id)+"-dl_bfw_ue"+str(i)+".txt"
818                 else:
819                     raise Exception('Direction is not supported %d'.format(direction))
820
821                 print("test result   :", file_tst)
822                 print("test reference:", file_ref)
823                 if os.path.exists(file_tst):
824                     try:
825                         file_tst = open(file_tst, 'r')
826                     except OSError:
827                         print ("Could not open/read file:", file_tst)
828                         sys.exit()
829                 else:
830                     print(file_tst, "doesn't exist")
831                     res = -1
832                     return res
833                 if os.path.exists(file_ref):
834                     try:
835                         file_ref = open(file_ref, 'r')
836                     except OSError:
837                         print ("Could not open/read file:", file_ref)
838                         sys.exit()
839                 else:
840                     print(file_tst, "doesn't exist")
841                     res = -1
842                     return res
843
844                 tst = file_tst.readlines()
845                 ref = file_ref.readlines()
846
847                 print(len(tst))
848                 print(len(ref))
849
850                 file_tst.close()
851                 file_ref.close()
852
853                 print(numSlots)
854
855                 for slot_idx in range(0, numSlots):
856                     skip_tti = 1
857                     if nFrameDuplexType==1:
858                         #skip tti if UL slot
859                         if direction == 0:
860                             #DL
861                             for sym_idx in range(0,14):
862                                 sym_dir = SlotConfig[slot_idx%nTddPeriod][sym_idx]
863                                 if(sym_dir == 0):
864                                     skip_tti = 0
865                                     break
866                             if(skip_tti == 1):
867                                 continue
868                     for line_idx in bfw_map:
869                         offset = slot_idx * (nDlRB*antElmTRx) #(slot_idx*numsetBFW_total*antElmTRx) + line_idx
870                         try:
871                             line_tst = tst[offset].rstrip()
872                         except IndexError:
873                             res = -1
874                             print("FAIL:","IndexError on tst: ant:[",i,"]:",offset, slot_idx, line_idx, len(tst))
875                             raise GetOutOfLoops
876                         try:
877                             line_ref = ref[offset].rstrip()
878                         except IndexError:
879                             res = -1
880                             print("FAIL:","IndexError on ref: ant:[",i,"]:",offset, slot_idx, line_idx, len(ref))
881                             raise GetOutOfLoops
882
883                         if comp == 1:
884                             # discard LSB bits as BFP compression is not "bit exact"
885                             tst_i_value = int(line_tst.split(" ")[0]) & 0xFF80
886                             tst_q_value = int(line_tst.split(" ")[1]) & 0xFF80
887                             ref_i_value = int(line_ref.split(" ")[0]) & 0xFF80
888                             ref_q_value = int(line_ref.split(" ")[1]) & 0xFF80
889
890                             tst_i_act = int(line_tst.split(" ")[0])
891                             tst_q_act = int(line_tst.split(" ")[1])
892                             ref_i_act = int(line_ref.split(" ")[0])
893                             ref_q_act = int(line_ref.split(" ")[1])
894
895                             #print("check:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")
896                             if (tst_i_value != ref_i_value) or  (tst_q_value != ref_q_value) :
897                                 print("868 Actual:","bfw:[",i,"]:",offset, slot_idx, line_idx,":","tst: ", tst_i_act, " ", tst_q_act, " " , "ref: ", ref_i_act, " ", ref_q_act, " ")
898                                 print("FAIL:","bfw:[",i,"]:",offset, slot_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")
899                                 res = -1
900                                 raise GetOutOfLoops
901                         else:
902                             #if line_idx == 0:
903                                 #print("Check:", offset,"[",i,"]", slot_idx, sym_idx,":",line_tst, line_ref)
904                             if line_ref != line_tst:
905                                 print("876 Actual:","bfw:[",i,"]:",offset, slot_idx, line_idx,":","tst: ", tst_i_act, " ", tst_q_act, " " , "ref: ", ref_i_act, " ", ref_q_act, " ")
906                                 print("FAIL:","bfw:[",i,"]:",offset, slot_idx, line_idx,":","tst:", line_tst, "ref:", line_ref)
907                                 res = -1
908                                 raise GetOutOfLoops
909         except GetOutOfLoops:
910             res = 0 # Not treating it as a test case fail criteria for now
911             # return res
912
913         try:
914             if (direction == 0) & (cat == 1): #DL
915                 flowId = ccNum*antNumUL
916             if direction == 0:
917                 bfw_map, numsetBFW_total = get_bfw_map(direction)
918             else:
919                 raise Exception('Direction is not supported %d'.format(direction))
920
921             for i in range(0, flowId):
922                 #read ref and test files
923                 tst = []
924                 ref = []
925                 if direction == 0:
926                     # DL
927                     file_tst = xran_path+"/app/logs/"+"o-ru"+str(o_xu_id)+"-ul_bfw_log_ue"+str(i)+".txt"
928                     file_ref = xran_path+"/app/logs/"+"o-du"+str(o_xu_id)+"-ul_bfw_ue"+str(i)+".txt"
929                 else:
930                     raise Exception('Direction is not supported %d'.format(direction))
931
932                 print("test result   :", file_tst)
933                 print("test reference:", file_ref)
934                 if os.path.exists(file_tst):
935                     try:
936                         file_tst = open(file_tst, 'r')
937                     except OSError:
938                         print ("Could not open/read file:", file_tst)
939                         sys.exit()
940                 else:
941                     print(file_tst, "doesn't exist")
942                     res = -1
943                     return res
944                 if os.path.exists(file_ref):
945                     try:
946                         file_ref = open(file_ref, 'r')
947                     except OSError:
948                         print ("Could not open/read file:", file_ref)
949                         sys.exit()
950                 else:
951                     print(file_tst, "doesn't exist")
952                     res = -1
953                     return res
954
955                 tst = file_tst.readlines()
956                 ref = file_ref.readlines()
957
958                 print(len(tst))
959                 print(len(ref))
960
961                 file_tst.close()
962                 file_ref.close()
963
964                 print(numSlots)
965
966                 for slot_idx in range(0, numSlots):
967                     skip_tti = 1
968                     if nFrameDuplexType==1:
969                         #skip tti if UL slot
970                         if direction == 0:
971                             #DL
972                             for sym_idx in range(0,14):
973                                 sym_dir = SlotConfig[slot_idx%nTddPeriod][sym_idx]
974                                 if(sym_dir == 1):
975                                     skip_tti = 0
976                                     break
977                             if(skip_tti == 1):
978                                 continue
979                     for line_idx in bfw_map:
980                         offset = slot_idx * (nUlRB*antElmTRx) #(slot_idx*numsetBFW_total*antElmTRx) + line_idx
981                         try:
982                             line_tst = tst[offset].rstrip()
983                         except IndexError:
984                             res = -1
985                             print("FAIL:","IndexError on tst: ant:[",i,"]:",offset, slot_idx, line_idx, len(tst))
986                             raise GetOutOfLoops
987                         try:
988                             line_ref = ref[offset].rstrip()
989                         except IndexError:
990                             res = -1
991                             print("FAIL:","IndexError on ref: ant:[",i,"]:",offset, slot_idx, line_idx, len(ref))
992                             raise GetOutOfLoops
993
994                         if comp == 1:
995                             # discard LSB bits as BFP compression is not "bit exact"
996                             tst_i_value = int(line_tst.split(" ")[0]) & 0xFF80
997                             tst_q_value = int(line_tst.split(" ")[1]) & 0xFF80
998                             ref_i_value = int(line_ref.split(" ")[0]) & 0xFF80
999                             ref_q_value = int(line_ref.split(" ")[1]) & 0xFF80
1000
1001                             #print("check:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")
1002                             if (tst_i_value != ref_i_value) or  (tst_q_value != ref_q_value) :
1003                                 print("FAIL:","bfw:[",i,"]:",offset, slot_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")
1004                                 res = -1
1005                                 raise GetOutOfLoops
1006                         else:
1007                             #if line_idx == 0:
1008                                 #print("Check:", offset,"[",i,"]", slot_idx, sym_idx,":",line_tst, line_ref)
1009                             if line_ref != line_tst:
1010                                 print("FAIL:","bfw:[",i,"]:",offset, slot_idx, line_idx,":","tst:", line_tst, "ref:", line_ref)
1011                                 res = -1
1012                                 raise GetOutOfLoops
1013         except GetOutOfLoops:
1014             res = 0        # Not treating it as a test case fail criteria for now
1015             # return res
1016
1017     if (direction == 0) | (cat == 0) | (srs_enb == 0): #DL or Cat A
1018         #done
1019     return res
1020
1021     print("O-RU {} compare results: {} [compression {}]\n".format(o_xu_id, 'SRS', comp))
1022
1023     #srs
1024     PrbElemContent = []
1025     if 'nPrbElemSrs' in globals():
1026         for i in range(0, nPrbElemSrs):
1027             elm = str('PrbElemSrs'+str(i))
1028             #print(elm)
1029             if (elm in globals()):
1030                 PrbElemContent.insert(i,list(globals()[elm]))
1031                 symbMask = 1 << PrbElemContent[i][2]    # start symbol
1032                 print(symbMask)
1033                 #print(PrbElemContent,"RBStart: ", xRBStart, "RBSize: ",xRBSize, list(range(xRBStart, xRBStart + xRBSize)))
1034     else:
1035         print("Cannot find SRS PRB map!")
1036         symbMask = 0
1037
1038     re_map = get_re_map(nUlRB, 2)
1039     try:
1040         flowId = ccNum*antElmTRx
1041         for i in range(0, flowId):
1042             #read ref and test files
1043             tst = []
1044             ref = []
1045
1046             if direction == 1:
1047                 # UL
1048                 nRB = nUlRB
1049                 file_tst = xran_path+"/app/logs/"+"o-du"+str(o_xu_id)+"-srs_log_ant"+str(i)+".txt"
1050                 file_ref = xran_path+"/app/logs/"+"o-ru"+str(o_xu_id)+"-play_srs_ant"+str(i)+".txt"
1051             else:
1052                 raise Exception('Direction is not supported %d'.format(direction))
1053
1054             print("test result   :", file_tst)
1055             print("test reference:", file_ref)
1056             if os.path.exists(file_tst):
1057                 try:
1058                     file_tst = open(file_tst, 'r')
1059                 except OSError:
1060                     print ("Could not open/read file:", file_tst)
1061                     sys.exit()
1062             else:
1063                 print(file_tst, "doesn't exist")
1064                 res = -1
1065                 return res
1066             if os.path.exists(file_ref):
1067                 try:
1068                     file_ref = open(file_ref, 'r')
1069                 except OSError:
1070                     print ("Could not open/read file:", file_ref)
1071                     sys.exit()
1072             else:
1073                 print(file_tst, "doesn't exist")
1074                 res = -1
1075                 return res
1076
1077             tst = file_tst.readlines()
1078             ref = file_ref.readlines()
1079
1080             print(len(tst))
1081             print(len(ref))
1082
1083             file_tst.close()
1084             file_ref.close()
1085
1086             print(numSlots)
1087
1088             for slot_idx in range(0, numSlots - (1*direction)):
1089                 for sym_idx in range(0, 14):
1090                     if symbMask & (1 << sym_idx) and slot_idx%nTddPeriod == srsSlot:
1091                         print("SRS check sym ", slot_idx,  sym_idx)
1092                         if nFrameDuplexType==1:
1093                             #skip sym if TDD
1094                             if direction == 0:
1095                                 #DL
1096                                 sym_dir = SlotConfig[slot_idx%nTddPeriod][sym_idx]
1097                                 if(sym_dir != 0):
1098                                     continue
1099                             elif direction == 1:
1100                                 #UL
1101                                 sym_dir = SlotConfig[slot_idx%nTddPeriod][sym_idx]
1102                                 # ignore if DL symbol for now
1103                                 #if(sym_dir != 1):
1104                                 #    continue
1105
1106                         print("Check:","[",i,"]", slot_idx, sym_idx)
1107                         for line_idx in re_map:
1108                             offset = (slot_idx*nRB*12*14) + sym_idx*nRB*12 + line_idx
1109                             try:
1110                                 line_tst = tst[offset].rstrip()
1111                             except IndexError:
1112                                 res = -1
1113                                 print("FAIL:","IndexError on tst: ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx, len(tst))
1114                                 raise GetOutOfLoops
1115                             try:
1116                                 line_ref = ref[offset].rstrip()
1117                             except IndexError:
1118                                 res = -1
1119                                 print("FAIL:","IndexError on ref: ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx, len(ref))
1120                                 raise GetOutOfLoops
1121
1122                             if comp == 1:
1123                                 # discard LSB bits as BFP compression is not "bit exact"
1124                                 tst_i_value = int(line_tst.split(" ")[0]) & 0xFF80
1125                                 tst_q_value = int(line_tst.split(" ")[1]) & 0xFF80
1126                                 ref_i_value = int(line_ref.split(" ")[0]) & 0xFF80
1127                                 ref_q_value = int(line_ref.split(" ")[1]) & 0xFF80
1128
1129                                 #print("check:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")
1130                                 if (tst_i_value != ref_i_value) or  (tst_q_value != ref_q_value) :
1131                                     print("FAIL:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst: ", tst_i_value, " ", tst_q_value, " " , "ref: ", ref_i_value, " ", ref_q_value, " ")
1132                                     res = -1
1133                                     raise GetOutOfLoops
1134                             else:
1135                                 #if line_idx == 0:
1136                                     #print("Check:", offset,"[",i,"]", slot_idx, sym_idx,":",line_tst, line_ref)
1137                                 if line_ref != line_tst:
1138                                     print("FAIL:","ant:[",i,"]:",offset, slot_idx, sym_idx, line_idx,":","tst:", line_tst, "ref:", line_ref)
1139                                     res = -1
1140                                     raise GetOutOfLoops
1141     except GetOutOfLoops:
1142         #don't threat SRS as error for now
1143         res = 0
1144         return res
1145
1146
1147     return res
1148
1149 def parse_usecase_cfg(rantech, cat, mu, bw, tcase, xran_path, usecase_cfg):
1150     #parse config files
1151     logging.info("parse config files %s\n", usecase_cfg[0])
1152     lineList = list()
1153     sep = '#'
1154     with open(usecase_cfg[0],'r') as fh:
1155         for curline in dropwhile(is_comment, fh):
1156             my_line = curline.rstrip().split(sep, 1)[0].strip()
1157             if my_line:
1158                 lineList.append(my_line)
1159
1160     global_env = {}
1161     local_env  = {}
1162
1163     for line in lineList:
1164         exe_line = line.replace(":", ",0x")
1165         if exe_line.find("../") > 0 :
1166             exe_line = exe_line.replace('../', "'../")
1167             exe_line = exe_line+"'"
1168         elif exe_line.find("./") > 0 :
1169             exe_line = exe_line.replace('./', "'./")
1170             exe_line = exe_line+"'"
1171
1172         code = compile(str(exe_line), '<string>', 'exec')
1173         exec (code, global_env, local_env)
1174
1175     for k, v in local_env.items():
1176         globals()[k] = v
1177         print(k, v)
1178
1179     print("Number of O-RU:", oXuNum)
1180
1181     return local_env
1182
1183 def parse_dat_file(rantech, cat, mu, bw, tcase, xran_path, test_cfg):
1184     #parse config files
1185     logging.info("parse config files %s\n", test_cfg[0])
1186     lineList = list()
1187
1188     sep = '#'
1189     with open(test_cfg[0],'r') as fh:
1190         for curline in dropwhile(is_comment, fh):
1191             my_line = curline.rstrip().split(sep, 1)[0].strip()
1192             if my_line:
1193                 lineList.append(my_line)
1194     global_env = {}
1195     local_env = {}
1196
1197     for line in lineList:
1198         exe_line = line.replace(":", ",0x")
1199         if exe_line.find("../") > 0 :
1200             exe_line = exe_line.replace('../', "'../")
1201             exe_line = exe_line+"'"
1202         elif exe_line.find("./") > 0 :
1203             exe_line = exe_line.replace('./', "'./")
1204             exe_line = exe_line+"'"
1205
1206         code = compile(str(exe_line), '<string>', 'exec')
1207         exec (code, global_env, local_env)
1208
1209     for k, v in local_env.items():
1210         globals()[k] = v
1211         print(k, v)
1212
1213     return local_env
1214
1215 def del_dat_file_vars(local_env):
1216
1217     for k, v in local_env.items():
1218         del globals()[k]
1219
1220     return 0
1221
1222 def make_copy_mlog(rantech, cat, mu, bw, tcase, xran_path):
1223     res = 0
1224
1225     src_bin = xran_path+"/app/mlog-o-du.bin"
1226     src_csv = xran_path+"/app/mlog-o-du_hist.csv"
1227     dst_bin = xran_path+"/app/mlog-o-du-ran"+str(rantech)+"-cat"+str(cat)+"-mu"+str(mu)+"-bw"+str(bw)+"-tcase"+str(tcase)+".bin"
1228     dst_csv = xran_path+"/app/mlog-o-du_hist-ran"+str(rantech)+"-cat"+str(cat)+"-mu"+str(mu)+"-bw"+str(bw)+"-tcase"+str(tcase)+".csv"
1229
1230     try:
1231         d_bin  = shutil.copyfile(src_bin, dst_bin)
1232         d_csv  = shutil.copyfile(src_csv, dst_csv)
1233     except IOError:
1234         logging.info("O-DU MLog is not present\n")
1235         res = 1
1236         return res
1237     else:
1238         logging.info("O-DU Mlog was copied\n")
1239
1240
1241     print("Destination path:", d_bin)
1242     print("Destination path:", d_csv)
1243
1244     d_bin  = shutil.copyfile(src_bin, dst_bin)
1245     d_csv  = shutil.copyfile(src_csv, dst_csv)
1246
1247     src_bin = xran_path+"/app/mlog-o-ru.bin"
1248     src_csv = xran_path+"/app/mlog-o-ru_hist.csv"
1249     dst_bin = xran_path+"/app/mlog-o-ru-ran"+str(rantech)+"-cat"+str(cat)+"-mu"+str(mu)+"-bw"+str(bw)+"-tcase"+str(tcase)+".bin"
1250     dst_csv = xran_path+"/app/mlog-o-ru_hist-ran"+str(rantech)+"-cat"+str(cat)+"-mu"+str(mu)+"-bw"+str(bw)+"-tcase"+str(tcase)+".csv"
1251
1252     d_bin  = shutil.copyfile(src_bin, dst_bin)
1253     d_csv  = shutil.copyfile(src_csv, dst_csv)
1254
1255     try:
1256         d_bin  = shutil.copyfile(src_bin, dst_bin)
1257         d_csv  = shutil.copyfile(src_csv, dst_csv)
1258     except IOError:
1259         logging.info("O-RU MLog is not present\n")
1260         res = 1
1261         return res
1262     else:
1263         logging.info("O-RU Mlog was copied\n")
1264
1265     return res
1266
1267
1268 def run_tcase(rem_o_ru_host, rantech, cat, mu, bw, tcase, verbose, xran_path, vf_addr_o_xu):
1269
1270     if rantech == 2: #LTE and #5G NR
1271         if cat == 0:
1272             test_config =xran_path+"/app/usecase/dss/mu{0:d}_{1:d}mhz".format(mu, bw)
1273         else:
1274             print("Incorrect cat argument\n")
1275             return -1
1276     elif rantech == 1: #LTE
1277         if cat == 1:
1278             test_config =xran_path+"/app/usecase/lte_b/mu{0:d}_{1:d}mhz".format(mu, bw)
1279         elif cat == 0 :
1280             test_config =xran_path+"/app/usecase/lte_a/mu{0:d}_{1:d}mhz".format(mu, bw)
1281         else:
1282             print("Incorrect cat arguments\n")
1283             return -1
1284     elif rantech == 0: #5G NR
1285         if cat == 1:
1286             test_config =xran_path+"/app/usecase/cat_b/mu{0:d}_{1:d}mhz".format(mu, bw)
1287         elif cat == 0 :
1288             test_config =xran_path+"/app/usecase/cat_a/mu{0:d}_{1:d}mhz".format(mu, bw)
1289         else:
1290             print("Incorrect cat argument\n")
1291             return -1
1292     else:
1293         print("Incorrect rantech argument\n")
1294         return -1
1295
1296     if(tcase > 0) :
1297         test_config = test_config+"/"+str(tcase)
1298
1299     app = [xran_path+"/app/build/sample-app", xran_path+"/app/build-oru/sample-app-ru"]
1300
1301     logging.debug("run: %s %s", app, test_config)
1302     logging.debug("Started script: master.py, XRAN path %s", xran_path)
1303
1304     test_cfg = []
1305     global oXuOwdmEnabled
1306     oXuOwdmEnabled = 0 #Default is owdm measurements are disabled
1307     REM_O_RU_HOST=rem_o_ru_host
1308
1309     if(os.system('lscpu | grep -q -i AVX512IFMA') == 0):
1310         cpu = 'icx'
1311     else:
1312         cpu = 'csx'
1313
1314     #O-DU
1315     if REM_O_RU_HOST == "":
1316
1317         if (cpu == 'icx'):
1318             if ((os.path.isfile(test_config+"/usecase_du_icx.cfg")) & (os.path.isfile(test_config+"/usecase_ru_icx.cfg"))):
1319                 test_cfg.append(test_config+"/usecase_du_icx.cfg")
1320                 test_cfg.append(test_config+"/usecase_ru_icx.cfg")
1321             else:
1322                 test_cfg.append(test_config+"/usecase_du.cfg")
1323                 test_cfg.append(test_config+"/usecase_ru.cfg")
1324         else: #(csx_cpu)
1325             if ((os.path.isfile(test_config+"/usecase_du_csx.cfg")) & (os.path.isfile(test_config+"/usecase_ru_csx.cfg"))):
1326                 test_cfg.append(test_config+"/usecase_du_csx.cfg")
1327                 test_cfg.append(test_config+"/usecase_ru_csx.cfg")
1328             else:
1329                 test_cfg.append(test_config+"/usecase_du.cfg")
1330                 test_cfg.append(test_config+"/usecase_ru.cfg")
1331     else: # O-RU remote always CSX-SP
1332         if (cpu == 'icx'):
1333             if (os.path.isfile(test_config+"/usecase_du_icx.cfg")):
1334                 test_cfg.append(test_config+"/usecase_du_icx.cfg")
1335             else:
1336                 test_cfg.append(test_config+"/usecase_du.cfg")
1337             if (os.path.isfile(test_config+"/usecase_ru_csx.cfg")):
1338                 test_cfg.append(test_config+"/usecase_ru_csx.cfg")
1339             else:
1340                 test_cfg.append(test_config+"/usecase_ru.cfg")
1341         else: #(csx_cpu)
1342             if ((os.path.isfile(test_config+"/usecase_du_csx.cfg")) & (os.path.isfile(test_config+"/usecase_ru_csx.cfg"))):
1343                 test_cfg.append(test_config+"/usecase_du_csx.cfg")
1344                 test_cfg.append(test_config+"/usecase_ru_csx.cfg")
1345             else:
1346     test_cfg.append(test_config+"/usecase_du.cfg")
1347     test_cfg.append(test_config+"/usecase_ru.cfg")
1348
1349     usecase_dirname = os.path.dirname(os.path.realpath(test_cfg[0]))
1350     print(usecase_dirname)
1351
1352     wd = os.getcwd()
1353     os.chdir(xran_path+"/app/")
1354
1355     processes     = []
1356     logfile_xu    = []
1357     log_file_name = []
1358     timer         = []
1359
1360     os.system('pkill -9 "sample-app"')
1361     os.system('pkill -9 "sample-app-ru"')
1362     os.system('rm -rf ./logs')
1363
1364     usecase_cfg = parse_usecase_cfg(rantech, cat, mu, bw, tcase, xran_path, test_cfg)
1365
1366
1367     for i in range(2):
1368
1369         log_file_name.append("sampleapp_log_{}_{}_cat_{}_mu{}_{}mhz_tst_{}.log".format(dic_ran_tech.get(rantech), dic_xu.get(i),cat, mu, bw, tcase))
1370         with open(log_file_name[i], "w") as f:
1371             run_cmd = [app[i], "--usecasefile", test_cfg[i], "--num_eth_vfs", "8", "--vf_addr_o_xu_a", vf_addr_o_xu[i][0], "--vf_addr_o_xu_b", vf_addr_o_xu[i][1],"--vf_addr_o_xu_c", vf_addr_o_xu[i][2],"--vf_addr_o_xu_d", vf_addr_o_xu[i][3]]
1372             #, stdout=f, stderr=f
1373             if (verbose==1):
1374                 if i == 0 or REM_O_RU_HOST == "":
1375                 p = subprocess.Popen(run_cmd)
1376             else:
1377                     CMD = ' '.join([str(elem) for elem in run_cmd])
1378                     ssh = ["ssh", "%s" % REM_O_RU_HOST, "cd " + xran_path + "/app"+"; hostname; pwd; pkill -9 sample-app; rm -rf ./logs; ulimit -c unlimited; echo 1 > /proc/sys/kernel/core_uses_pid; " + CMD]
1379                     print(ssh)
1380                     print("my_cmd: ", ' '.join([str(elem) for elem in ssh]))
1381                     p = subprocess.Popen(ssh, shell=False)
1382             else:
1383                 if i == 0 or REM_O_RU_HOST == "":
1384                 p = subprocess.Popen(run_cmd, stdout=f, stderr=f)
1385                 else :
1386                     CMD = ' '.join([str(elem) for elem in run_cmd])
1387                     ssh = ["ssh", "%s" % REM_O_RU_HOST, "cd " + xran_path + "/app"+"; hostname; pwd; pkill -9 sample-app; rm -rf ./logs; ulimit -c unlimited; echo 1 > /proc/sys/kernel/core_uses_pid; " + CMD]
1388                     p = subprocess.Popen(ssh, shell=False, stdout=f, stderr=f)
1389                     #stdout=subprocess.PIPE, stderr=subprocess.PIPE)
1390
1391             t = Timer(timeout_sec, p.kill)
1392             t.start()
1393             timer.append(t)
1394             logfile_xu.insert(i, f)
1395         processes.append((p, logfile_xu[i]))
1396
1397     logging.info("Running O-DU and O-RU see output in:\n    O-DU: %s\n    O-RU: %s\n", xran_path+"/app/"+logfile_xu[0].name, xran_path+"/app/"+logfile_xu[1].name)
1398     #while (gmtime().tm_sec % 30) <> 0:
1399         #pass
1400     print(strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()))
1401     i = 0
1402     for p, f in processes:
1403         try:
1404         p.communicate()[0]
1405         p.wait()
1406         except (KeyboardInterrupt, SystemExit):
1407             for i in range(2):
1408                 timer[i].cancel()
1409                 timer[i].cancel()
1410             for pp, ff in processes:
1411                 pp.send_signal(signal.SIGINT)
1412                 pp.wait()
1413             raise
1414
1415         if p.returncode != 0:
1416             print("Application {} failed p.returncode:{}".format(dic_xu.get(i), p.returncode))
1417             print("FAIL")
1418             #logging.info("FAIL\n")
1419             #logging.shutdown()
1420             #sys.exit(p.returncode)
1421         i += 1
1422         f.close()
1423
1424     for i in range(2):
1425         timer[i].cancel()
1426         timer[i].cancel()
1427
1428     logging.info("O-DU and O-RU are done\n")
1429
1430     if REM_O_RU_HOST:
1431         sys_cmd = "scp -r "+REM_O_RU_HOST+":"+ xran_path+"/app/logs/*.txt "+ xran_path+"/app/logs/"
1432         print(sys_cmd)
1433         os.system(sys_cmd)
1434         sys_cmd = "scp -r "+REM_O_RU_HOST+":"+ xran_path+"/app/mlog-o-ru* "+ xran_path+"/app/"
1435         print(sys_cmd)
1436         os.system(sys_cmd)
1437
1438     make_copy_mlog(rantech, cat, mu, bw, tcase, xran_path)
1439     #oXuNum check only O-RU 0 for now
1440     if 'oXuOwdmEnabled==1' in globals():
1441          OwdmTest=1
1442     else:
1443          OwdmTest=0
1444
1445     for o_xu_id in range(0, oXuNum):
1446         o_xu_test_cfg = []
1447         if o_xu_id == 0:
1448             o_xu_test_cfg.append(usecase_dirname+"/"+oXuCfgFile0)
1449         elif o_xu_id == 1:
1450             o_xu_test_cfg.append(usecase_dirname+"/"+oXuCfgFile1)
1451         elif o_xu_id == 2:
1452             o_xu_test_cfg.append(usecase_dirname+"/"+oXuCfgFile2)
1453         elif o_xu_id == 3:
1454             o_xu_test_cfg.append(usecase_dirname+"/"+oXuCfgFile3)
1455
1456         logging.info("O-RU %d parse config files %s\n", o_xu_id, o_xu_test_cfg)
1457
1458         usecase_cfg_per_o_ru = parse_dat_file(rantech, cat, mu, bw, tcase, xran_path, o_xu_test_cfg)
1459
1460         res = compare_results(o_xu_id,rantech, cat, mu, bw, tcase, xran_path, o_xu_test_cfg, 0)
1461         if OwdmTest == 1:
1462         # overwrite PASS/FAIL in res if the owd tests have failed
1463              res1 = check_owdm_test_results(xran_path, o_xu_id)
1464              print("res1 :", res1)
1465              if res1 !=0 :
1466                   res = -1     
1467     if res != 0:
1468         os.chdir(wd)
1469         print("FAIL")
1470             del_dat_file_vars(usecase_cfg_per_o_ru)
1471         return res
1472
1473         res = compare_results(o_xu_id, rantech, cat, mu, bw, tcase, xran_path, o_xu_test_cfg, 1)
1474     if res != 0:
1475         os.chdir(wd)
1476         print("FAIL")
1477             del_dat_file_vars(usecase_cfg_per_o_ru)
1478         return res
1479
1480     os.chdir(wd)
1481     print("PASS")
1482
1483         del_dat_file_vars(usecase_cfg_per_o_ru)
1484
1485     return res
1486
1487 def main():
1488     test_results = []
1489     run_total = 0
1490     test_fail_cnt = 0
1491     test_pass_cnt = 0
1492     cat   = 0
1493     mu    = 0
1494     bw    = 0
1495     tcase = 0
1496     tcase_description = "n/a"
1497
1498     """Processes input files to produce IACA files"""
1499     # Find path to XRAN
1500     if os.getenv("XRAN_DIR") is not None:
1501         xran_path = os.getenv("XRAN_DIR")
1502     else:
1503         print("please set 'export XRAN_DIR' in the OS")
1504         return -1
1505
1506     # Set up logging with given level (DEBUG, INFO, ERROR) for console end logfile
1507     init_logger(logging.INFO, logging.DEBUG)
1508     host_name =  socket.gethostname()
1509     logging.info("host: %s Started script: master.py from XRAN path %s",host_name, xran_path)
1510
1511     options = parse_args(sys.argv[1:])
1512     rem_o_ru_host = options.rem_o_ru_host
1513
1514     all_test_cases  = all_test_cases_long
1515     if host_name == "sc12-xran-sub6":
1516         if rem_o_ru_host:
1517             vf_addr_o_xu = vf_addr_o_xu_sc12_cvl
1518         else:
1519             vf_addr_o_xu = vf_addr_o_xu_sc12
1520     elif host_name == "csl-npg-scs1-30":
1521         vf_addr_o_xu = vf_addr_o_xu_scs1_30
1522     elif host_name == "npg-scs1-repo.la.intel.com":
1523         vf_addr_o_xu = vf_addr_o_xu_scs1_repo
1524     elif host_name == "icelake-scs1-1":
1525         vf_addr_o_xu = vf_addr_o_xu_icelake_scs1_1
1526     elif host_name == "icx-npg-scs1-coyote4":
1527         vf_addr_o_xu = vf_addr_o_xu_icx_npg_scs1_coyote4
1528     elif host_name == "csl-npg-scs1-35":
1529         vf_addr_o_xu = vf_addr_o_xu_scs1_35
1530     elif host_name == "csl-npg-scs1-33":
1531         vf_addr_o_xu = vf_addr_o_xu_csl_npg_scs1_33
1532     elif host_name == "skx-5gnr-sd6":
1533         vf_addr_o_xu = vf_addr_o_xu_skx_5gnr_sd6
1534     else:
1535         vf_addr_o_xu = vf_addr_o_xu_jenkins
1536         all_test_cases  = all_test_cases_short
1537
1538     print(vf_addr_o_xu[0][0],vf_addr_o_xu[0][1],vf_addr_o_xu[0][2],vf_addr_o_xu[0][3])
1539     print(vf_addr_o_xu[1][0],vf_addr_o_xu[1][1],vf_addr_o_xu[1][2],vf_addr_o_xu[1][3])
1540
1541     # Parse input arguments
1542     if len(sys.argv) == 1 or (len(sys.argv) == 3 and rem_o_ru_host):
1543         run_total = len(all_test_cases)
1544         print(run_total)
1545         print("Run All test cases {}\n".format(run_total))
1546     else:
1547         rantech = options.rantech
1548         cat     = options.category
1549         mu      = options.numerology
1550         bw      = options.bandwidth
1551         tcase   = options.testcase
1552         verbose = options.verbose
1553
1554         print(rem_o_ru_host)
1555
1556     if (run_total):
1557         for test_run_ix in range(0, run_total):
1558             rantech = all_test_cases[test_run_ix][0]
1559             cat     = all_test_cases[test_run_ix][1]
1560             mu      = all_test_cases[test_run_ix][2]
1561             bw      = all_test_cases[test_run_ix][3]
1562             tcase   = all_test_cases[test_run_ix][4]
1563             tcase_description = all_test_cases[test_run_ix][5]
1564             verbose = 0
1565
1566             logging.info("Test# %d out of %d [PASS %d FAIL %d]: ran %d cat %d mu %d bw %d test case %d [%s]\n",test_run_ix, run_total, test_pass_cnt, test_fail_cnt, rantech, cat, mu, bw, tcase, tcase_description)
1567             res = run_tcase(rem_o_ru_host, rantech, cat, mu, bw, tcase, verbose,  xran_path, vf_addr_o_xu)
1568             if (res != 0):
1569                 test_fail_cnt += 1
1570                 test_results.append((rantech, cat, mu, bw, tcase,'FAIL', tcase_description))
1571                 continue
1572
1573             test_pass_cnt += 1
1574             test_results.append((rantech, cat, mu, bw, tcase,'PASS', tcase_description))
1575     else:
1576         res = run_tcase(rem_o_ru_host, rantech, cat, mu, bw, tcase, verbose, xran_path, vf_addr_o_xu)
1577         if (res != 0):
1578             test_results.append((rantech, cat, mu, bw, tcase,'FAIL'))
1579         else:
1580         test_results.append((rantech, cat, mu, bw, tcase,'PASS'))
1581
1582         with open('testresult.txt', 'w') as reshandle:
1583             json.dump(test_results, reshandle)
1584
1585     return res
1586
1587 if __name__ == '__main__':
1588     print("Python version")
1589     print (sys.version)
1590     print("Version info.")
1591     print (sys.version_info)
1592     if (sys.version_info[0] < 3):
1593         raise Exception ("Must be Python 3")
1594     START_TIME = datetime.now()
1595     res = main()
1596     END_TIME = datetime.now()
1597     logging.debug("Start time: %s, end time: %s", START_TIME, END_TIME)
1598     logging.info("Execution time: %s", END_TIME - START_TIME)
1599     logging.shutdown()
1600     sys.exit(res)