/
gnb_appconfig_cli11_schema.cpp
2613 lines (2373 loc) · 123 KB
/
gnb_appconfig_cli11_schema.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
*
* Copyright 2021-2024 Software Radio Systems Limited
*
* This file is part of srsRAN.
*
* srsRAN is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsRAN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "gnb_appconfig_cli11_schema.h"
#include "gnb_appconfig.h"
#include "srsran/ran/du_types.h"
#include "srsran/ran/duplex_mode.h"
#include "srsran/ran/pdsch/pdsch_mcs.h"
#include "srsran/support/cli11_utils.h"
#include "srsran/support/config_parsers.h"
#include "srsran/support/error_handling.h"
#include "CLI/CLI11.hpp"
using namespace srsran;
template <typename Integer>
static expected<Integer, std::string> parse_int(const std::string& value)
{
try {
return std::stoi(value);
} catch (const std::invalid_argument& e) {
return {e.what()};
} catch (const std::out_of_range& e) {
return {e.what()};
}
}
static void configure_cli11_log_args(CLI::App& app, log_appconfig& log_params)
{
auto level_check = [](const std::string& value) -> std::string {
if (value == "info" || value == "debug" || value == "warning" || value == "error") {
return {};
}
return "Log level value not supported. Accepted values [info,debug,warning,error]";
};
app.add_option("--filename", log_params.filename, "Log file output path")->capture_default_str();
app.add_option(
"--all_level", log_params.all_level, "Default log level for PHY, MAC, RLC, PDCP, RRC, SDAP, NGAP and GTPU")
->capture_default_str()
->check(level_check);
app.add_option("--phy_level", log_params.phy_level, "PHY log level")->capture_default_str()->check(level_check);
app.add_option("--mac_level", log_params.mac_level, "MAC log level")->capture_default_str()->check(level_check);
app.add_option("--rlc_level", log_params.rlc_level, "RLC log level")->capture_default_str()->check(level_check);
app.add_option("--pdcp_level", log_params.pdcp_level, "PDCP log level")->capture_default_str()->check(level_check);
app.add_option("--rrc_level", log_params.rrc_level, "RRC log level")->capture_default_str()->check(level_check);
app.add_option("--sdap_level", log_params.sdap_level, "SDAP log level")->capture_default_str()->check(level_check);
app.add_option("--ngap_level", log_params.ngap_level, "NGAP log level")->capture_default_str()->check(level_check);
app.add_option("--gtpu_level", log_params.gtpu_level, "GTPU log level")->capture_default_str()->check(level_check);
app.add_option("--radio_level", log_params.radio_level, "Radio log level")->capture_default_str()->check(level_check);
app.add_option("--fapi_level", log_params.fapi_level, "FAPI log level")->capture_default_str()->check(level_check);
app.add_option("--ofh_level", log_params.ofh_level, "Open Fronthaul log level")
->capture_default_str()
->check(level_check);
app.add_option("--f1ap_level", log_params.f1ap_level, "F1AP log level")->capture_default_str()->check(level_check);
app.add_option("--f1u_level", log_params.f1u_level, "F1-U log level")->capture_default_str()->check(level_check);
app.add_option("--du_level", log_params.du_level, "Log level for the DU")->capture_default_str()->check(level_check);
app.add_option("--cu_level", log_params.cu_level, "Log level for the CU")->capture_default_str()->check(level_check);
app.add_option("--sec_level", log_params.sec_level, "Security functions log level")
->capture_default_str()
->check(level_check);
app.add_option("--lib_level", log_params.lib_level, "Generic log level")->capture_default_str()->check(level_check);
app.add_option(
"--hex_max_size", log_params.hex_max_size, "Maximum number of bytes to print in hex (zero for no hex dumps)")
->capture_default_str()
->check(CLI::Range(0, 1024));
app.add_option("--broadcast_enabled",
log_params.broadcast_enabled,
"Enable logging in the physical and MAC layer of broadcast messages and all PRACH opportunities")
->always_capture_default();
app.add_option("--phy_rx_symbols_filename",
log_params.phy_rx_symbols_filename,
"Set to a valid file path to print the received symbols.")
->always_capture_default();
app.add_option_function<std::string>(
"--phy_rx_symbols_port",
[&log_params](const std::string& value) {
if (value == "all") {
log_params.phy_rx_symbols_port = nullopt;
} else {
log_params.phy_rx_symbols_port = parse_int<unsigned>(value).value();
}
},
"Set to a valid receive port number to dump the IQ symbols from that port only, or set to \"all\" to dump the "
"IQ symbols from all UL receive ports. Only works if \"phy_rx_symbols_filename\" is set.")
->default_str("0")
->check(CLI::NonNegativeNumber | CLI::IsMember({"all"}));
app.add_option("--phy_rx_symbols_prach",
log_params.phy_rx_symbols_prach,
"Set to true to dump the IQ symbols from all the PRACH ports. Only works if "
"\"phy_rx_symbols_filename\" is set.")
->capture_default_str();
app.add_option("--tracing_filename", log_params.tracing_filename, "Set to a valid file path to enable tracing")
->always_capture_default();
// Post-parsing callback. This allows us to set the log level to "all" level, if no level is provided.
app.callback([&]() {
if (app.count("--phy_level") == 0) {
log_params.phy_level = log_params.all_level;
}
if (app.count("--mac_level") == 0) {
log_params.mac_level = log_params.all_level;
}
if (app.count("--rlc_level") == 0) {
log_params.rlc_level = log_params.all_level;
}
if (app.count("--f1ap_level") == 0) {
log_params.f1ap_level = log_params.all_level;
}
if (app.count("--pdcp_level") == 0) {
log_params.pdcp_level = log_params.all_level;
}
if (app.count("--rrc_level") == 0) {
log_params.rrc_level = log_params.all_level;
}
if (app.count("--sdap_level") == 0) {
log_params.sdap_level = log_params.all_level;
}
if (app.count("--ngap_level") == 0) {
log_params.ngap_level = log_params.all_level;
}
if (app.count("--gtpu_level") == 0) {
log_params.gtpu_level = log_params.all_level;
}
// Update the radio log level to all levels when radio level was not found and all level is not warning.
if (app.count("--radio_level") == 0 && log_params.all_level != "warning") {
log_params.radio_level = log_params.all_level;
}
if (app.count("--fapi_level") == 0) {
log_params.fapi_level = log_params.all_level;
}
if (app.count("--ofh_level") == 0) {
log_params.ofh_level = log_params.all_level;
}
if (app.count("--f1ap_level") == 0) {
log_params.f1ap_level = log_params.all_level;
}
if (app.count("--f1u_level") == 0) {
log_params.f1u_level = log_params.all_level;
}
if (app.count("--du_level") == 0) {
log_params.du_level = log_params.all_level;
}
if (app.count("--cu_level") == 0) {
log_params.cu_level = log_params.all_level;
}
if (app.count("--sec_level") == 0) {
log_params.sec_level = log_params.all_level;
}
if (app.count("--lib_level") == 0) {
log_params.lib_level = log_params.all_level;
}
});
}
static void configure_cli11_pcap_args(CLI::App& app, pcap_appconfig& pcap_params)
{
app.add_option("--ngap_filename", pcap_params.ngap.filename, "NGAP PCAP file output path")->capture_default_str();
app.add_option("--ngap_enable", pcap_params.ngap.enabled, "Enable NGAP packet capture")->always_capture_default();
app.add_option("--e1ap_filename", pcap_params.e1ap.filename, "E1AP PCAP file output path")->capture_default_str();
app.add_option("--e1ap_enable", pcap_params.e1ap.enabled, "Enable E1AP packet capture")->always_capture_default();
app.add_option("--f1ap_filename", pcap_params.f1ap.filename, "F1AP PCAP file output path")->capture_default_str();
app.add_option("--f1ap_enable", pcap_params.f1ap.enabled, "Enable F1AP packet capture")->always_capture_default();
app.add_option("--rlc_filename", pcap_params.rlc.filename, "RLC PCAP file output path")->capture_default_str();
app.add_option("--rlc_rb_type", pcap_params.rlc.rb_type, "RLC PCAP RB type (all, srb, drb)")->capture_default_str();
app.add_option("--rlc_enable", pcap_params.rlc.enabled, "Enable RLC packet capture")->always_capture_default();
app.add_option("--mac_filename", pcap_params.mac.filename, "MAC PCAP file output path")->capture_default_str();
app.add_option("--mac_type", pcap_params.mac.type, "MAC PCAP pcap type (dlt or udp)")->capture_default_str();
app.add_option("--mac_enable", pcap_params.mac.enabled, "Enable MAC packet capture")->always_capture_default();
app.add_option("--e2ap_filename", pcap_params.e2ap.filename, "E2AP PCAP file output path")->capture_default_str();
app.add_option("--e2ap_enable", pcap_params.e2ap.enabled, "Enable E2AP packet capture")->always_capture_default();
app.add_option("--gtpu_filename", pcap_params.gtpu.filename, "GTP-U PCAP file output path")->capture_default_str();
app.add_option("--gtpu_enable", pcap_params.gtpu.enabled, "Enable GTP-U packet capture")->always_capture_default();
}
static void configure_cli11_metrics_args(CLI::App& app, metrics_appconfig& metrics_params)
{
app.add_option("--rlc_report_period", metrics_params.rlc.report_period, "RLC metrics report period")
->capture_default_str();
app.add_option("--rlc_json_enable", metrics_params.rlc.json_enabled, "Enable RLC JSON metrics reporting")
->always_capture_default();
app.add_option("--pdcp_report_period", metrics_params.pdcp.report_period, "PDCP metrics report period")
->capture_default_str();
app.add_option("--cu_cp_statistics_report_period",
metrics_params.cu_cp_statistics_report_period,
"CU-CP statistics report period in seconds. Set this value to 0 to disable this feature")
->capture_default_str();
app.add_option("--cu_up_statistics_report_period",
metrics_params.cu_up_statistics_report_period,
"CU-UP statistics report period in seconds. Set this value to 0 to disable this feature")
->capture_default_str();
app.add_option("--enable_json_metrics", metrics_params.enable_json_metrics, "Enable JSON metrics reporting")
->always_capture_default();
app.add_option("--addr", metrics_params.addr, "Metrics address.")->capture_default_str()->check(CLI::ValidIPV4);
app.add_option("--port", metrics_params.port, "Metrics UDP port.")
->capture_default_str()
->check(CLI::Range(0, 65535));
app.add_option(
"--autostart_stdout_metrics", metrics_params.autostart_stdout_metrics, "Autostart stdout metrics reporting")
->capture_default_str();
app.add_option("--stdout_metrics_period",
metrics_params.stdout_metrics_period,
"DU statistics report period in milliseconds. This metrics sets the console output period.")
->capture_default_str();
}
static void configure_cli11_slicing_args(CLI::App& app, s_nssai_t& slice_params)
{
app.add_option("--sst", slice_params.sst, "Slice Service Type")->capture_default_str()->check(CLI::Range(0, 255));
app.add_option("--sd", slice_params.sd, "Service Differentiator")
->capture_default_str()
->check(CLI::Range(0, 0xffffff));
}
static void configure_cli11_amf_args(CLI::App& app, amf_appconfig& amf_params)
{
app.add_option("--addr", amf_params.ip_addr, "AMF IP address");
app.add_option("--port", amf_params.port, "AMF port")->capture_default_str()->check(CLI::Range(20000, 40000));
app.add_option("--bind_addr",
amf_params.bind_addr,
"Default local IP address interfaces bind to, unless a specific bind address is specified")
->check(CLI::ValidIPV4);
app.add_option("--n2_bind_addr", amf_params.n2_bind_addr, "Local IP address to bind for N2 interface")
->check(CLI::ValidIPV4);
app.add_option("--n3_bind_addr", amf_params.n3_bind_addr, "Local IP address to bind for N3 interface")
->check(CLI::ValidIPV4);
app.add_option("--n3_bind_interface", amf_params.n3_bind_interface, "Network device to bind for N3 interface")
->capture_default_str();
app.add_option("--n2_bind_interface", amf_params.n2_bind_interface, "Network device to bind for N2 interface")
->capture_default_str();
app.add_option("--sctp_rto_initial", amf_params.sctp_rto_initial, "SCTP initial RTO value");
app.add_option("--sctp_rto_min", amf_params.sctp_rto_min, "SCTP RTO min");
app.add_option("--sctp_rto_max", amf_params.sctp_rto_max, "SCTP RTO max");
app.add_option("--sctp_init_max_attempts", amf_params.sctp_init_max_attempts, "SCTP init max attempts");
app.add_option("--sctp_max_init_timeo", amf_params.sctp_max_init_timeo, "SCTP max init timeout");
app.add_option("--sctp_nodelay",
amf_params.sctp_nodelay,
"Send SCTP messages as soon as possible without any Nagle-like algorithm");
app.add_option("--udp_max_rx_msgs", amf_params.udp_rx_max_msgs, "Maximum amount of messages RX in a single syscall");
app.add_option("--no_core", amf_params.no_core, "Allow gNB to run without a core");
}
static void configure_cli11_e2_args(CLI::App& app, e2_appconfig& e2_params)
{
app.add_option("--enable_du_e2", e2_params.enable_du_e2, "Enable DU E2 agent");
app.add_option("--addr", e2_params.ip_addr, "RIC IP address");
app.add_option("--port", e2_params.port, "RIC port")->capture_default_str()->check(CLI::Range(20000, 40000));
app.add_option("--bind_addr", e2_params.bind_addr, "Local IP address to bind for RIC connection")
->check(CLI::ValidIPV4);
app.add_option("--sctp_rto_initial", e2_params.sctp_rto_initial, "SCTP initial RTO value");
app.add_option("--sctp_rto_min", e2_params.sctp_rto_min, "SCTP RTO min");
app.add_option("--sctp_rto_max", e2_params.sctp_rto_max, "SCTP RTO max");
app.add_option("--sctp_init_max_attempts", e2_params.sctp_init_max_attempts, "SCTP init max attempts");
app.add_option("--sctp_max_init_timeo", e2_params.sctp_max_init_timeo, "SCTP max init timeout");
app.add_option("--e2sm_kpm_enabled", e2_params.e2sm_kpm_enabled, "Enable KPM service module");
app.add_option("--e2sm_rc_enabled", e2_params.e2sm_rc_enabled, "Enable RC service module");
}
static void configure_cli11_ncell_args(CLI::App& app, cu_cp_neighbor_cell_appconfig_item& config)
{
app.add_option("--nr_cell_id", config.nr_cell_id, "Neighbor cell id");
app.add_option(
"--report_configs", config.report_cfg_ids, "Report configurations to configure for this neighbor cell");
}
static void configure_cli11_cells_args(CLI::App& app, cu_cp_cell_appconfig_item& config)
{
app.add_option("--nr_cell_id", config.nr_cell_id, "Cell id to be configured");
app.add_option("--rat", config.rat, "RAT of this neighbor cell")->capture_default_str();
app.add_option("--periodic_report_cfg_id",
config.periodic_report_cfg_id,
"Periodical report configuration for the serving cell")
->check(CLI::Range(1, 64));
;
add_auto_enum_option(app, "--band", config.band, "NR frequency band");
app.add_option("--gnb_id", config.gnb_id, "gNodeB identifier");
app.add_option("--ssb_arfcn", config.ssb_arfcn, "SSB ARFCN");
app.add_option("--ssb_scs", config.ssb_scs, "SSB subcarrier spacing")->check(CLI::IsMember({15, 30, 60, 120, 240}));
app.add_option("--ssb_period", config.ssb_period, "SSB period in ms");
app.add_option("--ssb_offset", config.ssb_offset, "SSB offset");
app.add_option("--ssb_duration", config.ssb_duration, "SSB duration");
// report configuration parameters.
app.add_option_function<std::vector<std::string>>(
"--ncells",
[&config](const std::vector<std::string>& values) {
config.ncells.resize(values.size());
for (unsigned i = 0, e = values.size(); i != e; ++i) {
CLI::App subapp("CU-CP neighbor cell list");
subapp.config_formatter(create_yaml_config_parser());
subapp.allow_config_extras(CLI::config_extras_mode::error);
configure_cli11_ncell_args(subapp, config.ncells[i]);
std::istringstream ss(values[i]);
subapp.parse_from_stream(ss);
}
},
"Sets the list of neighbor cells known to the CU-CP");
}
static void configure_cli11_report_args(CLI::App& app, cu_cp_report_appconfig& report_params)
{
app.add_option("--report_cfg_id", report_params.report_cfg_id, "Report configuration id to be configured")
->check(CLI::Range(1, 64));
app.add_option("--report_type", report_params.report_type, "Type of the report configuration")
->check(CLI::IsMember({"periodical", "event_triggered"}));
app.add_option("--report_interval_ms", report_params.report_interval_ms, "Report interval in ms");
app.add_option("--a3_report_type", report_params.a3_report_type, "A3 report type");
app.add_option("--a3_offset_db", report_params.a3_offset_db, "A3 offset in dB used for measurement report trigger");
app.add_option(
"--a3_hysteresis_db", report_params.a3_hysteresis_db, "A3 hysteresis in dB used for measurement report trigger");
app.add_option("--a3_time_to_trigger_ms",
report_params.a3_time_to_trigger_ms,
"Time in ms during which A3 condition must be met before measurement report trigger");
}
static void configure_cli11_mobility_args(CLI::App& app, mobility_appconfig& config)
{
app.add_option("--trigger_handover_from_measurements",
config.trigger_handover_from_measurements,
"Whether to start HO if neighbor cells become stronger")
->capture_default_str();
// Cell map parameters.
app.add_option_function<std::vector<std::string>>(
"--cells",
[&config](const std::vector<std::string>& values) {
config.cells.resize(values.size());
for (unsigned i = 0, e = values.size(); i != e; ++i) {
CLI::App subapp("CU-CP cell list");
subapp.config_formatter(create_yaml_config_parser());
subapp.allow_config_extras(CLI::config_extras_mode::error);
configure_cli11_cells_args(subapp, config.cells[i]);
std::istringstream ss(values[i]);
subapp.parse_from_stream(ss);
}
},
"Sets the list of cells known to the CU-CP");
// report configuration parameters.
app.add_option_function<std::vector<std::string>>(
"--report_configs",
[&config](const std::vector<std::string>& values) {
config.report_configs.resize(values.size());
for (unsigned i = 0, e = values.size(); i != e; ++i) {
CLI::App subapp("CU-CP measurement report config list");
subapp.config_formatter(create_yaml_config_parser());
subapp.allow_config_extras(CLI::config_extras_mode::error);
configure_cli11_report_args(subapp, config.report_configs[i]);
std::istringstream ss(values[i]);
subapp.parse_from_stream(ss);
}
},
"Sets report configurations");
}
static void configure_cli11_rrc_args(CLI::App& app, rrc_appconfig& config)
{
app.add_option("--force_reestablishment_fallback",
config.force_reestablishment_fallback,
"Force RRC re-establishment fallback to RRC setup")
->capture_default_str();
app.add_option(
"--rrc_procedure_timeout_ms",
config.rrc_procedure_timeout_ms,
"Timeout in ms used for RRC message exchange with UE. It needs to suit the expected communication delay and "
"account for potential retransmissions UE processing delays, SR delays, etc.")
->capture_default_str();
}
static void configure_cli11_security_args(CLI::App& app, security_appconfig& config)
{
auto sec_check = [](const std::string& value) -> std::string {
if (value == "required" || value == "preferred" || value == "not_needed") {
return {};
}
return "Security indication value not supported. Accepted values [required,preferred,not_needed]";
};
app.add_option("--integrity", config.integrity_protection, "Default integrity protection indication for DRBs")
->capture_default_str()
->check(sec_check);
app.add_option("--confidentiality",
config.confidentiality_protection,
"Default confidentiality protection indication for DRBs")
->capture_default_str()
->check(sec_check);
app.add_option("--nea_pref_list",
config.nea_preference_list,
"Ordered preference list for the selection of encryption algorithm (NEA) (default: NEA0, NEA2, NEA1)");
app.add_option("--nia_pref_list",
config.nia_preference_list,
"Ordered preference list for the selection of encryption algorithm (NIA) (default: NIA2, NIA1)")
->capture_default_str();
}
static void configure_cli11_cu_cp_args(CLI::App& app, cu_cp_appconfig& cu_cp_params)
{
app.add_option(
"--max_nof_dus", cu_cp_params.max_nof_dus, "Maximum number of DU connections that the CU-CP may accept");
app.add_option(
"--max_nof_cu_ups", cu_cp_params.max_nof_cu_ups, "Maximum number of CU-UP connections that the CU-CP may accept");
app.add_option("--inactivity_timer", cu_cp_params.inactivity_timer, "UE/PDU Session/DRB inactivity timer in seconds")
->capture_default_str()
->check(CLI::Range(1, 7200));
app.add_option("--pdu_session_setup_timeout",
cu_cp_params.pdu_session_setup_timeout,
"Timeout for the setup of a PDU session after an InitialUeMessage was sent to the core, in "
"seconds. The timeout must be larger than T310. If the value is reached, the UE will be released")
->capture_default_str();
CLI::App* mobility_subcmd = app.add_subcommand("mobility", "Mobility configuration");
configure_cli11_mobility_args(*mobility_subcmd, cu_cp_params.mobility_config);
CLI::App* rrc_subcmd = app.add_subcommand("rrc", "RRC specific configuration");
configure_cli11_rrc_args(*rrc_subcmd, cu_cp_params.rrc_config);
CLI::App* security_subcmd = app.add_subcommand("security", "Security configuration");
configure_cli11_security_args(*security_subcmd, cu_cp_params.security_config);
}
static void configure_cli11_cu_up_args(CLI::App& app, cu_up_appconfig& cu_up_params)
{
app.add_option("--gtpu_queue_size", cu_up_params.gtpu_queue_size, "GTP-U queue size, in PDUs")->capture_default_str();
app.add_option("--gtpu_reordering_timer",
cu_up_params.gtpu_reordering_timer_ms,
"GTP-U RX reordering timer (in milliseconds)")
->capture_default_str();
app.add_option("--warn_on_drop",
cu_up_params.warn_on_drop,
"Log a warning for dropped packets in GTP-U and PDCP due to full queues")
->capture_default_str();
}
static void configure_cli11_expert_phy_args(CLI::App& app, expert_upper_phy_appconfig& expert_phy_params)
{
auto pusch_sinr_method_check = [](const std::string& value) -> std::string {
if ((value == "channel_estimator") || (value == "post_equalization") || (value == "evm")) {
return {};
}
return "Invalid PUSCH SINR calculation method. Accepted values [channel_estimator,post_equalization,evm]";
};
app.add_option("--max_proc_delay",
expert_phy_params.max_processing_delay_slots,
"Maximum allowed DL processing delay in slots.")
->capture_default_str()
->check(CLI::Range(1, 30));
app.add_option("--pusch_dec_max_iterations",
expert_phy_params.pusch_decoder_max_iterations,
"Maximum number of PUSCH LDPC decoder iterations")
->capture_default_str()
->check(CLI::Number);
app.add_option("--pusch_dec_enable_early_stop",
expert_phy_params.pusch_decoder_early_stop,
"Enables PUSCH LDPC decoder early stop")
->capture_default_str();
app.add_option("--pusch_sinr_calc_method",
expert_phy_params.pusch_sinr_calc_method,
"PUSCH SINR calculation method: channel_estimator, post_equalization and evm.")
->capture_default_str()
->check(pusch_sinr_method_check);
app.add_option("--max_request_headroom_slots",
expert_phy_params.nof_slots_request_headroom,
"Maximum request headroom size in slots.")
->capture_default_str()
->check(CLI::Range(0, 3));
}
static void configure_cli11_pdcch_common_args(CLI::App& app, pdcch_common_appconfig& common_params)
{
app.add_option("--coreset0_index", common_params.coreset0_index, "CORESET#0 index")
->capture_default_str()
->check(CLI::Range(0, 15));
app.add_option("--ss1_n_candidates",
common_params.ss1_n_candidates,
"Number of PDCCH candidates per aggregation level for SearchSpace#1. Default: {0, 0, 1, 0, 0}")
->capture_default_str()
->check(CLI::IsMember({0, 1, 2, 3, 4, 5, 6, 8}));
app.add_option("--ss0_index", common_params.ss0_index, "SearchSpace#0 index")
->capture_default_str()
->check(CLI::Range(0, 15));
// NOTE: The CORESET duration of 3 symbols is only permitted if the dmrs-typeA-Position information element has
// been set to 3. And, we use only pos2 or pos1.
app.add_option("--max_coreset0_duration",
common_params.max_coreset0_duration,
"Maximum CORESET#0 duration in OFDM symbols to consider when deriving CORESET#0 index")
->capture_default_str()
->check(CLI::Range(1, 2));
}
static void configure_cli11_pdcch_dedicated_args(CLI::App& app, pdcch_dedicated_appconfig& ded_params)
{
app.add_option("--coreset1_rb_start",
ded_params.coreset1_rb_start,
"Starting Common Resource Block (CRB) number for CORESET 1 relative to CRB 0. Default: CRB0")
->capture_default_str()
->check(CLI::Range(0, 275));
app.add_option("--coreset1_l_crb",
ded_params.coreset1_l_crb,
"Length of CORESET 1 in number of CRBs. Default: Across entire BW of cell")
->capture_default_str()
->check(CLI::Range(0, 275));
// NOTE: The CORESET duration of 3 symbols is only permitted if the dmrs-typeA-Position information element has been
// set to 3. And, we use only pos2 or pos1.
app.add_option("--coreset1_duration",
ded_params.coreset1_duration,
"Duration of CORESET 1 in number of OFDM symbols. Default: Max(2, Nof. CORESET#0 symbols)")
->capture_default_str()
->check(CLI::Range(1, 2));
app.add_option("--ss2_n_candidates",
ded_params.ss2_n_candidates,
"Number of PDCCH candidates per aggregation level for SearchSpace#2. Default: {0, 0, 0, 0, 0} i.e. "
"auto-compute nof. candidates")
->capture_default_str()
->check(CLI::IsMember({0, 1, 2, 3, 4, 5, 6, 8}));
app.add_option("--dci_format_0_1_and_1_1",
ded_params.dci_format_0_1_and_1_1,
"DCI format to use in UE dedicated SearchSpace#2")
->capture_default_str();
app.add_option_function<std::string>(
"--ss2_type",
[&ded_params](const std::string& value) {
ded_params.ss2_type = (value == "common") ? search_space_configuration::type_t::common
: search_space_configuration::type_t::ue_dedicated;
},
"SearchSpace type for UE dedicated SearchSpace#2")
->default_str("ue_dedicated")
->check(CLI::IsMember({"common", "ue_dedicated"}, CLI::ignore_case));
}
static void configure_cli11_pdcch_args(CLI::App& app, pdcch_appconfig& pdcch_params)
{
// PDCCH Common configuration.
CLI::App* pdcch_common_subcmd = app.add_subcommand("common", "PDCCH Common configuration parameters");
configure_cli11_pdcch_common_args(*pdcch_common_subcmd, pdcch_params.common);
// PDCCH Dedicated configuration.
CLI::App* pdcch_dedicated_subcmd = app.add_subcommand("dedicated", "PDCCH Dedicated configuration parameters");
configure_cli11_pdcch_dedicated_args(*pdcch_dedicated_subcmd, pdcch_params.dedicated);
}
static void configure_cli11_pdsch_args(CLI::App& app, pdsch_appconfig& pdsch_params)
{
app.add_option("--min_ue_mcs", pdsch_params.min_ue_mcs, "Minimum UE MCS")
->capture_default_str()
->check(CLI::Range(0, 28));
app.add_option("--max_ue_mcs", pdsch_params.max_ue_mcs, "Maximum UE MCS")
->capture_default_str()
->check(CLI::Range(0, 28));
app.add_option("--fixed_rar_mcs", pdsch_params.fixed_rar_mcs, "Fixed RAR MCS")
->capture_default_str()
->check(CLI::Range(0, 28));
app.add_option("--fixed_sib1_mcs", pdsch_params.fixed_sib1_mcs, "Fixed SIB1 MCS")
->capture_default_str()
->check(CLI::Range(0, 28));
app.add_option("--nof_harqs", pdsch_params.nof_harqs, "Number of DL HARQ processes")
->capture_default_str()
->check(CLI::IsMember({2, 4, 6, 8, 10, 12, 16}));
app.add_option("--max_nof_harq_retxs",
pdsch_params.max_nof_harq_retxs,
"Maximum number of times a DL HARQ can be retransmitted, before it gets discarded")
->capture_default_str()
->check(CLI::Range(0, 4));
app.add_option("--max_consecutive_kos",
pdsch_params.max_consecutive_kos,
"Maximum number of HARQ-ACK consecutive KOs before an Radio Link Failure is reported")
->capture_default_str();
app.add_option("--rv_sequence", pdsch_params.rv_sequence, "RV sequence for PUSCH. (e.g. [0 2 3 1]")
->capture_default_str()
->check(CLI::IsMember({0, 1, 2, 3}));
app.add_option_function<std::string>(
"--mcs_table",
[&pdsch_params](const std::string& value) {
if (value == "qam256") {
pdsch_params.mcs_table = pdsch_mcs_table::qam256;
}
},
"MCS table to use PDSCH")
->default_str("qam64")
->check(CLI::IsMember({"qam64", "qam256"}, CLI::ignore_case));
app.add_option("--min_rb_size", pdsch_params.min_rb_size, "Minimum RB size for UE PDSCH resource allocation")
->capture_default_str()
->check(CLI::Range(1U, (unsigned)MAX_NOF_PRBS));
app.add_option("--max_rb_size", pdsch_params.max_rb_size, "Maximum RB size for UE PDSCH resource allocation")
->capture_default_str()
->check(CLI::Range(1U, (unsigned)MAX_NOF_PRBS));
app.add_option("--max_pdschs_per_slot",
pdsch_params.max_pdschs_per_slot,
"Maximum number of PDSCH grants per slot, including SIB, RAR, Paging and UE data grants.")
->capture_default_str()
->check(CLI::Range(1U, (unsigned)MAX_PDSCH_PDUS_PER_SLOT));
app.add_option("--max_alloc_attempts",
pdsch_params.max_pdcch_alloc_attempts_per_slot,
"Maximum number of DL or UL PDCCH grant allocation attempts per slot before scheduler skips the slot")
->capture_default_str()
->check(CLI::Range(1U, (unsigned)std::max(MAX_DL_PDCCH_PDUS_PER_SLOT, MAX_UL_PDCCH_PDUS_PER_SLOT)));
app.add_option("--olla_cqi_inc_step",
pdsch_params.olla_cqi_inc,
"Outer-loop link adaptation (OLLA) increment value. The value 0 means that OLLA is disabled")
->capture_default_str()
->check(CLI::Range(0.0, 1.0));
app.add_option("--olla_target_bler",
pdsch_params.olla_target_bler,
"Target DL BLER set in Outer-loop link adaptation (OLLA) algorithm")
->capture_default_str()
->check(CLI::Range(0.0, 0.5));
app.add_option("--olla_max_cqi_offset",
pdsch_params.olla_max_cqi_offset,
"Maximum offset that the Outer-loop link adaptation (OLLA) can apply to CQI")
->capture_default_str()
->check(CLI::PositiveNumber);
app.add_option_function<std::string>(
"--dc_offset",
[&pdsch_params](const std::string& value) {
if (value == "undetermined") {
pdsch_params.dc_offset = dc_offset_t::undetermined;
} else if (value == "outside") {
pdsch_params.dc_offset = dc_offset_t::outside;
} else if (value == "center") {
pdsch_params.dc_offset = dc_offset_t::center;
} else {
pdsch_params.dc_offset = static_cast<dc_offset_t>(parse_int<int>(value).value());
}
},
"Direct Current (DC) Offset in number of subcarriers, using the common SCS as reference for carrier spacing, "
"and the center of the gNB DL carrier as DC offset value 0. The user can additionally set \"outside\" to "
"define that the DC offset falls outside the DL carrier or \"undetermined\" in the case the DC offset is "
"unknown.")
->capture_default_str()
->check(CLI::Range(static_cast<int>(dc_offset_t::min), static_cast<int>(dc_offset_t::max)) |
CLI::IsMember({"outside", "undetermined", "center"}));
app.add_option("--harq_la_cqi_drop_threshold",
pdsch_params.harq_la_cqi_drop_threshold,
"Link Adaptation (LA) threshold for drop in CQI of the first HARQ transmission above which HARQ "
"retransmissions are cancelled. Set this value to 0 to disable this feature")
->capture_default_str()
->check(CLI::Range(0, 15));
app.add_option("--harq_la_ri_drop_threshold",
pdsch_params.harq_la_ri_drop_threshold,
"Link Adaptation (LA) threshold for drop in nof. layers of the first HARQ transmission above which "
"HARQ retransmission is cancelled. Set this value to 0 to disable this feature")
->capture_default_str()
->check(CLI::Range(0, 4));
app.add_option("--dmrs_additional_position", pdsch_params.dmrs_add_pos, "PDSCH DMRS additional position")
->capture_default_str()
->check(CLI::Range(0, 3));
}
static void configure_cli11_pusch_args(CLI::App& app, pusch_appconfig& pusch_params)
{
app.add_option("--min_ue_mcs", pusch_params.min_ue_mcs, "Minimum UE MCS")
->capture_default_str()
->check(CLI::Range(0, 28));
app.add_option("--max_ue_mcs", pusch_params.max_ue_mcs, "Maximum UE MCS")
->capture_default_str()
->check(CLI::Range(0, 28));
app.add_option("--max_consecutive_kos",
pusch_params.max_consecutive_kos,
"Maximum number of CRC consecutive KOs before an Radio Link Failure is reported")
->capture_default_str();
app.add_option("--rv_sequence", pusch_params.rv_sequence, "RV sequence for PUSCH. (e.g. [0 2 3 1]")
->capture_default_str()
->check(CLI::IsMember({0, 1, 2, 3}));
app.add_option_function<std::string>(
"--mcs_table",
[&pusch_params](const std::string& value) {
if (value == "qam256") {
pusch_params.mcs_table = pusch_mcs_table::qam256;
}
},
"MCS table to use PUSCH")
->default_str("qam64")
->check(CLI::IsMember({"qam64", "qam256"}, CLI::ignore_case));
app.add_option("--msg3_delta_preamble",
pusch_params.msg3_delta_preamble,
"msg3-DeltaPreamble, Power offset between msg3 and RACH preamble transmission")
->capture_default_str()
->check(CLI::Range(-1, 6));
app.add_option("--p0_nominal_with_grant",
pusch_params.p0_nominal_with_grant,
"P0 value for PUSCH with grant (except msg3). Value in dBm. Valid values must be multiple of 2 and "
"within the [-202, 24] interval. Default: -76")
->capture_default_str()
->check([](const std::string& value) -> std::string {
std::stringstream ss(value);
int pw;
ss >> pw;
const std::string& error_message = "Must be a multiple of 2 and within the [-202, 24] interval";
if (pw < -202 or pw > 24 or pw % 2 != 0) {
return error_message;
}
return "";
});
app.add_option("--msg3_delta_power",
pusch_params.msg3_delta_power,
"Target power level at the network receiver side, in dBm. Valid values must be multiple of 2 and "
"within the [-6, 8] interval. Default: 8")
->capture_default_str()
->check([](const std::string& value) -> std::string {
std::stringstream ss(value);
int pw;
ss >> pw;
const std::string& error_message = "Must be a multiple of 2 and within the [-6, 8] interval";
if (pw < -6 or pw > 8 or pw % 2 != 0) {
return error_message;
}
return "";
});
app.add_option("--max_puschs_per_slot", pusch_params.max_puschs_per_slot, "Maximum number of PUSCH grants per slot")
->capture_default_str()
->check(CLI::Range(1U, (unsigned)MAX_PUSCH_PDUS_PER_SLOT));
app.add_option("--b_offset_ack_idx_1", pusch_params.b_offset_ack_idx_1, "betaOffsetACK-Index1 part of UCI-OnPUSCH")
->capture_default_str()
->check(CLI::Range(0, 31));
app.add_option("--b_offset_ack_idx_2", pusch_params.b_offset_ack_idx_2, "betaOffsetACK-Index2 part of UCI-OnPUSCH")
->capture_default_str()
->check(CLI::Range(0, 31));
app.add_option("--b_offset_ack_idx_3", pusch_params.b_offset_ack_idx_3, "betaOffsetACK-Index3 part of UCI-OnPUSCH")
->capture_default_str()
->check(CLI::Range(0, 31));
app.add_option(
"--beta_offset_csi_p1_idx_1", pusch_params.b_offset_csi_p1_idx_1, "b_offset_csi_p1_idx_1 part of UCI-OnPUSCH")
->capture_default_str()
->check(CLI::Range(0, 31));
app.add_option(
"--beta_offset_csi_p1_idx_2", pusch_params.b_offset_csi_p1_idx_2, "b_offset_csi_p1_idx_2 part of UCI-OnPUSCH")
->capture_default_str()
->check(CLI::Range(0, 31));
app.add_option(
"--beta_offset_csi_p2_idx_1", pusch_params.b_offset_csi_p2_idx_1, "b_offset_csi_p2_idx_1 part of UCI-OnPUSCH")
->capture_default_str()
->check(CLI::Range(0, 31));
app.add_option(
"--beta_offset_csi_p2_idx_2", pusch_params.b_offset_csi_p2_idx_2, "b_offset_csi_p2_idx_2 part of UCI-OnPUSCH")
->capture_default_str()
->check(CLI::Range(0, 31));
app.add_option("--min_k2", pusch_params.min_k2, "Minimum value of K2 (difference in slots between PDCCH and PUSCH).")
->capture_default_str()
->check(CLI::Range(1, 4));
app.add_option_function<std::string>(
"--dc_offset",
[&pusch_params](const std::string& value) {
if (value == "undetermined") {
pusch_params.dc_offset = dc_offset_t::undetermined;
} else if (value == "outside") {
pusch_params.dc_offset = dc_offset_t::outside;
} else {
pusch_params.dc_offset = static_cast<dc_offset_t>(parse_int<int>(value).value());
}
},
"Direct Current (DC) Offset in number of subcarriers, using the common SCS as reference for carrier spacing, "
"and the center of the gNB UL carrier as DC offset value 0. The user can additionally set \"outside\" to "
"define that the DC offset falls outside the UL carrier or \"undetermined\" in the case the DC offset is "
"unknown.")
->capture_default_str()
->check(CLI::Range(static_cast<int>(dc_offset_t::min), static_cast<int>(dc_offset_t::max)) |
CLI::IsMember({"outside", "undetermined"}));
app.add_option("--olla_snr_inc_step",
pusch_params.olla_snr_inc,
"Outer-loop link adaptation (OLLA) increment value. The value 0 means that OLLA is disabled")
->capture_default_str()
->check(CLI::Range(0.0, 1.0));
app.add_option("--olla_target_bler",
pusch_params.olla_target_bler,
"Target UL BLER set in Outer-loop link adaptation (OLLA) algorithm")
->capture_default_str()
->check(CLI::Range(0.0, 0.5));
app.add_option("--olla_max_snr_offset",
pusch_params.olla_max_snr_offset,
"Maximum offset that the Outer-loop link adaptation (OLLA) can apply to the estimated UL SINR")
->capture_default_str()
->check(CLI::PositiveNumber);
app.add_option("--dmrs_additional_position", pusch_params.dmrs_add_pos, "PUSCH DMRS additional position")
->capture_default_str()
->check(CLI::Range(0, 3));
}
static void configure_cli11_pucch_args(CLI::App& app, pucch_appconfig& pucch_params)
{
app.add_option(
"--p0_nominal",
pucch_params.p0_nominal,
"Power control parameter P0 for PUCCH transmissions. Value in dBm. Valid values must be multiple of 2 and "
"within the [-202, 24] interval. Default: -90")
->capture_default_str()
->check([](const std::string& value) -> std::string {
std::stringstream ss(value);
int pw;
ss >> pw;
const std::string& error_message = "Must be a multiple of 2 and within the [-202, 24] interval";
if (pw < -202 or pw > 24 or pw % 2 != 0) {
return error_message;
}
return "";
});
app.add_option("--sr_period_ms", pucch_params.sr_period_msec, "SR period in msec")
->capture_default_str()
->check(CLI::IsMember({1, 2, 4, 8, 10, 16, 20, 40, 80, 160, 320}));
app.add_option("--f1_nof_ue_res_harq",
pucch_params.nof_ue_pucch_f1_res_harq,
"Number of PUCCH F1 resources available per UE for HARQ")
->capture_default_str()
->check(CLI::Range(1, 8));
app.add_option("--f1_nof_cell_res_sr",
pucch_params.nof_cell_sr_resources,
"Number of PUCCH F1 resources available per cell for SR")
->capture_default_str()
->check(CLI::Range(1, 50));
app.add_option("--f1_nof_symbols", pucch_params.f1_nof_symbols, "Number of symbols for PUCCH F1 resources")
->capture_default_str()
->check(CLI::Range(4, 14));
app.add_option("--f1_enable_occ", pucch_params.f1_enable_occ, "Enable OCC for PUCCH F1")->capture_default_str();
app.add_option("--f1_nof_cyclic_shifts",
pucch_params.nof_cyclic_shift,
"Number of possible cyclic shifts available for PUCCH F1 resources")
->capture_default_str()
->check(CLI::IsMember({1, 2, 3, 4, 6, 12}));
app.add_option("--f1_intraslot_freq_hop",
pucch_params.f1_intraslot_freq_hopping,
"Enable intra-slot frequency hopping for PUCCH F1")
->capture_default_str();
app.add_option("--nof_cell_harq_pucch_res_sets",
pucch_params.nof_cell_harq_pucch_sets,
"Number of separate PUCCH resource sets for HARQ-ACK that are available in the cell. NOTE: the "
"higher the number of sets, the lower the chances UEs have to share the same PUCCH resources.")
->capture_default_str()
->check(CLI::Range(1, 10));
app.add_option("--f2_nof_ue_res_harq",
pucch_params.nof_ue_pucch_f2_res_harq,
"Number of PUCCH F2 resources available per UE for HARQ")
->capture_default_str()
->check(CLI::Range(1, 8));
app.add_option("--f2_nof_cell_res_csi",
pucch_params.nof_cell_csi_resources,
"Number of PUCCH F2 resources available per cell for CSI")
->capture_default_str()
->check(CLI::Range(0, 50));
app.add_option("--f2_nof_symbols", pucch_params.f2_nof_symbols, "Number of symbols for PUCCH F2 resources")
->capture_default_str()
->check(CLI::Range(1, 2));
app.add_option("--f2_max_nof_rbs", pucch_params.f2_max_nof_rbs, "Max number of RBs for PUCCH F2 resources")
->capture_default_str()
->check(CLI::Range(1, 16));
app.add_option("--f2_max_payload", pucch_params.max_payload_bits, "Max number payload bits for PUCCH F2 resources")
->check(CLI::Range(1, 11));
app.add_option_function<std::string>(
"--f2_max_code_rate",
[&pucch_params](const std::string& value) {
if (value == "dot08") {
pucch_params.max_code_rate = max_pucch_code_rate::dot_08;
} else if (value == "dot15") {
pucch_params.max_code_rate = max_pucch_code_rate::dot_15;
} else if (value == "dot25") {
pucch_params.max_code_rate = max_pucch_code_rate::dot_25;
} else if (value == "dot35") {
pucch_params.max_code_rate = max_pucch_code_rate::dot_35;
} else if (value == "dot45") {
pucch_params.max_code_rate = max_pucch_code_rate::dot_45;
} else if (value == "dot60") {
pucch_params.max_code_rate = max_pucch_code_rate::dot_60;
} else if (value == "dot80") {
pucch_params.max_code_rate = max_pucch_code_rate::dot_80;
}
},
"PUCCH F2 max code rate {dot08, dot15, dot25, dot35, dot45, dot60, dot80}. Default: dot35")
->check(CLI::IsMember({"dot08", "dot15", "dot25", "dot35", "dot45", "dot60", "dot80"}, CLI::ignore_case));
app.add_option("--f2_intraslot_freq_hop",
pucch_params.f2_intraslot_freq_hopping,
"Enable intra-slot frequency hopping for PUCCH F2")
->capture_default_str();
app.add_option("--min_k1",
pucch_params.min_k1,
"Minimum value of K1 (difference in slots between PDSCH and HARQ-ACK). Lower k1 values will reduce "
"latency, but place a stricter requirement on the UE decode latency.")
->capture_default_str()
->check(CLI::Range(1, 4));
app.add_option("--max_consecutive_kos",
pucch_params.max_consecutive_kos,
"Maximum number of consecutive undecoded PUCCH F2 for CSI before an Radio Link Failure is reported")
->capture_default_str();
}
static void configure_cli11_ul_common_args(CLI::App& app, ul_common_appconfig& ul_common_params)
{
app.add_option("--p_max", ul_common_params.p_max, "Maximum transmit power allowed in this serving cell")
->capture_default_str()
->check(CLI::Range(-30, 23));
app.add_option("--max_pucchs_per_slot",
ul_common_params.max_pucchs_per_slot,
"Maximum number of PUCCH grants that can be allocated per slot")
->capture_default_str()
->check(CLI::Range(1U, static_cast<unsigned>(MAX_PUCCH_PDUS_PER_SLOT)));
app.add_option("--max_ul_grants_per_slot",
ul_common_params.max_ul_grants_per_slot,
"Maximum number of UL grants that can be allocated per slot")
->capture_default_str()
->check(CLI::Range(1U, (unsigned)(MAX_PUSCH_PDUS_PER_SLOT + MAX_PUCCH_PDUS_PER_SLOT)));
}
static void configure_cli11_ssb_args(CLI::App& app, ssb_appconfig& ssb_params)
{
app.add_option("--ssb_period", ssb_params.ssb_period_msec, "Period of SSB scheduling in milliseconds")
->capture_default_str()
->check(CLI::IsMember({5, 10, 20}));
app.add_option("--ssb_block_power_dbm", ssb_params.ssb_block_power, "SS_PBCH_power_block in dBm")
->capture_default_str()
->check(CLI::Range(-60, 50));
app.add_option_function<unsigned>(
"--pss_to_sss_epre_db",
[&ssb_params](unsigned value) {
if (value == 0) {
ssb_params.pss_to_sss_epre = srsran::ssb_pss_to_sss_epre::dB_0;
} else if (value == 3) {
ssb_params.pss_to_sss_epre = srsran::ssb_pss_to_sss_epre::dB_3;
}
},
"SSB PSS to SSS EPRE ratio in dB {0, 3}")
->check(CLI::IsMember({0, 3}));
}
static void configure_cli11_si_sched_info(CLI::App& app, sib_appconfig::si_sched_info_config& si_sched_info)
{
app.add_option("--si_period", si_sched_info.si_period_rf, "SI message scheduling period in radio frames")
->capture_default_str()
->check(CLI::IsMember({8, 16, 32, 64, 128, 256, 512}));
app.add_option("--sib_mapping",
si_sched_info.sib_mapping_info,
"Mapping of SIB types to SI-messages. SIB numbers should not be repeated")
->capture_default_str()
->check(CLI::IsMember({2, 19}));
}
static void configure_cli11_epoch_time(CLI::App& app, epoch_time_t& epoch_time)
{
app.add_option("--sfn", epoch_time.sfn, "SFN Part")->capture_default_str()->check(CLI::Range(0, 1023));
app.add_option("--subframe_number", epoch_time.subframe_number, "Sub-frame number Part")
->capture_default_str()
->check(CLI::Range(0, 9));
}
static void configure_cli11_ephemeris_info_ecef(CLI::App& app, ecef_coordinates_t& ephemeris_info)
{
app.add_option("--pos_x", ephemeris_info.position_x, "X Position of the satellite")
->capture_default_str()
->check(CLI::Range(-67108864, 67108863));
app.add_option("--pos_y", ephemeris_info.position_y, "Y Position of the satellite")
->capture_default_str()
->check(CLI::Range(-67108864, 67108863));
app.add_option("--pos_z", ephemeris_info.position_z, "Z Position of the satellite")
->capture_default_str()
->check(CLI::Range(-67108864, 67108863));
app.add_option("--vel_x", ephemeris_info.velocity_vx, "X Velocity of the satellite")